Blender V4.5
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
10
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_callocN<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_callocN<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{
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_callocN<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;
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;
139 input->uniform_attr = link->uniform_attr;
140 break;
143 input->layer_attr = link->layer_attr;
144 break;
147 break;
149 input->source = GPU_SOURCE_UNIFORM;
150 break;
153 /* NOTE(@fclem): End of function call is the return variable set during codegen. */
154 SNPRINTF(input->function_call,
155 "dF_branch_incomplete(%s(), %g, ",
158 break;
159 default:
160 break;
161 }
162
164 memcpy(input->vec, link->data, type * sizeof(float));
165 }
166
167 if (link->link_type != GPU_NODE_LINK_OUTPUT) {
168 MEM_freeN(link);
169 }
170 BLI_addtail(&node->inputs, input);
171}
172
174{
175 switch (type) {
176 /* For now INT & BOOL are supported as float. */
177 case SOCK_INT:
178 case SOCK_FLOAT:
179 case SOCK_BOOLEAN:
180 return "set_value";
181 case SOCK_VECTOR:
182 return "set_rgb";
183 case SOCK_RGBA:
184 return "set_rgba";
185 default:
186 BLI_assert_msg(0, "No gpu function for non-supported eNodeSocketDatatype");
187 return nullptr;
188 }
189}
190
196 const bNode *node,
197 GPUNodeStack *stack,
198 const int index,
199 const eNodeSocketInOut in_out)
200{
201 bNodeSocket *socket;
202
203 if (in_out == SOCK_IN) {
204 socket = static_cast<bNodeSocket *>(BLI_findlink(&node->inputs, index));
205 }
206 else {
207 socket = static_cast<bNodeSocket *>(BLI_findlink(&node->outputs, index));
208 }
209
210 BLI_assert(socket != nullptr);
211 BLI_assert(socket->in_out == in_out);
212
213 if (socket->flag & SOCK_HIDE_VALUE) {
214 return nullptr;
215 }
216
217 if (!ELEM(socket->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA)) {
218 return nullptr;
219 }
220
221 GPUNodeLink *link = GPU_uniform(stack->vec);
222
223 if (in_out == SOCK_IN) {
224 GPU_link(mat,
226 link,
227 &stack->link);
228 }
229
230 return link;
231}
232
234 GPUMaterial *material, const bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
235{
236 if (sock->link) {
237 gpu_node_input_link(node, sock->link, sock->type);
238 }
239 else if ((material != nullptr) &&
240 (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != nullptr))
241 {
242 gpu_node_input_link(node, sock->link, sock->type);
243 }
244 else {
245 gpu_node_input_link(node, GPU_constant(sock->vec), sock->type);
246 }
247}
248
249static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **link)
250{
252
253 output->type = type;
254 output->node = node;
255
256 if (link) {
257 *link = output->link = gpu_node_link_create();
258 output->link->link_type = GPU_NODE_LINK_OUTPUT;
259 output->link->output = output;
260
261 /* NOTE: the caller owns the reference to the link, GPUOutput
262 * merely points to it, and if the node is destroyed it will
263 * set that pointer to nullptr */
264 }
265
266 BLI_addtail(&node->outputs, output);
267}
268
269/* Uniform Attribute Functions */
270
271static int uniform_attr_sort_cmp(const void *a, const void *b)
272{
273 const GPUUniformAttr *attr_a = static_cast<const GPUUniformAttr *>(a),
274 *attr_b = static_cast<const GPUUniformAttr *>(b);
275
276 int cmps = strcmp(attr_a->name, attr_b->name);
277 if (cmps != 0) {
278 return cmps > 0 ? 1 : 0;
279 }
280
281 return (attr_a->use_dupli && !attr_b->use_dupli);
282}
283
284static uint uniform_attr_list_hash(const void *key)
285{
286 const GPUUniformAttrList *attrs = static_cast<const GPUUniformAttrList *>(key);
287 return attrs->hash_code;
288}
289
290static bool uniform_attr_list_cmp(const void *a, const void *b)
291{
292 const GPUUniformAttrList *set_a = static_cast<const GPUUniformAttrList *>(a),
293 *set_b = static_cast<const GPUUniformAttrList *>(b);
294
295 if (set_a->hash_code != set_b->hash_code || set_a->count != set_b->count) {
296 return true;
297 }
298
299 GPUUniformAttr *attr_a = static_cast<GPUUniformAttr *>(set_a->list.first),
300 *attr_b = static_cast<GPUUniformAttr *>(set_b->list.first);
301
302 for (; attr_a && attr_b; attr_a = attr_a->next, attr_b = attr_b->next) {
303 if (!STREQ(attr_a->name, attr_b->name) || attr_a->use_dupli != attr_b->use_dupli) {
304 return true;
305 }
306 }
307
308 return attr_a || attr_b;
309}
310
315
317{
318 dest->count = src->count;
319 dest->hash_code = src->hash_code;
320 BLI_duplicatelist(&dest->list, &src->list);
321}
322
324{
325 set->count = 0;
326 set->hash_code = 0;
327 BLI_freelistN(&set->list);
328}
329
331{
332 GPUUniformAttrList *attrs = &graph->uniform_attrs;
333 BLI_assert(attrs->count == BLI_listbase_count(&attrs->list));
334
335 /* Sort the attributes by name to ensure a stable order. */
337
338 /* Compute the indices and the hash code. */
339 int next_id = 0;
340 attrs->hash_code = 0;
341
342 LISTBASE_FOREACH (GPUUniformAttr *, attr, &attrs->list) {
343 attr->id = next_id++;
344 attrs->hash_code ^= BLI_ghashutil_uinthash(attr->hash_code + (1 << (attr->id + 1)));
345 }
346}
347
348/* Attributes and Textures */
349
350static char attr_prefix_get(const GPUMaterialAttribute *attr)
351{
352 if (attr->is_default_color) {
353 return 'c';
354 }
355 if (attr->is_hair_length) {
356 return 'l';
357 }
358 switch (attr->type) {
359 case CD_TANGENT:
360 return 't';
362 return 'a';
363 default:
364 BLI_assert_msg(0, "GPUVertAttr Prefix type not found : This should not happen!");
365 return '\0';
366 }
367}
368
370{
371 /* NOTE: Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.cc */
372 if (attr->type == CD_ORCO) {
373 /* OPTI: orco is computed from local positions, but only if no modifier is present. */
374 STRNCPY(attr->input_name, "orco");
375 }
376 else {
377 attr->input_name[0] = attr_prefix_get(attr);
378 attr->input_name[1] = '\0';
379 if (attr->name[0] != '\0') {
380 /* XXX FIXME: see notes in mesh_render_data_create() */
382 }
383 }
384}
385
388 eCustomDataType type,
389 const char *name,
390 const bool is_default_color,
391 const bool is_hair_length)
392{
393 /* Find existing attribute. */
394 int num_attributes = 0;
395 GPUMaterialAttribute *attr = static_cast<GPUMaterialAttribute *>(graph->attributes.first);
396 for (; attr; attr = attr->next) {
397 if (attr->type == type && STREQ(attr->name, name) &&
398 attr->is_default_color == is_default_color && attr->is_hair_length == is_hair_length)
399 {
400 break;
401 }
402 num_attributes++;
403 }
404
405 /* Add new requested attribute if it's within GPU limits. */
406 if (attr == nullptr) {
407 attr = MEM_callocN<GPUMaterialAttribute>(__func__);
408 attr->is_default_color = is_default_color;
409 attr->is_hair_length = is_hair_length;
410 attr->type = type;
411 STRNCPY(attr->name, name);
412 attr_input_name(attr);
413 attr->id = num_attributes;
414 BLI_addtail(&graph->attributes, attr);
415 }
416
417 if (attr != nullptr) {
418 attr->users++;
419 }
420
421 return attr;
422}
423
426 const char *name,
427 bool use_dupli)
428{
429 /* Find existing attribute. */
430 GPUUniformAttrList *attrs = &graph->uniform_attrs;
431 GPUUniformAttr *attr = static_cast<GPUUniformAttr *>(attrs->list.first);
432
433 for (; attr; attr = attr->next) {
434 if (STREQ(attr->name, name) && attr->use_dupli == use_dupli) {
435 break;
436 }
437 }
438
439 /* Add new requested attribute if it's within GPU limits. */
440 if (attr == nullptr && attrs->count < GPU_MAX_UNIFORM_ATTR) {
441 attr = MEM_callocN<GPUUniformAttr>(__func__);
442 STRNCPY(attr->name, name);
443 attr->use_dupli = use_dupli;
444 attr->hash_code = BLI_ghashutil_strhash_p(attr->name) << 1 | (attr->use_dupli ? 0 : 1);
445 attr->id = -1;
446 BLI_addtail(&attrs->list, attr);
447 attrs->count++;
448 }
449
450 if (attr != nullptr) {
451 attr->users++;
452 }
453
454 return attr;
455}
456
459{
460 /* Find existing attribute. */
461 ListBase *attrs = &graph->layer_attrs;
462 GPULayerAttr *attr = static_cast<GPULayerAttr *>(attrs->first);
463
464 for (; attr; attr = attr->next) {
465 if (STREQ(attr->name, name)) {
466 break;
467 }
468 }
469
470 /* Add new requested attribute to the list. */
471 if (attr == nullptr) {
472 attr = MEM_callocN<GPULayerAttr>(__func__);
473 STRNCPY(attr->name, name);
475 BLI_addtail(attrs, attr);
476 }
477
478 if (attr != nullptr) {
479 attr->users++;
480 }
481
482 return attr;
483}
484
486 Image *ima,
487 ImageUser *iuser,
488 GPUTexture **colorband,
489 GPUTexture **sky,
490 bool is_tiled,
491 GPUSamplerState sampler_state)
492{
493 /* Find existing texture. */
494 int num_textures = 0;
495 GPUMaterialTexture *tex = static_cast<GPUMaterialTexture *>(graph->textures.first);
496 for (; tex; tex = tex->next) {
497 if (tex->ima == ima && tex->colorband == colorband && tex->sky == sky &&
498 tex->sampler_state == sampler_state)
499 {
500 break;
501 }
502 num_textures++;
503 }
504
505 /* Add new requested texture. */
506 if (tex == nullptr) {
507 tex = MEM_callocN<GPUMaterialTexture>(__func__);
508 tex->ima = ima;
509 if (iuser != nullptr) {
510 tex->iuser = *iuser;
511 tex->iuser_available = true;
512 }
513 tex->colorband = colorband;
514 tex->sky = sky;
515 tex->sampler_state = sampler_state;
516 SNPRINTF(tex->sampler_name, "samp%d", num_textures);
517 if (is_tiled) {
518 SNPRINTF(tex->tiled_mapping_name, "tsamp%d", num_textures);
519 }
520 BLI_addtail(&graph->textures, tex);
521 }
522
523 tex->users++;
524
525 return tex;
526}
527
528/* Creating Inputs */
529
530GPUNodeLink *GPU_attribute(GPUMaterial *mat, const eCustomDataType type, const char *name)
531{
533 GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name, false, false);
534
535 if (type == CD_ORCO) {
536 /* OPTI: orco might be computed from local positions and needs object information. */
538 }
539
540 /* Dummy fallback if out of slots. */
541 if (attr == nullptr) {
542 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
543 return GPU_constant(zero_data);
544 }
545
548 link->attr = attr;
549 return link;
550}
551
553{
556 graph, CD_AUTO_FROM_NAME, "", true, false);
557 if (attr == nullptr) {
558 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
559 return GPU_constant(zero_data);
560 }
561 attr->is_default_color = true;
564 link->attr = attr;
565 return link;
566}
567
569{
572 graph, CD_AUTO_FROM_NAME, "", false, true);
573 if (attr == nullptr) {
574 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
575 return GPU_constant(zero_data);
576 }
579 link->attr = attr;
580 return link;
581}
582
584 const eCustomDataType type,
585 const char *name,
586 eGPUDefaultValue default_value)
587{
588 GPUNodeLink *link = GPU_attribute(mat, type, name);
589 if (link->link_type == GPU_NODE_LINK_ATTR) {
590 link->attr->default_value = default_value;
591 }
592 return link;
593}
594
596 const char *name,
597 bool use_dupli,
598 uint32_t *r_hash)
599{
601 GPUUniformAttr *attr = gpu_node_graph_add_uniform_attribute(graph, name, use_dupli);
602
603 /* Dummy fallback if out of slots. */
604 if (attr == nullptr) {
605 *r_hash = 0;
606 static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
607 return GPU_constant(zero_data);
608 }
609 *r_hash = attr->hash_code;
610
613 link->uniform_attr = attr;
614 return link;
615}
616
618{
621
624 link->layer_attr = attr;
625 return link;
626}
627
629{
632 link->data = num;
633 return link;
634}
635
637{
640 link->data = num;
641 return link;
642}
643
644GPUNodeLink *GPU_differentiate_float_function(const char *function_name, const float filter_width)
645{
648 link->differentiate_float.function_name = function_name;
649 link->differentiate_float.filter_width = filter_width;
650 return link;
651}
652
654 Image *ima,
655 ImageUser *iuser,
656 GPUSamplerState sampler_state)
657{
662 graph, ima, iuser, nullptr, nullptr, false, sampler_state);
663 return link;
664}
665
667 int width,
668 int height,
669 const float *pixels,
670 float *layer,
671 GPUSamplerState sampler_state)
672{
673 GPUTexture **sky = gpu_material_sky_texture_layer_set(mat, width, height, pixels, layer);
674
679 graph, nullptr, nullptr, nullptr, sky, false, sampler_state);
680 return link;
681}
682
684 Image *ima,
685 ImageUser *iuser,
686 GPUSamplerState sampler_state,
687 GPUNodeLink **r_image_tiled_link,
688 GPUNodeLink **r_image_tiled_mapping_link)
689{
692 graph, ima, iuser, nullptr, nullptr, true, sampler_state);
693
694 (*r_image_tiled_link) = gpu_node_link_create();
695 (*r_image_tiled_link)->link_type = GPU_NODE_LINK_IMAGE_TILED;
696 (*r_image_tiled_link)->texture = texture;
697
698 (*r_image_tiled_mapping_link) = gpu_node_link_create();
699 (*r_image_tiled_mapping_link)->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
700 (*r_image_tiled_mapping_link)->texture = texture;
701}
702
703GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *r_row)
704{
705 GPUTexture **colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, r_row);
706 MEM_freeN(pixels);
707
712 graph, nullptr, nullptr, colorband, nullptr, false, GPUSamplerState::internal_sampler());
713 return link;
714}
715
716/* Creating Nodes */
717
718bool GPU_link(GPUMaterial *mat, const char *name, ...)
719{
721 GPUNode *node;
722 GPUFunction *function;
723 GPUNodeLink *link, **linkptr;
724 va_list params;
725 int i;
726
727 function = gpu_material_library_use_function(graph->used_libraries, name);
728 if (!function) {
729 fprintf(stderr, "GPU failed to find function %s\n", name);
730 return false;
731 }
732
733 node = gpu_node_create(name);
734
735 va_start(params, name);
736 for (i = 0; i < function->totparam; i++) {
737 if (function->paramqual[i] == FUNCTION_QUAL_OUT) {
738 linkptr = va_arg(params, GPUNodeLink **);
739 gpu_node_output(node, function->paramtype[i], linkptr);
740 }
741 else {
742 link = va_arg(params, GPUNodeLink *);
743 gpu_node_input_link(node, link, function->paramtype[i]);
744 }
745 }
746 va_end(params);
747
748 BLI_addtail(&graph->nodes, node);
749
750 return true;
751}
752
753static bool gpu_stack_link_v(GPUMaterial *material,
754 const bNode *bnode,
755 const char *name,
758 va_list params)
759{
760 GPUNodeGraph *graph = gpu_material_node_graph(material);
761 GPUNode *node;
762 GPUFunction *function;
763 GPUNodeLink *link, **linkptr;
764 int i, totin, totout;
765
766 function = gpu_material_library_use_function(graph->used_libraries, name);
767 if (!function) {
768 fprintf(stderr, "GPU failed to find function %s\n", name);
769 return false;
770 }
771
772 node = gpu_node_create(name);
773 totin = 0;
774 totout = 0;
775
776 if (in) {
777 for (i = 0; !in[i].end; i++) {
778 if (in[i].type != GPU_NONE) {
779 gpu_node_input_socket(material, bnode, node, &in[i], i);
780 totin++;
781 }
782 }
783 }
784
785 if (out) {
786 for (i = 0; !out[i].end; i++) {
787 if (out[i].type != GPU_NONE) {
788 gpu_node_output(node, out[i].type, &out[i].link);
789 totout++;
790 }
791 }
792 }
793
794 for (i = 0; i < function->totparam; i++) {
795 if (function->paramqual[i] == FUNCTION_QUAL_OUT) {
796 if (totout == 0) {
797 linkptr = va_arg(params, GPUNodeLink **);
798 gpu_node_output(node, function->paramtype[i], linkptr);
799 }
800 else {
801 totout--;
802 }
803 }
804 else {
805 if (totin == 0) {
806 link = va_arg(params, GPUNodeLink *);
807 if (link->socket) {
808 gpu_node_input_socket(nullptr, nullptr, node, link->socket, -1);
809 }
810 else {
811 gpu_node_input_link(node, link, function->paramtype[i]);
812 }
813 }
814 else {
815 totin--;
816 }
817 }
818 }
819
820 BLI_addtail(&graph->nodes, node);
821
822 return true;
823}
824
826 const bNode *bnode,
827 const char *name,
830 ...)
831{
832 va_list params;
833 va_start(params, out);
834 bool valid = gpu_stack_link_v(material, bnode, name, in, out, params);
835 va_end(params);
836
837 return valid;
838}
839
840/* Node Graph */
841
843{
845 switch (input->source) {
846 case GPU_SOURCE_ATTR:
847 input->attr->users--;
848 break;
850 input->uniform_attr->users--;
851 break;
853 input->layer_attr->users--;
854 break;
855 case GPU_SOURCE_TEX:
856 input->texture->users--;
857 break;
859 /* Already handled by GPU_SOURCE_TEX. */
860 default:
861 break;
862 }
863
864 if (input->link) {
866 }
867 }
868
870}
871
872static void gpu_node_free(GPUNode *node)
873{
874 gpu_inputs_free(&node->inputs);
875
877 if (output->link) {
878 output->link->output = nullptr;
880 }
881 }
882
883 BLI_freelistN(&node->outputs);
884 MEM_freeN(node);
885}
886
888{
889 while (GPUNode *node = static_cast<GPUNode *>(BLI_pophead(&graph->nodes))) {
890 gpu_node_free(node);
891 }
892
893 graph->outlink_surface = nullptr;
894 graph->outlink_volume = nullptr;
895 graph->outlink_displacement = nullptr;
896 graph->outlink_thickness = nullptr;
897}
898
900{
905
906 BLI_freelistN(&graph->textures);
907 BLI_freelistN(&graph->attributes);
909 BLI_freelistN(&graph->layer_attrs);
910
911 if (graph->used_libraries) {
912 BLI_gset_free(graph->used_libraries, nullptr);
913 graph->used_libraries = nullptr;
914 }
915}
916
917/* Prune Unused Nodes */
918
920{
921 GPUNode *node;
922
923 if (!link || !link->output) {
924 return;
925 }
926
927 node = link->output->node;
928 if (node->tag & tag) {
929 return;
930 }
931
932 node->tag |= tag;
934 if (input->link) {
935 gpu_nodes_tag(input->link, tag);
936 }
937 }
938}
939
941{
942 LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
943 node->tag = GPU_NODE_TAG_NONE;
944 }
945
950
952 gpu_nodes_tag(aovlink->outlink, GPU_NODE_TAG_AOV);
953 }
955 gpu_nodes_tag(funclink->outlink, GPU_NODE_TAG_FUNCTION);
956 }
957 LISTBASE_FOREACH (GPUNodeGraphOutputLink *, compositor_link, &graph->outlink_compositor) {
958 gpu_nodes_tag(compositor_link->outlink, GPU_NODE_TAG_COMPOSITOR);
959 }
960
961 for (GPUNode *node = static_cast<GPUNode *>(graph->nodes.first), *next = nullptr; node;
962 node = next)
963 {
964 next = node->next;
965
966 if (node->tag == GPU_NODE_TAG_NONE) {
967 BLI_remlink(&graph->nodes, node);
968 gpu_node_free(node);
969 }
970 }
971
972 for (GPUMaterialAttribute *attr = static_cast<GPUMaterialAttribute *>(graph->attributes.first),
973 *next = nullptr;
974 attr;
975 attr = next)
976 {
977 next = attr->next;
978 if (attr->users == 0) {
979 BLI_freelinkN(&graph->attributes, attr);
980 }
981 }
982
983 for (GPUMaterialTexture *tex = static_cast<GPUMaterialTexture *>(graph->textures.first),
984 *next = nullptr;
985 tex;
986 tex = next)
987 {
988 next = tex->next;
989 if (tex->users == 0) {
990 BLI_freelinkN(&graph->textures, tex);
991 }
992 }
993
994 GPUUniformAttrList *uattrs = &graph->uniform_attrs;
995
996 LISTBASE_FOREACH_MUTABLE (GPUUniformAttr *, attr, &uattrs->list) {
997 if (attr->users == 0) {
998 BLI_freelinkN(&uattrs->list, attr);
999 uattrs->count--;
1000 }
1001 }
1002
1004 if (attr->users == 0) {
1005 BLI_freelinkN(&graph->layer_attrs, attr);
1006 }
1007 }
1008}
1009
1011{
1012 /* Replace all uniform node links with constant. */
1013 LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
1014 LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
1015 if (input->link) {
1016 if (input->link->link_type == GPU_NODE_LINK_UNIFORM) {
1017 input->link->link_type = GPU_NODE_LINK_CONSTANT;
1018 }
1019 }
1020 if (input->source == GPU_SOURCE_UNIFORM) {
1022 }
1023 }
1024 }
1025
1026 /* TODO: Consider performing other node graph optimizations here. */
1027}
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
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.cc:686
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:252
ATTR_WARN_UNUSED_RESULT const size_t num
#define STR_ELEM(...)
Definition BLI_string.h:656
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
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
static constexpr int GPU_MAX_UNIFORM_ATTR
Definition GPU_shader.hh:37
void GPU_vertformat_safe_attr_name(blender::StringRef attr_name, char *r_safe_name, uint max_len)
static constexpr int GPU_MAX_SAFE_ATTR_NAME
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
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)
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
#define input
#define in
#define out
#define output
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)
GPUNodeLink * GPU_differentiate_float_function(const char *function_name, const float filter_width)
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)
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_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong * next
static blender::bke::bNodeSocketTemplate inputs[]
eGPUType paramtype[MAX_PARAMETER]
GPUFunctionQual paramqual[MAX_PARAMETER]
char name[256]
GPULayerAttr * next
uint32_t hash_code
eGPUDefaultValue default_value
GPUMaterialAttribute * next
GPUSamplerState sampler_state
GPUTexture ** sky
char tiled_mapping_name[32]
GPUTexture ** colorband
GPUMaterialTexture * next
ListBase outlink_compositor
GPUNodeLink * outlink_displacement
ListBase layer_attrs
ListBase outlink_aovs
GPUNodeLink * outlink_thickness
GPUNodeLink * outlink_volume
ListBase attributes
GPUNodeLink * outlink_surface
GPUUniformAttrList uniform_attrs
ListBase material_functions
GPUNodeLink * link
eGPUNodeTag tag
ListBase outputs
ListBase inputs
const char * name
GPUNodeLink * link
GPUNode * node
static constexpr GPUSamplerState internal_sampler()
unsigned int hash_code
GPUUniformAttr * next
void * first
ListBase inputs
ListBase outputs
i
Definition text_draw.cc:230