26struct BundleSocketValue;
27using BundleSocketValuePtr = std::shared_ptr<BundleSocketValue>;
29struct FallbackValue {};
32struct DanglingValue {};
35 bNode *node =
nullptr;
39struct PrimitiveSocketValue {
40 std::variant<int, float, bool, ColorGeometry4f, float3, MenuValue> value;
42 const void *buffer()
const
44 return std::visit([](
auto &&value) ->
const void * {
return &value; }, value);
49 return const_cast<void *
>(
const_cast<const PrimitiveSocketValue *
>(
this)->buffer());
52 static PrimitiveSocketValue from_value(
const GPointer value)
54 const CPPType &type = *value.
type();
56 return {*
static_cast<const int *
>(value.get())};
58 if (type.
is<
float>()) {
59 return {*
static_cast<const float *
>(value.get())};
61 if (type.
is<
bool>()) {
62 return {*
static_cast<const bool *
>(value.get())};
68 return {*
static_cast<const float3 *
>(value.get())};
70 if (type.
is<MenuValue>()) {
71 return {*
static_cast<const MenuValue *
>(value.get())};
79struct LinkedSocketValue {
80 bNode *node =
nullptr;
85struct InputSocketValue {
89struct ClosureZoneValue {
90 const bke::bNodeTreeZone *zone =
nullptr;
91 const ComputeContext *closure_creation_context =
nullptr;
100 std::variant<FallbackValue,
104 PrimitiveSocketValue,
106 BundleSocketValuePtr>
110 std::optional<PrimitiveSocketValue> to_primitive(
const bke::bNodeSocketType &type)
const
112 if (
const auto *primitive_value = std::get_if<PrimitiveSocketValue>(&this->value)) {
113 return *primitive_value;
115 if (
const auto *input_socket_value = std::get_if<InputSocketValue>(&this->value)) {
116 const bNodeSocket &socket = *input_socket_value->socket;
118 if (!socket.
runtime->declaration) {
130 return PrimitiveSocketValue{
133 return PrimitiveSocketValue{
136 return PrimitiveSocketValue{
139 return PrimitiveSocketValue{
145 if (std::get_if<FallbackValue>(&this->value)) {
152 return PrimitiveSocketValue::from_value(
153 {type.base_cpp_type, type.base_cpp_type->default_value()});
162struct BundleSocketValue {
166 const bke::bNodeSocketType *socket_type =
nullptr;
172struct PreservedZone {
173 bNode *input_node =
nullptr;
174 bNode *output_node =
nullptr;
177class ShaderNodesInliner {
180 ResourceScope scope_;
186 InlineShaderNodeTreeParams ¶ms_;
188 bke::ComputeContextCache compute_context_cache_;
193 Map<const ComputeContext *, const ComputeContext *> parent_zone_contexts_;
195 Map<SocketInContext, SocketValue> value_by_socket_;
200 Map<NodeInContext, PreservedZone> copied_zone_by_zone_output_node_;
202 Stack<SocketInContext> scheduled_sockets_stack_;
204 const bke::DataTypeConversions &data_type_conversions_;
206 int dst_node_counter_ = 0;
209 ShaderNodesInliner(
const bNodeTree &src_tree,
211 InlineShaderNodeTreeParams &
params)
212 : src_tree_(src_tree),
221 src_tree_.ensure_topology_cache();
222 if (src_tree_.has_available_link_cycle()) {
226 const Vector<SocketInContext> final_output_sockets = this->find_final_output_sockets();
230 for (
const SocketInContext &socket : final_output_sockets) {
231 this->schedule_socket(socket);
239 while (!scheduled_sockets_stack_.is_empty()) {
240 const SocketInContext socket = scheduled_sockets_stack_.peek();
241 const int old_stack_size = scheduled_sockets_stack_.size();
243 this->handle_socket(socket);
245 if (scheduled_sockets_stack_.size() == old_stack_size) {
248 BLI_assert(socket == scheduled_sockets_stack_.peek());
249 scheduled_sockets_stack_.pop();
254 Map<NodeInContext, bNode *> final_output_nodes;
255 for (
const SocketInContext &socket : final_output_sockets) {
256 const NodeInContext src_node = socket.owner_node();
258 Map<const bNodeSocket *, bNodeSocket *> socket_map;
261 this->node_copy_flag(),
263 this->get_next_node_identifier(),
265 copied_node->
parent =
nullptr;
270 this->set_input_socket_value(
271 *src_node, *copied_node, *copied_socket, value_by_socket_.lookup(socket));
274 this->restore_zones_in_output_tree();
275 this->position_nodes_in_output_tree();
279 Vector<SocketInContext> find_final_output_sockets()
281 Vector<TreeInContext> trees;
282 this->find_trees_potentially_containing_shader_outputs_recursive(
nullptr, src_tree_, trees);
284 Vector<SocketInContext> output_sockets;
285 auto add_output_type = [&](
const char *output_type) {
286 for (
const TreeInContext &
tree : trees) {
287 const bke::bNodeTreeZones &zones = *
tree->zones();
288 for (
const bNode *node :
tree->nodes_by_type(output_type)) {
289 const bke::bNodeTreeZone *zone = zones.get_zone_by_node(node->identifier);
291 params_.r_error_messages.append({node,
TIP_(
"Output node must not be in zone")});
294 for (
const bNodeSocket *socket : node->input_sockets()) {
295 output_sockets.
append({
tree.context, socket});
302 ID_Type tree_type = src_tree_.owner_id ?
GS(src_tree_.owner_id->name) :
ID_MA;
306 add_output_type(
"ShaderNodeOutputMaterial");
307 add_output_type(
"ShaderNodeOutputAOV");
308 add_output_type(
"ShaderNodeOutputLight");
311 add_output_type(
"ShaderNodeOutputWorld");
312 add_output_type(
"ShaderNodeOutputAOV");
315 add_output_type(
"ShaderNodeOutputLight");
321 return output_sockets;
324 void find_trees_potentially_containing_shader_outputs_recursive(
const ComputeContext *context,
326 Vector<TreeInContext> &r_trees)
328 const bke::bNodeTreeZones *zones = src_tree_.zones();
332 if (
tree.has_available_link_cycle()) {
336 for (
const bNode *group_node :
tree.group_nodes()) {
337 if (group_node->is_muted()) {
340 const bNodeTree *group = id_cast<const bNodeTree *>(group_node->id);
344 group->ensure_topology_cache();
345 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(group_node->identifier);
350 const ComputeContext &group_context = compute_context_cache_.for_group_node(
351 context, group_node->identifier, &
tree);
352 this->find_trees_potentially_containing_shader_outputs_recursive(
353 &group_context, *group, r_trees);
357 void handle_socket(
const SocketInContext &socket)
359 if (!socket->is_available()) {
362 if (value_by_socket_.contains(socket)) {
366 if (socket->is_input()) {
367 this->handle_input_socket(socket);
370 this->handle_output_socket(socket);
374 void handle_input_socket(
const SocketInContext &socket)
380 for (
const bNodeLink *link : socket->directly_linked_links()) {
381 if (!link->is_used()) {
388 if (this->input_socket_may_have_dangling_value(socket)) {
389 this->store_socket_value(socket, {DanglingValue{}});
392 this->store_socket_value(socket, {InputSocketValue{socket.socket}});
397 const ComputeContext *
from_context = this->get_link_source_context(*used_link, socket);
399 if (
const auto *value = value_by_socket_.lookup_ptr(origin_socket)) {
400 if (std::holds_alternative<DanglingValue>(value->value)) {
401 if (this->input_socket_may_have_dangling_value(socket)) {
402 this->store_socket_value(socket, {DanglingValue{}});
406 this->store_socket_value(socket, {InputSocketValue{socket.socket}});
412 this->store_socket_value(socket,
413 this->handle_implicit_conversion(*value,
419 this->schedule_socket(origin_socket);
427 bool input_socket_may_have_dangling_value(
const SocketInContext &socket)
430 const NodeInContext node = socket.owner_node();
431 return node->is_reroute() || node->is_muted();
434 const ComputeContext *get_link_source_context(
const bNodeLink &link,
435 const SocketInContext &to_socket)
438 const bke::bNodeTreeZones *zones =
tree.zones();
442 const bke::bNodeTreeZone *to_zone = zones->get_zone_by_socket(*to_socket);
443 const bke::bNodeTreeZone *from_zone = zones->get_zone_by_socket(*link.
fromsock);
444 const ComputeContext *
context = to_socket.context;
445 for (
const bke::bNodeTreeZone *zone = to_zone; zone != from_zone; zone = zone->parent_zone) {
446 const bNode &zone_output_node = *zone->output_node();
447 if (zone_output_node.is_type(
"GeometryNodeRepeatOutput")) {
448 if (this->should_preserve_repeat_zone_node(zone_output_node)) {
453 context = parent_zone_contexts_.lookup(context);
458 void handle_output_socket(
const SocketInContext &socket)
460 const NodeInContext node = socket.owner_node();
461 if (node->is_reroute()) {
462 this->handle_output_socket__reroute(socket);
465 if (node->is_muted()) {
466 if (!this->handle_output_socket__internal_links(socket)) {
468 this->store_socket_value_dangling(socket);
472 if (node->is_group()) {
473 this->handle_output_socket__group(socket);
476 if (node->is_group_input()) {
477 this->handle_output_socket__group_input(socket);
480 if (node->is_type(
"GeometryNodeRepeatOutput")) {
481 if (this->should_preserve_repeat_zone_node(*node)) {
482 this->handle_output_socket__preserved_repeat_output(socket);
485 this->handle_output_socket__repeat_output(socket);
488 if (node->is_type(
"GeometryNodeRepeatInput")) {
489 if (this->should_preserve_repeat_zone_node(*node)) {
490 this->handle_output_socket__preserved_repeat_input(socket);
493 this->handle_output_socket__repeat_input(socket);
496 if (node->is_type(
"NodeClosureOutput")) {
497 this->handle_output_socket__closure_output(socket);
500 if (node->is_type(
"NodeClosureInput")) {
501 this->handle_output_socket__closure_input(socket);
504 if (node->is_type(
"NodeEvaluateClosure")) {
505 this->handle_output_socket__evaluate_closure(socket);
508 if (node->is_type(
"NodeCombineBundle")) {
509 this->handle_output_socket__combine_bundle(socket);
512 if (node->is_type(
"NodeSeparateBundle")) {
513 this->handle_output_socket__separate_bundle(socket);
516 if (node->is_type(
"GeometryNodeMenuSwitch")) {
517 this->handle_output_socket__menu_switch(socket);
520 this->handle_output_socket__eval(socket);
523 void handle_output_socket__reroute(
const SocketInContext &socket)
525 const NodeInContext node = socket.owner_node();
526 const SocketInContext input_socket = node.input_socket(0);
527 this->forward_value_or_schedule(socket, input_socket);
531 [[nodiscard]]
bool handle_output_socket__internal_links(
const SocketInContext &socket)
533 const NodeInContext node = socket.owner_node();
534 for (
const bNodeLink &internal_link : node->internal_links()) {
535 if (internal_link.tosock == socket.socket) {
536 const SocketInContext src_socket = {socket.context, internal_link.fromsock};
537 if (
const SocketValue *value = value_by_socket_.lookup_ptr(src_socket)) {
540 this->store_socket_value(
542 this->handle_implicit_conversion(
543 *value, *internal_link.fromsock->typeinfo, *internal_link.tosock->typeinfo));
546 this->schedule_socket(src_socket);
553 void handle_output_socket__group(
const SocketInContext &socket)
555 const NodeInContext node = socket.owner_node();
558 this->store_socket_value_fallback(socket);
561 group->ensure_interface_cache();
562 group->ensure_topology_cache();
563 const bNode *group_output_node = group->group_output_node();
564 if (!group_output_node) {
565 this->store_socket_value_fallback(socket);
570 const ComputeContext &group_compute_context = compute_context_cache_.for_group_node(
571 socket.context, node->identifier, &node->owner_tree());
572 const SocketInContext group_output_socket_ctx = {
573 &group_compute_context, &group_output_node->input_socket(socket->index())};
574 this->forward_value_or_schedule(socket, group_output_socket_ctx);
577 void handle_output_socket__group_input(
const SocketInContext &socket)
579 if (
const auto *group_node_compute_context =
580 dynamic_cast<const bke::GroupNodeComputeContext *
>(socket.context))
584 const ComputeContext *parent_compute_context = group_node_compute_context->parent();
585 const bNode *group_node = group_node_compute_context->node();
587 const bNodeSocket &group_node_input = group_node->input_socket(socket->index());
588 const SocketInContext group_input_socket_ctx = {parent_compute_context, &group_node_input};
589 this->forward_value_or_schedule(socket, group_input_socket_ctx);
592 this->store_socket_value_fallback(socket);
595 bool should_preserve_repeat_zone_node(
const bNode &repeat_zone_node)
const
597 BLI_assert(repeat_zone_node.is_type(
"GeometryNodeRepeatOutput") ||
598 repeat_zone_node.is_type(
"GeometryNodeRepeatInput"));
599 if (!params_.allow_preserving_repeat_zones) {
603 const bke::bNodeTreeZones *zones =
tree.zones();
607 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(repeat_zone_node.
identifier);
611 const bNode *repeat_zone_input_node = zone->input_node();
612 const bNode *repeat_zone_output_node = zone->output_node();
613 if (!repeat_zone_input_node || !repeat_zone_output_node) {
617 repeat_zone_output_node->
storage);
618 for (
const int i : IndexRange(storage.items_num)) {
628 void handle_output_socket__repeat_output(
const SocketInContext &socket)
630 const bNode &repeat_output_node = socket->owner_node();
633 const bke::bNodeTreeZones *zones =
tree.zones();
635 this->store_socket_value_fallback(socket);
638 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(repeat_output_node.
identifier);
640 this->store_socket_value_fallback(socket);
643 const NodeInContext repeat_input_node = {socket.context, zone->input_node()};
644 const SocketInContext iterations_input = repeat_input_node.input_socket(0);
645 const SocketValue *iterations_socket_value = value_by_socket_.lookup_ptr(iterations_input);
646 if (!iterations_socket_value) {
648 this->schedule_socket(iterations_input);
651 const std::optional<PrimitiveSocketValue> iterations_value_opt =
652 iterations_socket_value->to_primitive(*iterations_input->typeinfo);
653 if (!iterations_value_opt) {
654 this->add_dynamic_repeat_zone_iterations_error(*repeat_input_node);
656 const int iterations = iterations_value_opt.has_value() ?
657 std::get<int>(iterations_value_opt->value) :
659 if (iterations <= 0) {
662 const SocketInContext origin_socket = repeat_input_node.input_socket(1 + socket->index());
663 this->forward_value_or_schedule(socket, origin_socket);
667 const ComputeContext &last_iteration_context = compute_context_cache_.for_repeat_zone(
668 socket.context, repeat_output_node, iterations - 1);
669 parent_zone_contexts_.add(&last_iteration_context, socket.context);
670 const SocketInContext origin_socket = {&last_iteration_context,
671 &repeat_output_node.input_socket(socket->index())};
672 this->forward_value_or_schedule(socket, origin_socket);
675 void handle_output_socket__preserved_repeat_output(
const SocketInContext &socket)
678 const NodeInContext repeat_output_node = socket.owner_node();
679 const bke::bNodeTreeZones &zones = *
tree.zones();
680 const bke::bNodeTreeZone &zone = *zones.get_zone_by_node(repeat_output_node->identifier);
681 const bNode &repeat_input_node = *zone.input_node();
683 const EnsureInputsResult ensured_inputs = this->ensure_node_inputs(socket.owner_node());
684 if (ensured_inputs.has_missing_inputs) {
688 const NodeInContext node = socket.owner_node();
689 bNode &copied_node = this->handle_output_socket__eval_copy_node(node);
690 PreservedZone &preserved_zone = copied_zone_by_zone_output_node_.lookup_or_add_default(
692 preserved_zone.output_node = &copied_node;
694 this->schedule_socket({node.context, &repeat_input_node.output_socket(0)});
697 void handle_output_socket__preserved_repeat_input(
const SocketInContext &socket)
699 const EnsureInputsResult ensured_inputs = this->ensure_node_inputs(socket.owner_node());
700 if (ensured_inputs.has_missing_inputs) {
705 const NodeInContext node = socket.owner_node();
706 bNode &copied_node = this->handle_output_socket__eval_copy_node(node);
708 const NodeInContext repeat_output_node{node.context,
tree.node_by_id(storage.output_node_id)};
709 PreservedZone &preserved_zone = copied_zone_by_zone_output_node_.lookup_or_add_default(
711 preserved_zone.input_node = &copied_node;
714 void add_dynamic_repeat_zone_iterations_error(
const bNode &repeat_input_node)
716 params_.r_error_messages.append(
717 {&repeat_input_node,
TIP_(
"Iterations input has to be a constant value")});
720 void handle_output_socket__repeat_input(
const SocketInContext &socket)
722 const bNode &repeat_input_node = socket->owner_node();
723 const auto *repeat_zone_context =
dynamic_cast<const bke::RepeatZoneComputeContext *
>(
725 if (!repeat_zone_context) {
726 this->store_socket_value_fallback(socket);
730 const int iteration = repeat_zone_context->iteration();
732 if (socket->index() == 0) {
734 this->store_socket_value(socket, {PrimitiveSocketValue{iteration}});
738 if (iteration == 0) {
740 const SocketInContext origin_socket = {repeat_zone_context->parent(),
741 &repeat_input_node.input_socket(socket->index())};
742 this->forward_value_or_schedule(socket, origin_socket);
747 const bNode &repeat_output_node = *repeat_input_node.owner_tree().node_by_id(
748 repeat_zone_context->output_node_id());
749 const int previous_iteration = iteration - 1;
750 const ComputeContext &previous_iteration_context = compute_context_cache_.for_repeat_zone(
751 repeat_zone_context->parent(), repeat_output_node, previous_iteration);
752 parent_zone_contexts_.add(&previous_iteration_context, repeat_zone_context->parent());
753 const SocketInContext origin_socket = {&previous_iteration_context,
754 &repeat_output_node.input_socket(socket->index() - 1)};
755 this->forward_value_or_schedule(socket, origin_socket);
758 void handle_output_socket__closure_output(
const SocketInContext &socket)
760 const bNode &node = socket->owner_node();
761 const bke::bNodeTreeZones *zones = node.owner_tree().zones();
763 this->store_socket_value_fallback(socket);
766 const bke::bNodeTreeZone *zone = zones->get_zone_by_node(node.
identifier);
768 this->store_socket_value_fallback(socket);
772 this->store_socket_value(socket, {ClosureZoneValue{zone, socket.context}});
775 void handle_output_socket__evaluate_closure(
const SocketInContext &socket)
777 const NodeInContext evaluate_closure_node = socket.owner_node();
778 const SocketInContext closure_input_socket = evaluate_closure_node.input_socket(0);
779 const SocketValue *closure_input_value = value_by_socket_.lookup_ptr(closure_input_socket);
780 if (!closure_input_value) {
783 this->schedule_socket(closure_input_socket);
786 const ClosureZoneValue *closure_zone_value = std::get_if<ClosureZoneValue>(
787 &closure_input_value->value);
788 if (!closure_zone_value) {
790 if (!this->handle_output_socket__internal_links(socket)) {
791 this->store_socket_value_fallback(socket);
796 evaluate_closure_node->storage);
797 const bNode &closure_output_node = *closure_zone_value->zone->output_node();
802 const ClosureSourceLocation closure_source_location{
803 &closure_output_node.owner_tree(),
805 closure_zone_value->closure_creation_context ?
806 closure_zone_value->closure_creation_context->hash() :
807 ComputeContextHash{},
808 closure_zone_value->closure_creation_context};
809 const bke::EvaluateClosureComputeContext &closure_eval_context =
810 compute_context_cache_.for_evaluate_closure(socket.context,
811 evaluate_closure_node->identifier,
812 &socket->owner_tree(),
813 closure_source_location);
814 parent_zone_contexts_.add(&closure_eval_context, closure_zone_value->closure_creation_context);
816 if (closure_eval_context.is_recursive()) {
817 this->store_socket_value_fallback(socket);
818 params_.r_error_messages.append(
819 {&*evaluate_closure_node,
TIP_(
"Recursive closures are not supported")});
823 for (
const int i : IndexRange(closure_storage.output_items.items_num)) {
825 if (key != item.
name) {
829 const SocketInContext origin_socket = {&closure_eval_context,
830 &closure_output_node.input_socket(
i)};
831 this->forward_value_or_schedule(socket, origin_socket);
834 this->store_socket_value_fallback(socket);
837 void handle_output_socket__closure_input(
const SocketInContext &socket)
839 const bNode &closure_input_node = socket->owner_node();
840 const auto *closure_eval_context =
dynamic_cast<const bke::EvaluateClosureComputeContext *
>(
842 if (!closure_eval_context) {
843 this->store_socket_value_fallback(socket);
846 const bNode &closure_output_node = *closure_input_node.owner_tree().node_by_id(
847 closure_eval_context->closure_source_location()->closure_output_node_id);
848 const NodeInContext closure_eval_node = {closure_eval_context->parent(),
849 closure_eval_context->node()};
854 closure_eval_node->storage);
856 const StringRef key = closure_storage.input_items.items[socket->index()].name;
857 for (
const int i : IndexRange(eval_closure_storage.input_items.items_num)) {
859 if (key != item.
name) {
864 const SocketInContext origin_socket = closure_eval_node.input_socket(
i + 1);
865 this->forward_value_or_schedule(socket, origin_socket);
868 this->store_socket_value_fallback(socket);
871 void handle_output_socket__combine_bundle(
const SocketInContext &socket)
873 const NodeInContext node = socket.owner_node();
876 bool all_inputs_available =
true;
877 for (
const bNodeSocket *input_socket : node->input_sockets()) {
878 const SocketInContext input_socket_ctx = {socket.context, input_socket};
879 if (!value_by_socket_.lookup_ptr(input_socket_ctx)) {
880 this->schedule_socket(input_socket_ctx);
881 all_inputs_available =
false;
884 if (!all_inputs_available) {
889 auto bundle_value = std::make_shared<BundleSocketValue>();
890 for (
const int i : IndexRange(storage.items_num)) {
891 const SocketInContext input_socket = node.input_socket(
i);
893 const StringRef key = item.
name;
894 const auto &socket_value = value_by_socket_.lookup(input_socket);
895 bundle_value->items.append({key, socket_value, input_socket->typeinfo});
897 this->store_socket_value(socket, {bundle_value});
900 void handle_output_socket__separate_bundle(
const SocketInContext &socket)
902 const NodeInContext node = socket.owner_node();
905 const SocketInContext input_socket = node.input_socket(0);
906 const SocketValue *socket_value = value_by_socket_.lookup_ptr(input_socket);
909 this->schedule_socket(input_socket);
912 const auto *bundle_value_ptr = std::get_if<BundleSocketValuePtr>(&socket_value->value);
913 if (!bundle_value_ptr) {
915 this->store_socket_value_fallback(socket);
918 const BundleSocketValue &bundle_value = **bundle_value_ptr;
920 const StringRef key = storage.items[socket->index()].name;
921 for (
const BundleSocketValue::Item &item : bundle_value.items) {
922 if (key != item.key) {
926 const SocketValue converted_value = this->handle_implicit_conversion(
927 item.value, *item.socket_type, *socket->typeinfo);
928 this->store_socket_value(socket, converted_value);
932 this->store_socket_value_fallback(socket);
935 void handle_output_socket__menu_switch(
const SocketInContext &socket)
937 const NodeInContext node = socket.owner_node();
938 const auto &storage = *
static_cast<const NodeMenuSwitch *
>(node->storage);
940 const SocketInContext menu_input = node.input_socket(0);
941 const SocketValue *menu_socket_value = value_by_socket_.lookup_ptr(menu_input);
942 if (!menu_socket_value) {
944 this->schedule_socket(menu_input);
948 const std::optional<PrimitiveSocketValue> menu_value_opt = menu_socket_value->to_primitive(
949 *menu_input->typeinfo);
950 if (!menu_value_opt) {
953 this->store_socket_value_fallback(socket);
954 params_.r_error_messages.append({node.node,
TIP_(
"Menu value has to be a constant value")});
957 const MenuValue menu_value = std::get<MenuValue>(menu_value_opt->value);
959 std::optional<int> selected_index;
960 for (
const int item_i : IndexRange(storage.enum_definition.items_num)) {
961 const NodeEnumItem &item = storage.enum_definition.items_array[item_i];
962 if (MenuValue(item.
identifier) == menu_value) {
963 selected_index = item_i;
967 if (!selected_index.has_value()) {
969 this->store_socket_value_fallback(socket);
972 if (socket->index() == 0) {
974 this->forward_value_or_schedule(socket, node.input_socket(*selected_index + 1));
978 const bool is_selected = selected_index == socket->index() - 1;
979 this->store_socket_value(socket, {PrimitiveSocketValue{is_selected}});
986 void handle_output_socket__eval(
const SocketInContext &socket)
988 const NodeInContext node = socket.owner_node();
989 const EnsureInputsResult ensured_inputs = this->ensure_node_inputs(node);
990 if (ensured_inputs.has_missing_inputs) {
994 const bke::bNodeType &node_type = *node->typeinfo;
995 if (node_type.build_multi_function && ensured_inputs.all_inputs_primitive) {
997 this->handle_output_socket__eval_multi_function(node);
1001 this->handle_output_socket__eval_copy_node(node);
1004 struct EnsureInputsResult {
1005 bool has_missing_inputs =
false;
1006 bool all_inputs_primitive =
false;
1009 EnsureInputsResult ensure_node_inputs(
const NodeInContext &node)
1011 EnsureInputsResult
result;
1012 result.has_missing_inputs =
false;
1013 result.all_inputs_primitive =
true;
1014 for (
const bNodeSocket *input_socket : node->input_sockets()) {
1015 if (!input_socket->is_available()) {
1018 const SocketInContext input_socket_ctx = {node.context, input_socket};
1019 const SocketValue *value = value_by_socket_.lookup_ptr(input_socket_ctx);
1021 this->schedule_socket(input_socket_ctx);
1022 result.has_missing_inputs =
true;
1025 if (!value->to_primitive(*input_socket->typeinfo)) {
1026 result.all_inputs_primitive =
false;
1032 void handle_output_socket__eval_multi_function(
const NodeInContext &node)
1034 NodeMultiFunctionBuilder builder{*node.node, node->owner_tree()};
1035 node->typeinfo->build_multi_function(builder);
1036 const mf::MultiFunction &fn = builder.function();
1042 for (
const bNodeSocket *input_socket : node->input_sockets()) {
1043 if (!input_socket->is_available()) {
1046 const SocketInContext input_socket_ctx = {node.context, input_socket};
1047 const PrimitiveSocketValue value =
1048 *value_by_socket_.lookup(input_socket_ctx).to_primitive(*input_socket->typeinfo);
1049 params.add_readonly_single_input(
1054 Vector<void *> output_values;
1055 for (
const bNodeSocket *output_socket : node->output_sockets()) {
1056 if (!output_socket->is_available()) {
1059 void *value = scope_.allocate_owned(*output_socket->typeinfo->base_cpp_type);
1060 output_values.
append(value);
1061 params.add_uninitialized_single_output(
1062 GMutableSpan(output_socket->typeinfo->base_cpp_type, value, 1));
1068 int current_output_i = 0;
1069 for (
const bNodeSocket *output_socket : node->output_sockets()) {
1070 if (!output_socket->is_available()) {
1073 const void *value = output_values[current_output_i++];
1074 this->store_socket_value(
1075 {node.context, output_socket},
1076 {PrimitiveSocketValue::from_value({output_socket->typeinfo->base_cpp_type, value})});
1080 bNode &handle_output_socket__eval_copy_node(
const NodeInContext &node)
1082 Map<const bNodeSocket *, bNodeSocket *> socket_map;
1085 const int identifier = this->get_next_node_identifier();
1086 const std::string
unique_name = fmt::format(
"{}_{}", identifier, node.node->name);
1090 this->node_copy_flag(),
1097 copied_node.
parent =
nullptr;
1100 for (
const bNodeSocket *src_input_socket : node->input_sockets()) {
1101 if (!src_input_socket->is_available()) {
1105 const SocketInContext input_socket_ctx = {node.context, src_input_socket};
1106 const SocketValue &value = value_by_socket_.lookup(input_socket_ctx);
1107 this->set_input_socket_value(*node, copied_node, dst_input_socket, value);
1109 for (
const bNodeSocket *src_output_socket : node->output_sockets()) {
1110 if (!src_output_socket->is_available()) {
1114 const SocketInContext output_socket_ctx = {node.context, src_output_socket};
1115 this->store_socket_value(output_socket_ctx,
1116 {LinkedSocketValue{&copied_node, &dst_output_socket}});
1122 SocketValue handle_implicit_conversion(
const SocketValue &src_value,
1123 const bke::bNodeSocketType &from_socket_type,
1124 const bke::bNodeSocketType &to_socket_type)
1126 if (from_socket_type.type == to_socket_type.type) {
1129 if (std::get_if<LinkedSocketValue>(&src_value.value)) {
1132 if (std::get_if<DanglingValue>(&src_value.value)) {
1135 const std::optional<PrimitiveSocketValue> src_primitive_value = src_value.to_primitive(
1137 if (src_primitive_value && to_socket_type.base_cpp_type) {
1138 if (data_type_conversions_.is_convertible(*from_socket_type.base_cpp_type,
1139 *to_socket_type.base_cpp_type))
1141 const void *src_buffer = src_primitive_value->buffer();
1143 data_type_conversions_.convert_to_uninitialized(*from_socket_type.base_cpp_type,
1144 *to_socket_type.base_cpp_type,
1148 PrimitiveSocketValue::from_value(GPointer{to_socket_type.base_cpp_type, dst_buffer})};
1151 if (src_primitive_value && to_socket_type.type ==
SOCK_SHADER) {
1154 const void *src_buffer = src_primitive_value->buffer();
1156 data_type_conversions_.convert_to_uninitialized(
1161 socket_storage->value[3] = 1.0f;
1162 return {LinkedSocketValue{color_node, output_socket}};
1165 return SocketValue{FallbackValue{}};
1168 void set_input_socket_value(
const bNode &original_node,
1171 const SocketValue &value)
1175 if (
const auto *input_socket_value = std::get_if<InputSocketValue>(&value.value)) {
1182 if (
const std::optional<PrimitiveSocketValue> primitive_value = value.to_primitive(
1188 const NodeAndSocket node_and_socket = this->primitive_value_to_output_socket(
1190 if (dst_tree_.typeinfo->validate_link(node_and_socket.socket->typeinfo->type,
1194 dst_tree_, *node_and_socket.node, *node_and_socket.socket, dst_node, dst_socket);
1198 this->set_primitive_value_on_socket(dst_socket, *primitive_value);
1202 if (!params_.allow_preserving_repeat_zones) {
1203 const bool is_iterations_input = dst_node.
inputs.
first == &dst_socket &&
1204 dst_node.is_type(
"GeometryNodeRepeatInput");
1205 if (is_iterations_input) {
1206 this->add_dynamic_repeat_zone_iterations_error(original_node);
1207 this->set_primitive_value_on_socket(dst_socket, PrimitiveSocketValue{0});
1211 if (std::get_if<InputSocketValue>(&value.value)) {
1215 if (std::get_if<FallbackValue>(&value.value)) {
1219 if (std::get_if<DanglingValue>(&value.value)) {
1225 if (std::get_if<BundleSocketValuePtr>(&value.value)) {
1230 if (std::get_if<ClosureZoneValue>(&value.value)) {
1235 if (
const auto *src_socket_value = std::get_if<LinkedSocketValue>(&value.value)) {
1236 if (dst_tree_.typeinfo->validate_link(src_socket_value->socket->typeinfo->type,
1240 dst_tree_, *src_socket_value->node, *src_socket_value->socket, dst_node, dst_socket);
1247 NodeAndSocket primitive_value_to_output_socket(
const PrimitiveSocketValue &value)
1249 if (
const float *value_float = std::get_if<float>(&value.value)) {
1253 return {node, socket};
1255 if (
const int *value_int = std::get_if<int>(&value.value)) {
1259 return {node, socket};
1261 if (
const bool *value_bool = std::get_if<bool>(&value.value)) {
1265 return {node, socket};
1267 if (
const float3 *value_float3 = std::get_if<float3>(&value.value)) {
1276 return {node, output_socket};
1278 if (
const ColorGeometry4f *value_color = std::get_if<ColorGeometry4f>(&value.value)) {
1282 copy_v3_v3(socket_storage->value, *value_color);
1283 socket_storage->value[3] = 1.0f;
1284 return {node, output_socket};
1292 return bke::node_add_node(
nullptr, dst_tree_, idname, this->get_next_node_identifier());
1295 int get_next_node_identifier()
1297 return ++dst_node_counter_;
1300 void set_primitive_value_on_socket(
bNodeSocket &socket,
const PrimitiveSocketValue &value)
1302 switch (socket.
type) {
1317 std::get<float3>(value.value));
1322 std::get<ColorGeometry4f>(value.value));
1332 void restore_zones_in_output_tree()
1334 for (
const PreservedZone &copied_zone : copied_zone_by_zone_output_node_.values()) {
1335 if (!copied_zone.input_node || !copied_zone.output_node) {
1339 copied_zone.input_node->type_legacy);
1343 int &output_id = zone_type->get_corresponding_output_id(*copied_zone.input_node);
1344 output_id = copied_zone.output_node->identifier;
1348 void position_nodes_in_output_tree()
1351 tree.ensure_topology_cache();
1353 Map<int, int> num_by_depth;
1354 Map<bNode *, int> depth_by_node;
1358 for (
bNode *node :
tree.toposort_right_to_left()) {
1360 for (
bNodeSocket *socket : node->output_sockets()) {
1361 for (
bNodeSocket *target : socket->directly_linked_sockets()) {
1362 depth = std::max(depth, depth_by_node.
lookup(&target->owner_node()) + 1);
1365 depth_by_node.
add_new(node, depth);
1366 const int index_at_depth = num_by_depth.
lookup_or_add(depth, 0)++;
1367 node->location[0] = 200 - depth * 200;
1368 node->location[1] = -index_at_depth * 300;
1376 void forward_value_or_schedule(
const SocketInContext &socket,
const SocketInContext &origin)
1378 if (
const SocketValue *value = value_by_socket_.lookup_ptr(origin)) {
1379 if (socket->type == origin->type) {
1380 this->store_socket_value(socket, *value);
1383 this->store_socket_value(
1384 socket, this->handle_implicit_conversion(*value, *origin->typeinfo, *socket->typeinfo));
1387 this->schedule_socket(origin);
1390 void store_socket_value(
const SocketInContext &socket, SocketValue value)
1392 value_by_socket_.add_new(socket, std::move(value));
1395 void store_socket_value_fallback(
const SocketInContext &socket)
1397 value_by_socket_.add_new(socket, {FallbackValue{}});
1400 void store_socket_value_dangling(
const SocketInContext &socket)
1402 value_by_socket_.add_new(socket, {DanglingValue{}});
1405 void schedule_socket(
const SocketInContext &socket)
1407 scheduled_sockets_stack_.push(socket);
1410 int node_copy_flag()
const
1412 const bool use_refcounting = !(dst_tree_.id.tag &
ID_TAG_NO_MAIN);
1423 ShaderNodesInliner inliner(src_tree, dst_tree,
params);
1425 if (inliner.do_inline()) {
1429 sock->link =
nullptr;
1432 sock->link =
nullptr;
@ LIB_ID_CREATE_NO_USER_REFCOUNT
#define BLI_assert_unreachable()
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
@ NODE_DEFAULT_INPUT_VALUE
struct NodeMenuSwitch NodeMenuSwitch
struct bNodeSocketValueFloat bNodeSocketValueFloat
struct bNodeSocketValueMenu bNodeSocketValueMenu
struct bNodeSocketValueInt bNodeSocketValueInt
struct NodeRepeatItem NodeRepeatItem
struct NodeCombineBundleItem NodeCombineBundleItem
struct bNodeSocketValueRGBA bNodeSocketValueRGBA
struct bNodeSocketValueVector bNodeSocketValueVector
struct NodeClosureOutput NodeClosureOutput
struct NodeGeometryRepeatInput NodeGeometryRepeatInput
struct NodeEvaluateClosure NodeEvaluateClosure
struct NodeSeparateBundle NodeSeparateBundle
struct NodeGeometryRepeatOutput NodeGeometryRepeatOutput
struct bNodeLink bNodeLink
struct NodeEvaluateClosureInputItem NodeEvaluateClosureInputItem
struct bNodeSocketValueBoolean bNodeSocketValueBoolean
struct bNodeTree bNodeTree
struct NodeCombineBundle NodeCombineBundle
struct NodeEnumItem NodeEnumItem
struct NodeClosureOutputItem NodeClosureOutputItem
struct bNodeSocket bNodeSocket
const Value & lookup(const Key &key) const
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
void add_new(const Key &key, const Value &value)
Value & lookup_or_add(const Key &key, const Value &value)
void append(const T &value)
static const CPPType & get()
static GVArray from_single(const CPPType &type, int64_t size, const void *value)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
const bNodeZoneType * zone_type_by_node_type(const int node_type)
bNode * node_add_node(const bContext *C, bNodeTree &ntree, StringRef idname, std::optional< int > unique_identifier=std::nullopt)
const DataTypeConversions & get_implicit_type_conversions()
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, int flag, std::optional< StringRefNull > dst_unique_name, std::optional< int > dst_unique_identifier, Map< const bNodeSocket *, bNodeSocket * > &new_socket_map, bool allow_duplicate_names=false)
int context(const bContext *C, const char *member, bContextDataResult *result)
GreasePencil * from_context(bContext &C)
bool inline_shader_node_tree(const bNodeTree &src_tree, bNodeTree &dst_tree, InlineShaderNodeTreeParams ¶ms)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
static void unique_name(bNode *node)
NodeClosureOutputItem * items
NodeClosureOutputItems output_items
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
struct bNodeSocket * next
bNodeTreeTypeHandle * typeinfo
static bNode * add_node(bNodeTree *ntree, const int type, const blender::float2 loc)