Blender V4.3
gpu_node_graph.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstdio>
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "DNA_node_types.h"
17
18#include "BLI_ghash.h"
19#include "BLI_listbase.h"
20#include "BLI_string.h"
21#include "BLI_utildefines.h"
22
23#include "GPU_texture.hh"
24#include "GPU_vertex_format.hh"
25
27#include "gpu_node_graph.hh"
28
29/* Node Link Functions */
30
32{
33 GPUNodeLink *link = MEM_cnew<GPUNodeLink>("GPUNodeLink");
34 link->users++;
35
36 return link;
37}
38
40{
41 link->users--;
42
43 if (link->users < 0) {
44 fprintf(stderr, "gpu_node_link_free: negative refcount\n");
45 }
46
47 if (link->users == 0) {
48 if (link->output) {
49 link->output->link = nullptr;
50 }
51 MEM_freeN(link);
52 }
53}
54
55/* Node Functions */
56
57static GPUNode *gpu_node_create(const char *name)
58{
59 GPUNode *node = MEM_cnew<GPUNode>("GPUNode");
60
61 node->name = name;
62
63 return node;
64}
65
66static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType type)
67{
68 GPUInput *input;
69 GPUNode *outnode;
70 const char *name;
71
72 if (link->link_type == GPU_NODE_LINK_OUTPUT) {
73 outnode = link->output->node;
74 name = outnode->name;
75 input = static_cast<GPUInput *>(outnode->inputs.first);
76
77 if (STR_ELEM(name, "set_value", "set_rgb", "set_rgba") && (input->type == type)) {
78 input = static_cast<GPUInput *>(MEM_dupallocN(outnode->inputs.first));
79
80 switch (input->source) {
81 case GPU_SOURCE_ATTR:
82 input->attr->users++;
83 break;
85 input->uniform_attr->users++;
86 break;
88 input->layer_attr->users++;
89 break;
90 case GPU_SOURCE_TEX:
91 input->texture->users++;
92 break;
94 /* Already handled by GPU_SOURCE_TEX. */
95 default:
96 break;
97 }
98
99 if (input->link) {
100 input->link->users++;
101 }
102
103 BLI_addtail(&node->inputs, input);
104 return;
105 }
106 }
107
108 input = MEM_cnew<GPUInput>("GPUInput");
109 input->node = node;
110 input->type = type;
111
112 switch (link->link_type) {
114 input->source = GPU_SOURCE_OUTPUT;
115 input->link = link;
116 link->users++;
117 break;
122 input->source = GPU_SOURCE_TEX;
123 input->texture = link->texture;
124 break;
126 input->source = GPU_SOURCE_TEX_TILED_MAPPING;
127 input->texture = link->texture;
128 break;
130 input->source = GPU_SOURCE_ATTR;
131 input->attr = link->attr;
132 /* Fail-safe handling if the same attribute is used with different data-types for
133 * some reason (only really makes sense with float/vec2/vec3/vec4 though). This
134 * can happen if mixing the generic Attribute node with specialized ones. */
135 CLAMP_MIN(input->attr->gputype, type);
136 break;
138 input->source = GPU_SOURCE_UNIFORM_ATTR;
139 input->uniform_attr = link->uniform_attr;
140 break;
142 input->source = GPU_SOURCE_LAYER_ATTR;
143 input->layer_attr = link->layer_attr;
144 break;
146 input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
147 break;
149 input->source = GPU_SOURCE_UNIFORM;
150 break;
152 input->source = GPU_SOURCE_FUNCTION_CALL;
153 /* NOTE(@fclem): End of function call is the return variable set during codegen. */
154 SNPRINTF(input->function_call, "dF_branch_incomplete(%s(), ", link->function_name);
155 break;
156 default:
157 break;
158 }
159
160 if (ELEM(input->source, GPU_SOURCE_CONSTANT, GPU_SOURCE_UNIFORM)) {
161 memcpy(input->vec, link->data, type * sizeof(float));
162 }
163
164 if (link->link_type != GPU_NODE_LINK_OUTPUT) {
165 MEM_freeN(link);
166 }
167 BLI_addtail(&node->inputs, input);
168}
169
171{
172 switch (type) {
173 /* For now INT & BOOL are supported as float. */
174 case SOCK_INT:
175 case SOCK_FLOAT:
176 case SOCK_BOOLEAN:
177 return "set_value";
178 case SOCK_VECTOR:
179 return "set_rgb";
180 case SOCK_RGBA:
181 return "set_rgba";
182 default:
183 BLI_assert_msg(0, "No gpu function for non-supported eNodeSocketDatatype");
184 return nullptr;
185 }
186}
187
193 const bNode *node,
194 GPUNodeStack *stack,
195 const int index,
196 const eNodeSocketInOut in_out)
197{
198 bNodeSocket *socket;
199
200 if (in_out == SOCK_IN) {
201 socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, index));
202 }
203 else {
204 socket = static_cast<bNodeSocket *>(BLI_findlink(&node->outputs, index));
205 }
206
207 BLI_assert(socket != nullptr);
208 BLI_assert(socket->in_out == in_out);
209
210 if (socket->flag & SOCK_HIDE_VALUE) {
211 return nullptr;
212 }
213
214 if (!ELEM(socket->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA)) {
215 return nullptr;
216 }
217
218 GPUNodeLink *link = GPU_uniform(stack->vec);
219
220 if (in_out == SOCK_IN) {
221 GPU_link(mat,
223 link,
224 &stack->link);
225 }
226
227 return link;
228}
229
231 GPUMaterial *material, const bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
232{
233 if (sock->link) {
234 gpu_node_input_link(node, sock->link, sock->type);
235 }
236 else if ((material != nullptr) &&
237 (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != nullptr))
238 {
239 gpu_node_input_link(node, sock->link, sock->type);
240 }
241 else {
242 gpu_node_input_link(node, GPU_constant(sock->vec), sock->type);
243 }
244}
245
246static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **link)
247{
248 GPUOutput *output = MEM_cnew<GPUOutput>("GPUOutput");
249
250 output->type = type;
251 output->node = node;
252
253 if (link) {
254 *link = output->link = gpu_node_link_create();
255 output->link->link_type = GPU_NODE_LINK_OUTPUT;
256 output->link->output = output;
257
258 /* NOTE: the caller owns the reference to the link, GPUOutput
259 * merely points to it, and if the node is destroyed it will
260 * set that pointer to nullptr */
261 }
262
263 BLI_addtail(&node->outputs, output);
264}
265
266/* Uniform Attribute Functions */
267
268static int uniform_attr_sort_cmp(const void *a, const void *b)
269{
270 const GPUUniformAttr *attr_a = static_cast<const GPUUniformAttr *>(a),
271 *attr_b = static_cast<const GPUUniformAttr *>(b);
272
273 int cmps = strcmp(attr_a->name, attr_b->name);
274 if (cmps != 0) {
275 return cmps > 0 ? 1 : 0;
276 }
277
278 return (attr_a->use_dupli && !attr_b->use_dupli);
279}
280
281static uint uniform_attr_list_hash(const void *key)
282{
283 const GPUUniformAttrList *attrs = static_cast<const GPUUniformAttrList *>(key);
284 return attrs->hash_code;
285}
286
287static bool uniform_attr_list_cmp(const void *a, const void *b)
288{
289 const GPUUniformAttrList *set_a = static_cast<const GPUUniformAttrList *>(a),
290 *set_b = static_cast<const GPUUniformAttrList *>(b);
291
292 if (set_a->hash_code != set_b->hash_code || set_a->count != set_b->count) {
293 return true;
294 }
295
296 GPUUniformAttr *attr_a = static_cast<GPUUniformAttr *>(set_a->list.first),
297 *attr_b = static_cast<GPUUniformAttr *>(set_b->list.first);
298
299 for (; attr_a && attr_b; attr_a = attr_a->next, attr_b = attr_b->next) {
300 if (!STREQ(attr_a->name, attr_b->name) || attr_a->use_dupli != attr_b->use_dupli) {
301 return true;
302 }
303 }
304
305 return attr_a || attr_b;
306}
307
312
314{
315 dest->count = src->count;
316 dest->hash_code = src->hash_code;
317 BLI_duplicatelist(&dest->list, &src->list);
318}
319
321{
322 set->count = 0;
323 set->hash_code = 0;
324 BLI_freelistN(&set->list);
325}
326
328{
329 GPUUniformAttrList *attrs = &graph->uniform_attrs;
330 BLI_assert(attrs->count == BLI_listbase_count(&attrs->list));
331
332 /* Sort the attributes by name to ensure a stable order. */
334
335 /* Compute the indices and the hash code. */
336 int next_id = 0;
337 attrs->hash_code = 0;
338
339 LISTBASE_FOREACH (GPUUniformAttr *, attr, &attrs->list) {
340 attr->id = next_id++;
341 attrs->hash_code ^= BLI_ghashutil_uinthash(attr->hash_code + (1 << (attr->id + 1)));
342 }
343}
344
345/* Attributes and Textures */
346
347static char attr_prefix_get(const GPUMaterialAttribute *attr)
348{
349 if (attr->is_default_color) {
350 return 'c';
351 }
352 if (attr->is_hair_length) {
353 return 'l';
354 }
355 switch (attr->type) {
356 case CD_TANGENT:
357 return 't';
359 return 'a';
360 default:
361 BLI_assert_msg(0, "GPUVertAttr Prefix type not found : This should not happen!");
362 return '\0';
363 }
364}
365
367{
368 /* NOTE: Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.cc */
369 if (attr->type == CD_ORCO) {
370 /* OPTI: orco is computed from local positions, but only if no modifier is present. */
371 STRNCPY(attr->input_name, "orco");
372 }
373 else {
374 attr->input_name[0] = attr_prefix_get(attr);
375 attr->input_name[1] = '\0';
376 if (attr->name[0] != '\0') {
377 /* XXX FIXME: see notes in mesh_render_data_create() */
379 }
380 }
381}
382
385 eCustomDataType type,
386 const char *name,
387 const bool is_default_color,
388 const bool is_hair_length)
389{
390 /* Find existing attribute. */
391 int num_attributes = 0;
392 GPUMaterialAttribute *attr = static_cast<GPUMaterialAttribute *>(graph->attributes.first);
393 for (; attr; attr = attr->next) {
394 if (attr->type == type && STREQ(attr->name, name) &&
395 attr->is_default_color == is_default_color && attr->is_hair_length == is_hair_length)
396 {
397 break;
398 }
399 num_attributes++;
400 }
401
402 /* Add new requested attribute if it's within GPU limits. */
403 if (attr == nullptr) {
404 attr = MEM_cnew<GPUMaterialAttribute>(__func__);
405 attr->is_default_color = is_default_color;
406 attr->is_hair_length = is_hair_length;
407 attr->type = type;
408 STRNCPY(attr->name, name);
409 attr_input_name(attr);
410 attr->id = num_attributes;
411 BLI_addtail(&graph->attributes, attr);
412 }
413
414 if (attr != nullptr) {
415 attr->users++;
416 }
417
418 return attr;
419}
420
423 const char *name,
424 bool use_dupli)
425{
426 /* Find existing attribute. */
427 GPUUniformAttrList *attrs = &graph->uniform_attrs;
428 GPUUniformAttr *attr = static_cast<GPUUniformAttr *>(attrs->list.first);
429
430 for (; attr; attr = attr->next) {
431 if (STREQ(attr->name, name) && attr->use_dupli == use_dupli) {
432 break;
433 }
434 }
435
436 /* Add new requested attribute if it's within GPU limits. */
437 if (attr == nullptr && attrs->count < GPU_MAX_UNIFORM_ATTR) {
438 attr = MEM_cnew<GPUUniformAttr>(__func__);
439 STRNCPY(attr->name, name);
440 attr->use_dupli = use_dupli;
441 attr->hash_code = BLI_ghashutil_strhash_p(attr->name) << 1 | (attr->use_dupli ? 0 : 1);
442 attr->id = -1;
443 BLI_addtail(&attrs->list, attr);
444 attrs->count++;
445 }
446
447 if (attr != nullptr) {
448 attr->users++;
449 }
450
451 return attr;
452}
453
456{
457 /* Find existing attribute. */
458 ListBase *attrs = &graph->layer_attrs;
459 GPULayerAttr *attr = static_cast<GPULayerAttr *>(attrs->first);
460
461 for (; attr; attr = attr->next) {
462 if (STREQ(attr->name, name)) {
463 break;
464 }
465 }
466
467 /* Add new requested attribute to the list. */
468 if (attr == nullptr) {
469 attr = MEM_cnew<GPULayerAttr>(__func__);
470 STRNCPY(attr->name, name);
472 BLI_addtail(attrs, attr);
473 }
474
475 if (attr != nullptr) {
476 attr->users++;
477 }
478
479 return attr;
480}
481
483 Image *ima,
484 ImageUser *iuser,
485 GPUTexture **colorband,
486 GPUTexture **sky,
487 bool is_tiled,
488 GPUSamplerState sampler_state)
489{
490 /* Find existing texture. */
491 int num_textures = 0;
492 GPUMaterialTexture *tex = static_cast<GPUMaterialTexture *>(graph->textures.first);
493 for (; tex; tex = tex->next) {
494 if (tex->ima == ima && tex->colorband == colorband && tex->sky == sky &&
495 tex->sampler_state == sampler_state)
496 {
497 break;
498 }
499 num_textures++;
500 }
501
502 /* Add new requested texture. */
503 if (tex == nullptr) {
504 tex = MEM_cnew<GPUMaterialTexture>(__func__);
505 tex->ima = ima;
506 if (iuser != nullptr) {
507 tex->iuser = *iuser;
508 tex->iuser_available = true;
509 }
510 tex->colorband = colorband;
511 tex->sky = sky;
512 tex->sampler_state = sampler_state;
513 SNPRINTF(tex->sampler_name, "samp%d", num_textures);
514 if (is_tiled) {
515 SNPRINTF(tex->tiled_mapping_name, "tsamp%d", num_textures);
516 }
517 BLI_addtail(&graph->textures, tex);
518 }
519
520 tex->users++;
521
522 return tex;
523}
524
525/* Creating Inputs */
526
527GPUNodeLink *GPU_attribute(GPUMaterial *mat, const eCustomDataType type, const char *name)
528{
530 GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name, false, false);
531
532 if (type == CD_ORCO) {
533 /* OPTI: orco might be computed from local positions and needs object infos. */
535 }
536
537 /* Dummy fallback if out of slots. */
538 if (attr == nullptr) {
539 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
540 return GPU_constant(zero_data);
541 }
542
545 link->attr = attr;
546 return link;
547}
548
550{
553 graph, CD_AUTO_FROM_NAME, "", true, false);
554 if (attr == nullptr) {
555 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
556 return GPU_constant(zero_data);
557 }
558 attr->is_default_color = true;
561 link->attr = attr;
562 return link;
563}
564
566{
569 graph, CD_AUTO_FROM_NAME, "", false, true);
570 if (attr == nullptr) {
571 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
572 return GPU_constant(zero_data);
573 }
576 link->attr = attr;
577 return link;
578}
579
581 const eCustomDataType type,
582 const char *name,
583 eGPUDefaultValue default_value)
584{
585 GPUNodeLink *link = GPU_attribute(mat, type, name);
586 if (link->link_type == GPU_NODE_LINK_ATTR) {
587 link->attr->default_value = default_value;
588 }
589 return link;
590}
591
593 const char *name,
594 bool use_dupli,
595 uint32_t *r_hash)
596{
598 GPUUniformAttr *attr = gpu_node_graph_add_uniform_attribute(graph, name, use_dupli);
599
600 /* Dummy fallback if out of slots. */
601 if (attr == nullptr) {
602 *r_hash = 0;
603 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
604 return GPU_constant(zero_data);
605 }
606 *r_hash = attr->hash_code;
607
610 link->uniform_attr = attr;
611 return link;
612}
613
615{
618
621 link->layer_attr = attr;
622 return link;
623}
624
625GPUNodeLink *GPU_constant(const float *num)
626{
629 link->data = num;
630 return link;
631}
632
633GPUNodeLink *GPU_uniform(const float *num)
634{
637 link->data = num;
638 return link;
639}
640
642{
645 link->function_name = function_name;
646 return link;
647}
648
650 Image *ima,
651 ImageUser *iuser,
652 GPUSamplerState sampler_state)
653{
658 graph, ima, iuser, nullptr, nullptr, false, sampler_state);
659 return link;
660}
661
663 int width,
664 int height,
665 const float *pixels,
666 float *layer,
667 GPUSamplerState sampler_state)
668{
669 GPUTexture **sky = gpu_material_sky_texture_layer_set(mat, width, height, pixels, layer);
670
675 graph, nullptr, nullptr, nullptr, sky, false, sampler_state);
676 return link;
677}
678
680 Image *ima,
681 ImageUser *iuser,
682 GPUSamplerState sampler_state,
683 GPUNodeLink **r_image_tiled_link,
684 GPUNodeLink **r_image_tiled_mapping_link)
685{
688 graph, ima, iuser, nullptr, nullptr, true, sampler_state);
689
690 (*r_image_tiled_link) = gpu_node_link_create();
691 (*r_image_tiled_link)->link_type = GPU_NODE_LINK_IMAGE_TILED;
692 (*r_image_tiled_link)->texture = texture;
693
694 (*r_image_tiled_mapping_link) = gpu_node_link_create();
695 (*r_image_tiled_mapping_link)->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
696 (*r_image_tiled_mapping_link)->texture = texture;
697}
698
699GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *r_row)
700{
701 GPUTexture **colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, r_row);
702 MEM_freeN(pixels);
703
708 graph, nullptr, nullptr, colorband, nullptr, false, GPUSamplerState::internal_sampler());
709 return link;
710}
711
712/* Creating Nodes */
713
714bool GPU_link(GPUMaterial *mat, const char *name, ...)
715{
717 GPUNode *node;
718 GPUFunction *function;
719 GPUNodeLink *link, **linkptr;
720 va_list params;
721 int i;
722
723 function = gpu_material_library_use_function(graph->used_libraries, name);
724 if (!function) {
725 fprintf(stderr, "GPU failed to find function %s\n", name);
726 return false;
727 }
728
729 node = gpu_node_create(name);
730
731 va_start(params, name);
732 for (i = 0; i < function->totparam; i++) {
733 if (function->paramqual[i] == FUNCTION_QUAL_OUT) {
734 linkptr = va_arg(params, GPUNodeLink **);
735 gpu_node_output(node, function->paramtype[i], linkptr);
736 }
737 else {
738 link = va_arg(params, GPUNodeLink *);
739 gpu_node_input_link(node, link, function->paramtype[i]);
740 }
741 }
742 va_end(params);
743
744 BLI_addtail(&graph->nodes, node);
745
746 return true;
747}
748
749static bool gpu_stack_link_v(GPUMaterial *material,
750 const bNode *bnode,
751 const char *name,
752 GPUNodeStack *in,
753 GPUNodeStack *out,
754 va_list params)
755{
756 GPUNodeGraph *graph = gpu_material_node_graph(material);
757 GPUNode *node;
758 GPUFunction *function;
759 GPUNodeLink *link, **linkptr;
760 int i, totin, totout;
761
762 function = gpu_material_library_use_function(graph->used_libraries, name);
763 if (!function) {
764 fprintf(stderr, "GPU failed to find function %s\n", name);
765 return false;
766 }
767
768 node = gpu_node_create(name);
769 totin = 0;
770 totout = 0;
771
772 if (in) {
773 for (i = 0; !in[i].end; i++) {
774 if (in[i].type != GPU_NONE) {
775 gpu_node_input_socket(material, bnode, node, &in[i], i);
776 totin++;
777 }
778 }
779 }
780
781 if (out) {
782 for (i = 0; !out[i].end; i++) {
783 if (out[i].type != GPU_NONE) {
784 gpu_node_output(node, out[i].type, &out[i].link);
785 totout++;
786 }
787 }
788 }
789
790 for (i = 0; i < function->totparam; i++) {
791 if (function->paramqual[i] == FUNCTION_QUAL_OUT) {
792 if (totout == 0) {
793 linkptr = va_arg(params, GPUNodeLink **);
794 gpu_node_output(node, function->paramtype[i], linkptr);
795 }
796 else {
797 totout--;
798 }
799 }
800 else {
801 if (totin == 0) {
802 link = va_arg(params, GPUNodeLink *);
803 if (link->socket) {
804 gpu_node_input_socket(nullptr, nullptr, node, link->socket, -1);
805 }
806 else {
807 gpu_node_input_link(node, link, function->paramtype[i]);
808 }
809 }
810 else {
811 totin--;
812 }
813 }
814 }
815
816 BLI_addtail(&graph->nodes, node);
817
818 return true;
819}
820
822 const bNode *bnode,
823 const char *name,
824 GPUNodeStack *in,
825 GPUNodeStack *out,
826 ...)
827{
828 va_list params;
829 va_start(params, out);
830 bool valid = gpu_stack_link_v(material, bnode, name, in, out, params);
831 va_end(params);
832
833 return valid;
834}
835
836/* Node Graph */
837
838static void gpu_inputs_free(ListBase *inputs)
839{
840 LISTBASE_FOREACH (GPUInput *, input, inputs) {
841 switch (input->source) {
842 case GPU_SOURCE_ATTR:
843 input->attr->users--;
844 break;
846 input->uniform_attr->users--;
847 break;
849 input->layer_attr->users--;
850 break;
851 case GPU_SOURCE_TEX:
852 input->texture->users--;
853 break;
855 /* Already handled by GPU_SOURCE_TEX. */
856 default:
857 break;
858 }
859
860 if (input->link) {
861 gpu_node_link_free(input->link);
862 }
863 }
864
865 BLI_freelistN(inputs);
866}
867
868static void gpu_node_free(GPUNode *node)
869{
870 gpu_inputs_free(&node->inputs);
871
872 LISTBASE_FOREACH (GPUOutput *, output, &node->outputs) {
873 if (output->link) {
874 output->link->output = nullptr;
875 gpu_node_link_free(output->link);
876 }
877 }
878
879 BLI_freelistN(&node->outputs);
880 MEM_freeN(node);
881}
882
884{
885 while (GPUNode *node = static_cast<GPUNode *>(BLI_pophead(&graph->nodes))) {
886 gpu_node_free(node);
887 }
888
889 graph->outlink_surface = nullptr;
890 graph->outlink_volume = nullptr;
891 graph->outlink_displacement = nullptr;
892 graph->outlink_thickness = nullptr;
893}
894
896{
897 BLI_freelistN(&graph->outlink_aovs);
898 BLI_freelistN(&graph->material_functions);
899 BLI_freelistN(&graph->outlink_compositor);
901
902 BLI_freelistN(&graph->textures);
903 BLI_freelistN(&graph->attributes);
904 GPU_uniform_attr_list_free(&graph->uniform_attrs);
905 BLI_freelistN(&graph->layer_attrs);
906
907 if (graph->used_libraries) {
908 BLI_gset_free(graph->used_libraries, nullptr);
909 graph->used_libraries = nullptr;
910 }
911}
912
913/* Prune Unused Nodes */
914
916{
917 GPUNode *node;
918
919 if (!link || !link->output) {
920 return;
921 }
922
923 node = link->output->node;
924 if (node->tag & tag) {
925 return;
926 }
927
928 node->tag |= tag;
929 LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
930 if (input->link) {
931 gpu_nodes_tag(input->link, tag);
932 }
933 }
934}
935
937{
938 LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
939 node->tag = GPU_NODE_TAG_NONE;
940 }
941
942 gpu_nodes_tag(graph->outlink_surface, GPU_NODE_TAG_SURFACE);
943 gpu_nodes_tag(graph->outlink_volume, GPU_NODE_TAG_VOLUME);
944 gpu_nodes_tag(graph->outlink_displacement, GPU_NODE_TAG_DISPLACEMENT);
945 gpu_nodes_tag(graph->outlink_thickness, GPU_NODE_TAG_THICKNESS);
946
947 LISTBASE_FOREACH (GPUNodeGraphOutputLink *, aovlink, &graph->outlink_aovs) {
948 gpu_nodes_tag(aovlink->outlink, GPU_NODE_TAG_AOV);
949 }
950 LISTBASE_FOREACH (GPUNodeGraphFunctionLink *, funclink, &graph->material_functions) {
951 gpu_nodes_tag(funclink->outlink, GPU_NODE_TAG_FUNCTION);
952 }
953 LISTBASE_FOREACH (GPUNodeGraphOutputLink *, compositor_link, &graph->outlink_compositor) {
954 gpu_nodes_tag(compositor_link->outlink, GPU_NODE_TAG_COMPOSITOR);
955 }
956
957 for (GPUNode *node = static_cast<GPUNode *>(graph->nodes.first), *next = nullptr; node;
958 node = next)
959 {
960 next = node->next;
961
962 if (node->tag == GPU_NODE_TAG_NONE) {
963 BLI_remlink(&graph->nodes, node);
964 gpu_node_free(node);
965 }
966 }
967
968 for (GPUMaterialAttribute *attr = static_cast<GPUMaterialAttribute *>(graph->attributes.first),
969 *next = nullptr;
970 attr;
971 attr = next)
972 {
973 next = attr->next;
974 if (attr->users == 0) {
975 BLI_freelinkN(&graph->attributes, attr);
976 }
977 }
978
979 for (GPUMaterialTexture *tex = static_cast<GPUMaterialTexture *>(graph->textures.first),
980 *next = nullptr;
981 tex;
982 tex = next)
983 {
984 next = tex->next;
985 if (tex->users == 0) {
986 BLI_freelinkN(&graph->textures, tex);
987 }
988 }
989
990 GPUUniformAttrList *uattrs = &graph->uniform_attrs;
991
992 LISTBASE_FOREACH_MUTABLE (GPUUniformAttr *, attr, &uattrs->list) {
993 if (attr->users == 0) {
994 BLI_freelinkN(&uattrs->list, attr);
995 uattrs->count--;
996 }
997 }
998
999 LISTBASE_FOREACH_MUTABLE (GPULayerAttr *, attr, &graph->layer_attrs) {
1000 if (attr->users == 0) {
1001 BLI_freelinkN(&graph->layer_attrs, attr);
1002 }
1003 }
1004}
1005
1007{
1008 /* Replace all uniform node links with constant. */
1009 LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
1010 LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
1011 if (input->link) {
1012 if (input->link->link_type == GPU_NODE_LINK_UNIFORM) {
1013 input->link->link_type = GPU_NODE_LINK_CONSTANT;
1014 }
1015 }
1016 if (input->source == GPU_SOURCE_UNIFORM) {
1017 input->source = (input->type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
1018 }
1019 }
1020 }
1021
1022 /* TODO: Consider performing other node graph optimizations here. */
1023}
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
unsigned int BLI_ghashutil_uinthash(unsigned int key)
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:251
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
unsigned int uint
#define ELEM(...)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
@ CD_AUTO_FROM_NAME
eNodeSocketInOut
@ SOCK_IN
@ SOCK_HIDE_VALUE
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_RGBA
eGPUDefaultValue
@ GPU_MATFLAG_OBJECT_INFO
void GPU_material_flag_set(GPUMaterial *mat, eGPUMaterialFlag flag)
eGPUType
@ GPU_MAX_CONSTANT_DATA
@ GPU_NONE
@ GPU_CLOSURE
#define GPU_MAX_UNIFORM_ATTR
Definition GPU_shader.hh:32
void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint max_len)
#define GPU_MAX_SAFE_ATTR_NAME
Read Guarded memory(de)allocation.
#define output
local_group_size(16, 16) .push_constant(Type b
local_group_size(16, 16) .push_constant(Type texture
OperationNode * node
GPUTexture ** gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, const float *pixels, float *r_row)
GPUTexture ** gpu_material_sky_texture_layer_set(GPUMaterial *mat, int width, int height, const float *pixels, float *row)
GPUNodeGraph * gpu_material_node_graph(GPUMaterial *material)
GPUFunction * gpu_material_library_use_function(GSet *used_libraries, const char *name)
@ FUNCTION_QUAL_OUT
GPUNodeLink * GPU_constant(const float *num)
GPUNodeLink * GPU_attribute_hair_length(GPUMaterial *mat)
static GPUNodeLink * gpu_node_link_create()
GPUNodeLink * GPU_layer_attribute(GPUMaterial *mat, const char *name)
GPUNodeLink * GPU_attribute_default_color(GPUMaterial *mat)
bool GPU_stack_link(GPUMaterial *material, const bNode *bnode, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
static GPUMaterialAttribute * gpu_node_graph_add_attribute(GPUNodeGraph *graph, eCustomDataType type, const char *name, const bool is_default_color, const bool is_hair_length)
static GPUNode * gpu_node_create(const char *name)
static void gpu_node_free(GPUNode *node)
static void gpu_inputs_free(ListBase *inputs)
static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **link)
GPUNodeLink * GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *r_row)
static void gpu_node_input_socket(GPUMaterial *material, const bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
static GPULayerAttr * gpu_node_graph_add_layer_attribute(GPUNodeGraph *graph, const char *name)
static GPUUniformAttr * gpu_node_graph_add_uniform_attribute(GPUNodeGraph *graph, const char *name, bool use_dupli)
void gpu_nodes_tag(GPUNodeLink *link, eGPUNodeTag tag)
void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph)
static void gpu_node_link_free(GPUNodeLink *link)
static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType type)
GPUNodeLink * GPU_attribute(GPUMaterial *mat, const eCustomDataType type, const char *name)
void gpu_node_graph_optimize(GPUNodeGraph *graph)
GPUNodeLink * GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser, GPUSamplerState sampler_state)
void GPU_uniform_attr_list_copy(GPUUniformAttrList *dest, const GPUUniformAttrList *src)
static uint uniform_attr_list_hash(const void *key)
GHash * GPU_uniform_attr_list_hash_new(const char *info)
void GPU_uniform_attr_list_free(GPUUniformAttrList *set)
GPUNodeLink * GPU_uniform_attribute(GPUMaterial *mat, const char *name, bool use_dupli, uint32_t *r_hash)
GPUNodeLink * GPU_image_sky(GPUMaterial *mat, int width, int height, const float *pixels, float *layer, GPUSamplerState sampler_state)
void gpu_node_graph_free(GPUNodeGraph *graph)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
void GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser, GPUSamplerState sampler_state, GPUNodeLink **r_image_tiled_link, GPUNodeLink **r_image_tiled_mapping_link)
static void attr_input_name(GPUMaterialAttribute *attr)
static char attr_prefix_get(const GPUMaterialAttribute *attr)
static bool uniform_attr_list_cmp(const void *a, const void *b)
static GPUMaterialTexture * gpu_node_graph_add_texture(GPUNodeGraph *graph, Image *ima, ImageUser *iuser, GPUTexture **colorband, GPUTexture **sky, bool is_tiled, GPUSamplerState sampler_state)
static bool gpu_stack_link_v(GPUMaterial *material, const bNode *bnode, const char *name, GPUNodeStack *in, GPUNodeStack *out, va_list params)
GPUNodeLink * GPU_differentiate_float_function(const char *function_name)
static int uniform_attr_sort_cmp(const void *a, const void *b)
static const char * gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
GPUNodeLink * GPU_attribute_with_default(GPUMaterial *mat, const eCustomDataType type, const char *name, eGPUDefaultValue default_value)
static GPUNodeLink * gpu_uniformbuffer_link(GPUMaterial *mat, const bNode *node, GPUNodeStack *stack, const int index, const eNodeSocketInOut in_out)
bool GPU_link(GPUMaterial *mat, const char *name,...)
GPUNodeLink * GPU_uniform(const float *num)
eGPUNodeTag
@ GPU_NODE_TAG_NONE
@ GPU_NODE_TAG_SURFACE
@ GPU_NODE_TAG_DISPLACEMENT
@ GPU_NODE_TAG_VOLUME
@ GPU_NODE_TAG_FUNCTION
@ GPU_NODE_TAG_COMPOSITOR
@ GPU_NODE_TAG_THICKNESS
@ GPU_NODE_TAG_AOV
@ GPU_SOURCE_CONSTANT
@ GPU_SOURCE_FUNCTION_CALL
@ GPU_SOURCE_ATTR
@ GPU_SOURCE_UNIFORM
@ GPU_SOURCE_OUTPUT
@ GPU_SOURCE_TEX_TILED_MAPPING
@ GPU_SOURCE_UNIFORM_ATTR
@ GPU_SOURCE_LAYER_ATTR
@ GPU_SOURCE_STRUCT
@ GPU_SOURCE_TEX
@ GPU_NODE_LINK_UNIFORM
@ GPU_NODE_LINK_IMAGE_SKY
@ GPU_NODE_LINK_LAYER_ATTR
@ GPU_NODE_LINK_ATTR
@ GPU_NODE_LINK_IMAGE
@ GPU_NODE_LINK_IMAGE_TILED
@ GPU_NODE_LINK_CONSTANT
@ GPU_NODE_LINK_IMAGE_TILED_MAPPING
@ GPU_NODE_LINK_COLORBAND
@ GPU_NODE_LINK_UNIFORM_ATTR
@ GPU_NODE_LINK_OUTPUT
@ GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
static ulong * next
unsigned int uint32_t
Definition stdint.h:80
GPUMaterialAttribute * attr
GPULayerAttr * next
uint32_t hash_code
eGPUDefaultValue default_value
GPUMaterialAttribute * next
eGPUType type
GPUNodeLink * link
eGPUNodeTag tag
ListBase inputs
const char * name
GPUNodeLink * link
GPUNode * node
static constexpr GPUSamplerState internal_sampler()
unsigned int hash_code
GPUUniformAttr * next
void * first
struct ImageUser iuser
struct Image * ima