2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2005 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Brecht Van Lommel.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/gpu/intern/gpu_codegen.c
31 * Convert material node-trees to GLSL.
34 #include "MEM_guardedalloc.h"
36 #include "DNA_customdata_types.h"
37 #include "DNA_image_types.h"
38 #include "DNA_material_types.h"
39 #include "DNA_node_types.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_hash_mm2a.h"
43 #include "BLI_link_utils.h"
44 #include "BLI_utildefines.h"
45 #include "BLI_dynstr.h"
46 #include "BLI_ghash.h"
47 #include "BLI_threads.h"
51 #include "GPU_extensions.h"
53 #include "GPU_material.h"
54 #include "GPU_shader.h"
55 #include "GPU_texture.h"
56 #include "GPU_uniformbuffer.h"
58 #include "BLI_sys_types.h" /* for intptr_t support */
60 #include "gpu_codegen.h"
65 extern char datatoc_gpu_shader_material_glsl[];
66 extern char datatoc_gpu_shader_geometry_glsl[];
68 static char *glsl_material_library = NULL;
70 /* -------------------- GPUPass Cache ------------------ */
72 * Internal shader cache: This prevent the shader recompilation / stall when
73 * using undo/redo AND also allows for GPUPass reuse if the Shader code is the
74 * same for 2 different Materials. Unused GPUPasses are free by Garbage collection.
77 /* Only use one linklist that contains the GPUPasses grouped by hash. */
78 static GPUPass *pass_cache = NULL;
79 static SpinLock pass_cache_spin;
81 static uint32_t gpu_pass_hash(const char *frag_gen, const char *defs, GPUVertexAttribs *attribs)
83 BLI_HashMurmur2A hm2a;
84 BLI_hash_mm2a_init(&hm2a, 0);
85 BLI_hash_mm2a_add(&hm2a, (uchar *)frag_gen, strlen(frag_gen));
87 for (int att_idx = 0; att_idx < attribs->totlayer; att_idx++) {
88 char *name = attribs->layer[att_idx].name;
89 BLI_hash_mm2a_add(&hm2a, (uchar *)name, strlen(name));
93 BLI_hash_mm2a_add(&hm2a, (uchar *)defs, strlen(defs));
95 return BLI_hash_mm2a_end(&hm2a);
98 /* Search by hash only. Return first pass with the same hash.
99 * There is hash collision if (pass->next && pass->next->hash == hash) */
100 static GPUPass *gpu_pass_cache_lookup(uint32_t hash)
102 BLI_spin_lock(&pass_cache_spin);
103 /* Could be optimized with a Lookup table. */
104 for (GPUPass *pass = pass_cache; pass; pass = pass->next) {
105 if (pass->hash == hash) {
106 BLI_spin_unlock(&pass_cache_spin);
110 BLI_spin_unlock(&pass_cache_spin);
114 /* Check all possible passes with the same hash. */
115 static GPUPass *gpu_pass_cache_resolve_collision(
116 GPUPass *pass, const char *vert, const char *geom, const char *frag, const char *defs, uint32_t hash)
118 BLI_spin_lock(&pass_cache_spin);
119 /* Collision, need to strcmp the whole shader. */
120 for (; pass && (pass->hash == hash); pass = pass->next) {
121 if ((defs != NULL) && (strcmp(pass->defines, defs) != 0)) { /* Pass */ }
122 else if ((geom != NULL) && (strcmp(pass->geometrycode, geom) != 0)) { /* Pass */ }
123 else if ((strcmp(pass->fragmentcode, frag) == 0) &&
124 (strcmp(pass->vertexcode, vert) == 0))
126 BLI_spin_unlock(&pass_cache_spin);
130 BLI_spin_unlock(&pass_cache_spin);
134 /* -------------------- GPU Codegen ------------------ */
136 /* type definitions and constants */
138 #define MAX_FUNCTION_NAME 64
139 #define MAX_PARAMETER 32
147 typedef struct GPUFunction {
148 char name[MAX_FUNCTION_NAME];
149 GPUType paramtype[MAX_PARAMETER];
150 GPUFunctionQual paramqual[MAX_PARAMETER];
154 /* Indices match the GPUType enum */
155 static const char *GPU_DATATYPE_STR[17] = {
156 "", "float", "vec2", "vec3", "vec4",
157 NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"
160 /* GLSL code parsing for finding function definitions.
161 * These are stored in a hash for lookup when creating a material. */
163 static GHash *FUNCTION_HASH = NULL;
165 static char *FUNCTION_PROTOTYPES = NULL;
166 static GPUShader *FUNCTION_LIB = NULL;
169 static int gpu_str_prefix(const char *str, const char *prefix)
171 while (*str && *prefix) {
179 return (*prefix == '\0');
182 static char *gpu_str_skip_token(char *str, char *token, int max)
186 /* skip a variable/function name */
188 if (ELEM(*str, ' ', '(', ')', ',', ';', '\t', '\n', '\r'))
191 if (token && len < max - 1) {
203 /* skip the next special characters:
204 * note the missing ')' */
206 if (ELEM(*str, ' ', '(', ',', ';', '\t', '\n', '\r'))
215 static void gpu_parse_functions_string(GHash *hash, char *code)
217 GPUFunction *function;
219 GPUFunctionQual qual;
222 while ((code = strstr(code, "void "))) {
223 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
225 code = gpu_str_skip_token(code, NULL, 0);
226 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
229 while (*code && *code != ')') {
230 /* test if it's an input or output */
231 qual = FUNCTION_QUAL_IN;
232 if (gpu_str_prefix(code, "out "))
233 qual = FUNCTION_QUAL_OUT;
234 if (gpu_str_prefix(code, "inout "))
235 qual = FUNCTION_QUAL_INOUT;
236 if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
237 code = gpu_str_skip_token(code, NULL, 0);
241 for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) {
242 if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
248 if (!type && gpu_str_prefix(code, "samplerCube")) {
251 if (!type && gpu_str_prefix(code, "sampler2DShadow")) {
254 if (!type && gpu_str_prefix(code, "sampler1DArray")) {
255 type = GPU_TEX1D_ARRAY;
257 if (!type && gpu_str_prefix(code, "sampler2D")) {
260 if (!type && gpu_str_prefix(code, "sampler3D")) {
264 if (!type && gpu_str_prefix(code, "Closure")) {
270 code = gpu_str_skip_token(code, NULL, 0);
271 code = gpu_str_skip_token(code, NULL, 0);
272 function->paramqual[function->totparam] = qual;
273 function->paramtype[function->totparam] = type;
274 function->totparam++;
277 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
282 if (function->name[0] == '\0' || function->totparam == 0) {
283 fprintf(stderr, "GPU functions parse error.\n");
288 BLI_ghash_insert(hash, function->name, function);
293 static char *gpu_generate_function_prototyps(GHash *hash)
295 DynStr *ds = BLI_dynstr_new();
297 GPUFunction *function;
298 char *name, *prototypes;
301 /* automatically generate function prototypes to add to the top of the
302 * generated code, to avoid have to add the actual code & recompile all */
303 ghi = BLI_ghashIterator_new(hash);
305 for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
306 name = BLI_ghashIterator_getValue(ghi);
307 function = BLI_ghashIterator_getValue(ghi);
309 BLI_dynstr_appendf(ds, "void %s(", name);
310 for (a = 0; a < function->totparam; a++) {
311 if (function->paramqual[a] == FUNCTION_QUAL_OUT)
312 BLI_dynstr_append(ds, "out ");
313 else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
314 BLI_dynstr_append(ds, "inout ");
316 if (function->paramtype[a] == GPU_TEX2D)
317 BLI_dynstr_append(ds, "sampler2D");
318 else if (function->paramtype[a] == GPU_SHADOW2D)
319 BLI_dynstr_append(ds, "sampler2DShadow");
321 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
323 BLI_dynstr_appendf(ds, " param%d", a);
326 if (a != function->totparam - 1)
327 BLI_dynstr_append(ds, ", ");
329 BLI_dynstr_append(ds, ");\n");
332 BLI_dynstr_append(ds, "\n");
334 prototypes = BLI_dynstr_get_cstring(ds);
341 static GPUFunction *gpu_lookup_function(const char *name)
343 if (!FUNCTION_HASH) {
344 FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
345 gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
348 return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
351 void gpu_codegen_init(void)
353 GPU_code_generate_glsl_lib();
356 void gpu_codegen_exit(void)
358 extern Material defmaterial; /* render module abuse... */
360 if (defmaterial.gpumaterial.first)
361 GPU_material_free(&defmaterial.gpumaterial);
364 BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
365 FUNCTION_HASH = NULL;
368 GPU_shader_free_builtin_shaders();
370 if (glsl_material_library) {
371 MEM_freeN(glsl_material_library);
372 glsl_material_library = NULL;
376 if (FUNCTION_PROTOTYPES) {
377 MEM_freeN(FUNCTION_PROTOTYPES);
378 FUNCTION_PROTOTYPES = NULL;
381 GPU_shader_free(FUNCTION_LIB);
387 /* GLSL code generation */
389 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
393 BLI_snprintf(name, sizeof(name), "%s%d", tmp, id);
396 BLI_dynstr_append(ds, name);
398 else if (to == GPU_FLOAT) {
399 if (from == GPU_VEC4)
400 BLI_dynstr_appendf(ds, "convert_rgba_to_float(%s)", name);
401 else if (from == GPU_VEC3)
402 BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name);
403 else if (from == GPU_VEC2)
404 BLI_dynstr_appendf(ds, "%s.r", name);
406 else if (to == GPU_VEC2) {
407 if (from == GPU_VEC4)
408 BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, %s.a)", name, name, name, name);
409 else if (from == GPU_VEC3)
410 BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, 1.0)", name, name, name);
411 else if (from == GPU_FLOAT)
412 BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
414 else if (to == GPU_VEC3) {
415 if (from == GPU_VEC4)
416 BLI_dynstr_appendf(ds, "%s.rgb", name);
417 else if (from == GPU_VEC2)
418 BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
419 else if (from == GPU_FLOAT)
420 BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name);
422 else if (to == GPU_VEC4) {
423 if (from == GPU_VEC3)
424 BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name);
425 else if (from == GPU_VEC2)
426 BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
427 else if (from == GPU_FLOAT)
428 BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
430 else if (to == GPU_CLOSURE) {
431 if (from == GPU_VEC4)
432 BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name);
433 else if (from == GPU_VEC3)
434 BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name);
435 else if (from == GPU_VEC2)
436 BLI_dynstr_appendf(ds, "closure_emission(%s.rrr)", name);
437 else if (from == GPU_FLOAT)
438 BLI_dynstr_appendf(ds, "closure_emission(vec3(%s, %s, %s))", name, name, name);
441 BLI_dynstr_append(ds, name);
445 static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
449 BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
451 for (i = 0; i < type; i++) {
452 BLI_dynstr_appendf(ds, "%.12f", data[i]);
454 BLI_dynstr_append(ds, ")");
456 BLI_dynstr_append(ds, ", ");
460 static int codegen_input_has_texture(GPUInput *input)
465 return (input->source == GPU_SOURCE_TEX);
468 const char *GPU_builtin_name(GPUBuiltin builtin)
470 if (builtin == GPU_VIEW_MATRIX)
472 else if (builtin == GPU_OBJECT_MATRIX)
474 else if (builtin == GPU_INVERSE_VIEW_MATRIX)
475 return "unfinvviewmat";
476 else if (builtin == GPU_INVERSE_OBJECT_MATRIX)
477 return "unfinvobmat";
478 else if (builtin == GPU_LOC_TO_VIEW_MATRIX)
479 return "unflocaltoviewmat";
480 else if (builtin == GPU_INVERSE_LOC_TO_VIEW_MATRIX)
481 return "unfinvlocaltoviewmat";
482 else if (builtin == GPU_VIEW_POSITION)
483 return "varposition";
484 else if (builtin == GPU_VIEW_NORMAL)
486 else if (builtin == GPU_OBCOLOR)
488 else if (builtin == GPU_AUTO_BUMPSCALE)
489 return "unfobautobumpscale";
490 else if (builtin == GPU_CAMERA_TEXCO_FACTORS)
491 return "unfcameratexfactors";
492 else if (builtin == GPU_PARTICLE_SCALAR_PROPS)
493 return "unfparticlescalarprops";
494 else if (builtin == GPU_PARTICLE_LOCATION)
495 return "unfparticleco";
496 else if (builtin == GPU_PARTICLE_VELOCITY)
497 return "unfparticlevel";
498 else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
499 return "unfparticleangvel";
500 else if (builtin == GPU_OBJECT_INFO)
501 return "unfobjectinfo";
502 else if (builtin == GPU_VOLUME_DENSITY)
503 return "sampdensity";
504 else if (builtin == GPU_VOLUME_FLAME)
506 else if (builtin == GPU_VOLUME_TEMPERATURE)
507 return "unftemperature";
508 else if (builtin == GPU_BARYCENTRIC_TEXCO)
509 return "unfbarycentrictex";
510 else if (builtin == GPU_BARYCENTRIC_DIST)
511 return "unfbarycentricdist";
516 /* assign only one texid per buffer to avoid sampling the same texture twice */
517 static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
519 if (BLI_ghash_haskey(bindhash, key)) {
520 /* Reuse existing texid */
521 input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, key));
524 /* Allocate new texid */
525 input->texid = *texid;
527 input->bindtex = true;
528 BLI_ghash_insert(bindhash, key, POINTER_FROM_INT(input->texid));
532 static void codegen_set_unique_ids(ListBase *nodes)
538 int id = 1, texid = 0;
540 bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
542 for (node = nodes->first; node; node = node->next) {
543 for (input = node->inputs.first; input; input = input->next) {
544 /* set id for unique names of uniform variables */
547 /* set texid used for settings texture slot */
548 if (codegen_input_has_texture(input)) {
549 input->bindtex = false;
551 /* input is texture from image */
552 codegen_set_texid(bindhash, input, &texid, input->ima);
554 else if (input->coba) {
555 /* input is color band texture, check coba pointer */
556 codegen_set_texid(bindhash, input, &texid, input->coba);
559 /* Either input->ima or input->coba should be non-NULL. */
565 for (output = node->outputs.first; output; output = output->next) {
566 /* set id for unique names of tmp variables storing output */
571 BLI_ghash_free(bindhash, NULL, NULL);
575 * It will create an UBO for GPUMaterial if there is any GPU_DYNAMIC_UBO.
577 static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes)
583 ListBase ubo_inputs = {NULL, NULL};
586 for (node = nodes->first; node; node = node->next) {
587 for (input = node->inputs.first; input; input = input->next) {
588 if (input->source == GPU_SOURCE_TEX) {
589 /* create exactly one sampler for each texture */
590 if (codegen_input_has_texture(input) && input->bindtex) {
592 ds, "uniform %s samp%d;\n",
593 (input->coba) ? "sampler1DArray" : "sampler2D",
597 else if (input->source == GPU_SOURCE_BUILTIN) {
598 /* only define each builtin uniform/varying once */
599 if (!(builtins & input->builtin)) {
600 builtins |= input->builtin;
601 name = GPU_builtin_name(input->builtin);
603 if (gpu_str_prefix(name, "samp")) {
604 if ((input->builtin == GPU_VOLUME_DENSITY) ||
605 (input->builtin == GPU_VOLUME_FLAME))
607 BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
610 else if (gpu_str_prefix(name, "unf")) {
612 ds, "uniform %s %s;\n",
613 GPU_DATATYPE_STR[input->type], name);
618 GPU_DATATYPE_STR[input->type], name);
622 else if (input->source == GPU_SOURCE_STRUCT) {
623 /* Add other struct here if needed. */
624 BLI_dynstr_appendf(ds, "Closure strct%d = CLOSURE_DEFAULT;\n", input->id);
626 else if (input->source == GPU_SOURCE_UNIFORM) {
628 /* We handle the UBOuniforms separately. */
629 BLI_addtail(&ubo_inputs, BLI_genericNodeN(input));
632 else if (input->source == GPU_SOURCE_CONSTANT) {
634 ds, "const %s cons%d = ",
635 GPU_DATATYPE_STR[input->type], input->id);
636 codegen_print_datatype(ds, input->type, input->vec);
637 BLI_dynstr_append(ds, ";\n");
639 else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
641 ds, "in %s var%d;\n",
642 GPU_DATATYPE_STR[input->type], input->attribid);
647 /* Handle the UBO block separately. */
648 if ((material != NULL) && !BLI_listbase_is_empty(&ubo_inputs)) {
649 GPU_material_uniform_buffer_create(material, &ubo_inputs);
651 /* Inputs are sorted */
652 BLI_dynstr_appendf(ds, "\nlayout (std140) uniform %s {\n", GPU_UBO_BLOCK_NAME);
654 for (LinkData *link = ubo_inputs.first; link; link = link->next) {
658 GPU_DATATYPE_STR[input->type], input->id);
660 BLI_dynstr_append(ds, "};\n");
661 BLI_freelistN(&ubo_inputs);
664 BLI_dynstr_append(ds, "\n");
669 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
674 for (node = nodes->first; node; node = node->next) {
675 /* declare temporary variables for node output storage */
676 for (output = node->outputs.first; output; output = output->next) {
677 if (output->type == GPU_CLOSURE) {
679 ds, "\tClosure tmp%d;\n", output->id);
684 GPU_DATATYPE_STR[output->type], output->id);
689 BLI_dynstr_append(ds, "\n");
692 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
698 for (node = nodes->first; node; node = node->next) {
699 BLI_dynstr_appendf(ds, "\t%s(", node->name);
701 for (input = node->inputs.first; input; input = input->next) {
702 if (input->source == GPU_SOURCE_TEX) {
703 BLI_dynstr_appendf(ds, "samp%d", input->texid);
705 else if (input->source == GPU_SOURCE_OUTPUT) {
706 codegen_convert_datatype(
707 ds, input->link->output->type, input->type,
708 "tmp", input->link->output->id);
710 else if (input->source == GPU_SOURCE_BUILTIN) {
711 /* TODO(fclem) get rid of that. */
712 if (input->builtin == GPU_INVERSE_VIEW_MATRIX)
713 BLI_dynstr_append(ds, "viewinv");
714 else if (input->builtin == GPU_VIEW_MATRIX)
715 BLI_dynstr_append(ds, "viewmat");
716 else if (input->builtin == GPU_CAMERA_TEXCO_FACTORS)
717 BLI_dynstr_append(ds, "camtexfac");
718 else if (input->builtin == GPU_LOC_TO_VIEW_MATRIX)
719 BLI_dynstr_append(ds, "localtoviewmat");
720 else if (input->builtin == GPU_INVERSE_LOC_TO_VIEW_MATRIX)
721 BLI_dynstr_append(ds, "invlocaltoviewmat");
722 else if (input->builtin == GPU_BARYCENTRIC_DIST)
723 BLI_dynstr_append(ds, "barycentricDist");
724 else if (input->builtin == GPU_BARYCENTRIC_TEXCO)
725 BLI_dynstr_append(ds, "barytexco");
726 else if (input->builtin == GPU_OBJECT_MATRIX)
727 BLI_dynstr_append(ds, "objmat");
728 else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX)
729 BLI_dynstr_append(ds, "objinv");
730 else if (input->builtin == GPU_VIEW_POSITION)
731 BLI_dynstr_append(ds, "viewposition");
732 else if (input->builtin == GPU_VIEW_NORMAL)
733 BLI_dynstr_append(ds, "facingnormal");
735 BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
737 else if (input->source == GPU_SOURCE_STRUCT) {
738 BLI_dynstr_appendf(ds, "strct%d", input->id);
740 else if (input->source == GPU_SOURCE_UNIFORM) {
741 BLI_dynstr_appendf(ds, "unf%d", input->id);
743 else if (input->source == GPU_SOURCE_CONSTANT) {
744 BLI_dynstr_appendf(ds, "cons%d", input->id);
746 else if (input->source == GPU_SOURCE_ATTRIB) {
747 BLI_dynstr_appendf(ds, "var%d", input->attribid);
750 BLI_dynstr_append(ds, ", ");
753 for (output = node->outputs.first; output; output = output->next) {
754 BLI_dynstr_appendf(ds, "tmp%d", output->id);
756 BLI_dynstr_append(ds, ", ");
759 BLI_dynstr_append(ds, ");\n");
762 BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id);
763 BLI_dynstr_append(ds, ";\n");
766 static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output, int *rbuiltins)
768 DynStr *ds = BLI_dynstr_new();
773 BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
776 codegen_set_unique_ids(nodes);
777 *rbuiltins = builtins = codegen_process_uniforms_functions(material, ds, nodes);
779 if (builtins & GPU_BARYCENTRIC_TEXCO)
780 BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n");
782 if (builtins & GPU_BARYCENTRIC_DIST)
783 BLI_dynstr_append(ds, "flat in vec3 barycentricDist;\n");
785 BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n");
787 if (builtins & GPU_BARYCENTRIC_TEXCO) {
788 BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
789 BLI_dynstr_append(ds, "\tvec2 barytexco = vec2((fract(barycentricTexCo.y) != 0.0)\n"
790 "\t ? barycentricTexCo.x\n"
791 "\t : 1.0 - barycentricTexCo.x,\n"
793 BLI_dynstr_append(ds, "#else\n");
794 BLI_dynstr_append(ds, "\tvec2 barytexco = barycentricTexCo;\n");
795 BLI_dynstr_append(ds, "#endif\n");
797 /* TODO(fclem) get rid of that. */
798 if (builtins & GPU_VIEW_MATRIX)
799 BLI_dynstr_append(ds, "\t#define viewmat ViewMatrix\n");
800 if (builtins & GPU_CAMERA_TEXCO_FACTORS)
801 BLI_dynstr_append(ds, "\t#define camtexfac CameraTexCoFactors\n");
802 if (builtins & GPU_OBJECT_MATRIX)
803 BLI_dynstr_append(ds, "\t#define objmat ModelMatrix\n");
804 if (builtins & GPU_INVERSE_OBJECT_MATRIX)
805 BLI_dynstr_append(ds, "\t#define objinv ModelMatrixInverse\n");
806 if (builtins & GPU_INVERSE_VIEW_MATRIX)
807 BLI_dynstr_append(ds, "\t#define viewinv ViewMatrixInverse\n");
808 if (builtins & GPU_LOC_TO_VIEW_MATRIX)
809 BLI_dynstr_append(ds, "\t#define localtoviewmat ModelViewMatrix\n");
810 if (builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX)
811 BLI_dynstr_append(ds, "\t#define invlocaltoviewmat ModelViewMatrixInverse\n");
812 if (builtins & GPU_VIEW_NORMAL)
813 BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n");
814 if (builtins & GPU_VIEW_POSITION)
815 BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n");
817 codegen_declare_tmps(ds, nodes);
818 codegen_call_functions(ds, nodes, output);
820 BLI_dynstr_append(ds, "}\n");
822 /* XXX This cannot go into gpu_shader_material.glsl because main() would be parsed and generate error */
823 /* Old glsl mode compat. */
824 BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n");
825 BLI_dynstr_append(ds, "out vec4 fragColor;\n");
826 BLI_dynstr_append(ds, "void main()\n");
827 BLI_dynstr_append(ds, "{\n");
828 BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n");
829 BLI_dynstr_append(ds, "\tfragColor = vec4(cl.radiance, cl.opacity);\n");
830 BLI_dynstr_append(ds, "}\n");
831 BLI_dynstr_append(ds, "#endif\n\n");
834 code = BLI_dynstr_get_cstring(ds);
838 if (G.debug & G_DEBUG) printf("%s\n", code);
844 static const char *attrib_prefix_get(CustomDataType type)
847 case CD_ORCO: return "orco";
848 case CD_MTFACE: return "u";
849 case CD_TANGENT: return "t";
850 case CD_MCOL: return "c";
851 case CD_AUTO_FROM_NAME: return "a";
852 default: BLI_assert(false && "GPUVertAttr Prefix type not found : This should not happen!"); return "";
856 static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool use_geom)
858 DynStr *ds = BLI_dynstr_new();
864 /* Hairs uv and col attribs are passed by bufferTextures. */
867 "#ifdef HAIR_SHADER\n"
868 "#define DEFINE_ATTRIB(type, attr) uniform samplerBuffer attr\n"
870 "#define DEFINE_ATTRIB(type, attr) in type attr\n"
874 for (node = nodes->first; node; node = node->next) {
875 for (input = node->inputs.first; input; input = input->next) {
876 if (input->source == GPU_SOURCE_BUILTIN) {
877 builtins |= input->builtin;
879 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
880 /* XXX FIXME : see notes in mesh_render_data_create() */
881 /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
882 if (input->attribtype == CD_ORCO) {
883 /* orco is computed from local positions, see below */
884 BLI_dynstr_appendf(ds, "uniform vec3 OrcoTexCoFactors[2];\n");
886 else if (input->attribname[0] == '\0') {
887 BLI_dynstr_appendf(ds, "DEFINE_ATTRIB(%s, %s);\n", GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype));
888 BLI_dynstr_appendf(ds, "#define att%d %s\n", input->attribid, attrib_prefix_get(input->attribtype));
891 uint hash = BLI_ghashutil_strhash_p(input->attribname);
893 ds, "DEFINE_ATTRIB(%s, %s%u);\n",
894 GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype), hash);
896 ds, "#define att%d %s%u\n",
897 input->attribid, attrib_prefix_get(input->attribtype), hash);
898 /* Auto attrib can be vertex color byte buffer.
899 * We need to know and convert them to linear space in VS. */
900 if (!use_geom && input->attribtype == CD_AUTO_FROM_NAME) {
901 BLI_dynstr_appendf(ds, "uniform bool ba%u;\n", hash);
902 BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%u\n", input->attribid, hash);
906 ds, "out %s var%d%s;\n",
907 GPU_DATATYPE_STR[input->type], input->attribid, use_geom ? "g" : "");
912 if (builtins & GPU_BARYCENTRIC_TEXCO) {
914 ds, "out vec2 barycentricTexCo%s;\n",
915 use_geom ? "g" : "");
918 if (builtins & GPU_BARYCENTRIC_DIST) {
919 BLI_dynstr_appendf(ds, "out vec3 barycentricPosg;\n");
923 BLI_dynstr_append(ds, "\n");
928 "uniform mat3 NormalMatrix;\n"
929 "uniform mat4 ModelMatrixInverse;\n"
930 "uniform mat4 ModelMatrix;\n"
931 "vec3 srgb_to_linear_attrib(vec3 c) {\n"
932 "\tc = max(c, vec3(0.0));\n"
933 "\tvec3 c1 = c * (1.0 / 12.92);\n"
934 "\tvec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));\n"
935 "\treturn mix(c1, c2, step(vec3(0.04045), c));\n"
939 /* Prototype because defined later. */
942 "vec2 hair_get_customdata_vec2(const samplerBuffer);\n"
943 "vec3 hair_get_customdata_vec3(const samplerBuffer);\n"
944 "vec4 hair_get_customdata_vec4(const samplerBuffer);\n"
945 "vec3 hair_get_strand_pos(void);\n"
946 "int hair_get_base_id(void);\n"
950 BLI_dynstr_append(ds, "void pass_attrib(in vec3 position) {\n");
952 BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
954 if (builtins & GPU_BARYCENTRIC_TEXCO) {
955 /* To match cycles without breaking into individual segment we encode if we need to invert
956 * the first component into the second component. We invert if the barycentricTexCo.y
957 * is NOT 0.0 or 1.0. */
959 ds, "\tint _base_id = hair_get_base_id();\n");
961 ds, "\tbarycentricTexCo%s.x = float((_base_id %% 2) == 1);\n",
962 use_geom ? "g" : "");
964 ds, "\tbarycentricTexCo%s.y = float(((_base_id %% 4) %% 3) > 0);\n",
965 use_geom ? "g" : "");
968 if (builtins & GPU_BARYCENTRIC_DIST) {
969 BLI_dynstr_appendf(ds, "\tbarycentricPosg = position;\n");
972 for (node = nodes->first; node; node = node->next) {
973 for (input = node->inputs.first; input; input = input->next) {
974 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
975 if (input->attribtype == CD_TANGENT) {
976 /* Not supported by hairs */
978 ds, "\tvar%d%s = vec4(0.0);\n",
979 input->attribid, use_geom ? "g" : "");
981 else if (input->attribtype == CD_ORCO) {
983 ds, "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n",
984 input->attribid, use_geom ? "g" : "");
988 ds, "\tvar%d%s = hair_get_customdata_%s(att%d);\n",
989 input->attribid, use_geom ? "g" : "", GPU_DATATYPE_STR[input->type], input->attribid);
995 BLI_dynstr_append(ds, "#else /* MESH_SHADER */\n");
997 if (builtins & GPU_BARYCENTRIC_TEXCO) {
999 ds, "\tbarycentricTexCo%s.x = float((gl_VertexID %% 3) == 0);\n",
1000 use_geom ? "g" : "");
1002 ds, "\tbarycentricTexCo%s.y = float((gl_VertexID %% 3) == 1);\n",
1003 use_geom ? "g" : "");
1006 if (builtins & GPU_BARYCENTRIC_DIST) {
1007 BLI_dynstr_appendf(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n");
1010 for (node = nodes->first; node; node = node->next) {
1011 for (input = node->inputs.first; input; input = input->next) {
1012 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
1013 if (input->attribtype == CD_TANGENT) { /* silly exception */
1015 ds, "\tvar%d%s.xyz = normalize(NormalMatrix * att%d.xyz);\n",
1016 input->attribid, use_geom ? "g" : "", input->attribid);
1018 ds, "\tvar%d%s.w = att%d.w;\n",
1019 input->attribid, use_geom ? "g" : "", input->attribid);
1021 else if (input->attribtype == CD_ORCO) {
1023 ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
1024 input->attribid, use_geom ? "g" : "");
1026 else if (input->attribtype == CD_MCOL) {
1028 ds, "\tvar%d%s = srgb_to_linear_attrib(att%d);\n",
1029 input->attribid, use_geom ? "g" : "", input->attribid);
1031 else if (input->attribtype == CD_AUTO_FROM_NAME) {
1033 ds, "\tvar%d%s = (att%d_is_srgb) ? srgb_to_linear_attrib(att%d) : att%d;\n",
1034 input->attribid, use_geom ? "g" : "",
1035 input->attribid, input->attribid, input->attribid);
1039 ds, "\tvar%d%s = att%d;\n",
1040 input->attribid, use_geom ? "g" : "", input->attribid);
1045 BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n");
1047 BLI_dynstr_append(ds, "}\n");
1050 /* XXX HACK: Eevee specific. */
1051 char *vert_new, *vert_new2;
1052 vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong");
1053 vert_new2 = vert_new;
1054 vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong");
1055 MEM_freeN(vert_new2);
1056 vert_new2 = vert_new;
1057 vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg");
1058 MEM_freeN(vert_new2);
1059 vert_new2 = vert_new;
1060 vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg");
1061 MEM_freeN(vert_new2);
1063 BLI_dynstr_append(ds, vert_new);
1065 MEM_freeN(vert_new);
1068 BLI_dynstr_append(ds, vert_code);
1071 code = BLI_dynstr_get_cstring(ds);
1073 BLI_dynstr_free(ds);
1076 if (G.debug & G_DEBUG) printf("%s\n", code);
1082 static char *code_generate_geometry(ListBase *nodes, const char *geom_code)
1084 DynStr *ds = BLI_dynstr_new();
1090 /* Create prototype because attributes cannot be declared before layout. */
1091 BLI_dynstr_appendf(ds, "void pass_attrib(in int vert);\n");
1092 BLI_dynstr_appendf(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2);\n");
1093 BLI_dynstr_append(ds, "#define ATTRIB\n");
1095 /* Generate varying declarations. */
1096 for (node = nodes->first; node; node = node->next) {
1097 for (input = node->inputs.first; input; input = input->next) {
1098 if (input->source == GPU_SOURCE_BUILTIN) {
1099 builtins |= input->builtin;
1101 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
1103 ds, "in %s var%dg[];\n",
1104 GPU_DATATYPE_STR[input->type],
1107 ds, "out %s var%d;\n",
1108 GPU_DATATYPE_STR[input->type],
1114 if (builtins & GPU_BARYCENTRIC_TEXCO) {
1115 BLI_dynstr_appendf(ds, "in vec2 barycentricTexCog[];\n");
1116 BLI_dynstr_appendf(ds, "out vec2 barycentricTexCo;\n");
1119 if (builtins & GPU_BARYCENTRIC_DIST) {
1120 BLI_dynstr_appendf(ds, "in vec3 barycentricPosg[];\n");
1121 BLI_dynstr_appendf(ds, "flat out vec3 barycentricDist;\n");
1124 if (geom_code == NULL) {
1125 if ((builtins & GPU_BARYCENTRIC_DIST) == 0) {
1127 BLI_dynstr_free(ds);
1131 /* Force geom shader usage */
1132 /* TODO put in external file. */
1133 BLI_dynstr_appendf(ds, "layout(triangles) in;\n");
1134 BLI_dynstr_appendf(ds, "layout(triangle_strip, max_vertices=3) out;\n");
1136 BLI_dynstr_appendf(ds, "in vec3 worldPositiong[];\n");
1137 BLI_dynstr_appendf(ds, "in vec3 viewPositiong[];\n");
1138 BLI_dynstr_appendf(ds, "in vec3 worldNormalg[];\n");
1139 BLI_dynstr_appendf(ds, "in vec3 viewNormalg[];\n");
1141 BLI_dynstr_appendf(ds, "out vec3 worldPosition;\n");
1142 BLI_dynstr_appendf(ds, "out vec3 viewPosition;\n");
1143 BLI_dynstr_appendf(ds, "out vec3 worldNormal;\n");
1144 BLI_dynstr_appendf(ds, "out vec3 viewNormal;\n");
1146 BLI_dynstr_appendf(ds, "void main(){\n");
1148 if (builtins & GPU_BARYCENTRIC_DIST) {
1149 BLI_dynstr_appendf(ds, "\tcalc_barycentric_distances(barycentricPosg[0], barycentricPosg[1], barycentricPosg[2]);\n");
1152 BLI_dynstr_appendf(ds, "\tgl_Position = gl_in[0].gl_Position;\n");
1153 BLI_dynstr_appendf(ds, "\tpass_attrib(0);\n");
1154 BLI_dynstr_appendf(ds, "\tEmitVertex();\n");
1156 BLI_dynstr_appendf(ds, "\tgl_Position = gl_in[1].gl_Position;\n");
1157 BLI_dynstr_appendf(ds, "\tpass_attrib(1);\n");
1158 BLI_dynstr_appendf(ds, "\tEmitVertex();\n");
1160 BLI_dynstr_appendf(ds, "\tgl_Position = gl_in[2].gl_Position;\n");
1161 BLI_dynstr_appendf(ds, "\tpass_attrib(2);\n");
1162 BLI_dynstr_appendf(ds, "\tEmitVertex();\n");
1163 BLI_dynstr_appendf(ds, "};\n");
1167 BLI_dynstr_append(ds, geom_code);
1170 if (builtins & GPU_BARYCENTRIC_DIST) {
1171 BLI_dynstr_appendf(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2) {\n");
1172 BLI_dynstr_appendf(ds, "\tvec3 edge21 = pos2 - pos1;\n");
1173 BLI_dynstr_appendf(ds, "\tvec3 edge10 = pos1 - pos0;\n");
1174 BLI_dynstr_appendf(ds, "\tvec3 edge02 = pos0 - pos2;\n");
1175 BLI_dynstr_appendf(ds, "\tvec3 d21 = normalize(edge21);\n");
1176 BLI_dynstr_appendf(ds, "\tvec3 d10 = normalize(edge10);\n");
1177 BLI_dynstr_appendf(ds, "\tvec3 d02 = normalize(edge02);\n");
1179 BLI_dynstr_appendf(ds, "\tfloat d = dot(d21, edge02);\n");
1180 BLI_dynstr_appendf(ds, "\tbarycentricDist.x = sqrt(dot(edge02, edge02) - d * d);\n");
1181 BLI_dynstr_appendf(ds, "\td = dot(d02, edge10);\n");
1182 BLI_dynstr_appendf(ds, "\tbarycentricDist.y = sqrt(dot(edge10, edge10) - d * d);\n");
1183 BLI_dynstr_appendf(ds, "\td = dot(d10, edge21);\n");
1184 BLI_dynstr_appendf(ds, "\tbarycentricDist.z = sqrt(dot(edge21, edge21) - d * d);\n");
1185 BLI_dynstr_append(ds, "}\n");
1188 /* Generate varying assignments. */
1189 BLI_dynstr_appendf(ds, "void pass_attrib(in int vert) {\n");
1191 /* XXX HACK: Eevee specific. */
1192 if (geom_code == NULL) {
1193 BLI_dynstr_appendf(ds, "\tworldPosition = worldPositiong[vert];\n");
1194 BLI_dynstr_appendf(ds, "\tviewPosition = viewPositiong[vert];\n");
1195 BLI_dynstr_appendf(ds, "\tworldNormal = worldNormalg[vert];\n");
1196 BLI_dynstr_appendf(ds, "\tviewNormal = viewNormalg[vert];\n");
1199 if (builtins & GPU_BARYCENTRIC_TEXCO) {
1200 BLI_dynstr_appendf(ds, "\tbarycentricTexCo = barycentricTexCog[vert];\n");
1203 for (node = nodes->first; node; node = node->next) {
1204 for (input = node->inputs.first; input; input = input->next) {
1205 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
1206 /* TODO let shader choose what to do depending on what the attrib is. */
1207 BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attribid, input->attribid);
1211 BLI_dynstr_append(ds, "}\n");
1213 code = BLI_dynstr_get_cstring(ds);
1214 BLI_dynstr_free(ds);
1219 void GPU_code_generate_glsl_lib(void)
1223 /* only initialize the library once */
1224 if (glsl_material_library)
1227 ds = BLI_dynstr_new();
1229 BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
1232 glsl_material_library = BLI_dynstr_get_cstring(ds);
1234 BLI_dynstr_free(ds);
1238 /* GPU pass binding/unbinding */
1240 GPUShader *GPU_pass_shader_get(GPUPass *pass)
1242 return pass->shader;
1245 void GPU_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListBase *nodes)
1248 GPUInput *next, *input;
1250 BLI_listbase_clear(inputs);
1255 GPU_shader_bind(shader);
1257 for (node = nodes->first; node; node = node->next) {
1259 for (input = node->inputs.first; input; input = next, z++) {
1262 /* attributes don't need to be bound, they already have
1263 * an id that the drawing functions will use. Builtins have
1264 * constant names. */
1265 if (ELEM(input->source, GPU_SOURCE_ATTRIB, GPU_SOURCE_BUILTIN)) {
1269 if (input->source == GPU_SOURCE_TEX)
1270 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
1272 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
1275 if (input->source == GPU_SOURCE_TEX) {
1276 if (input->bindtex) {
1277 input->shaderloc = GPU_shader_get_uniform_ensure(shader, input->shadername);
1279 BLI_remlink(&node->inputs, input);
1280 BLI_addtail(inputs, input);
1286 GPU_shader_unbind();
1289 /* Node Link Functions */
1291 static GPUNodeLink *GPU_node_link_create(void)
1293 GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
1299 static void gpu_node_link_free(GPUNodeLink *link)
1303 if (link->users < 0)
1304 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
1306 if (link->users == 0) {
1308 link->output->link = NULL;
1313 /* Node Functions */
1315 static GPUNode *GPU_node_begin(const char *name)
1317 GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
1324 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
1330 if (link->link_type == GPU_NODE_LINK_OUTPUT) {
1331 outnode = link->output->node;
1332 name = outnode->name;
1333 input = outnode->inputs.first;
1335 if ((STREQ(name, "set_value") || STREQ(name, "set_rgb") || STREQ(name, "set_rgba")) &&
1336 (input->type == type))
1338 input = MEM_dupallocN(outnode->inputs.first);
1340 input->link->users++;
1341 BLI_addtail(&node->inputs, input);
1346 input = MEM_callocN(sizeof(GPUInput), "GPUInput");
1350 switch (link->link_type) {
1351 case GPU_NODE_LINK_BUILTIN:
1352 input->source = GPU_SOURCE_BUILTIN;
1353 input->builtin = link->builtin;
1355 case GPU_NODE_LINK_OUTPUT:
1356 input->source = GPU_SOURCE_OUTPUT;
1360 case GPU_NODE_LINK_COLORBAND:
1361 input->source = GPU_SOURCE_TEX;
1362 input->coba = link->coba;
1364 case GPU_NODE_LINK_IMAGE_BLENDER:
1365 input->source = GPU_SOURCE_TEX;
1366 input->ima = link->ima;
1367 input->iuser = link->iuser;
1368 input->image_isdata = link->image_isdata;
1370 case GPU_NODE_LINK_ATTRIB:
1371 input->source = GPU_SOURCE_ATTRIB;
1372 input->attribtype = link->attribtype;
1373 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
1375 case GPU_NODE_LINK_CONSTANT:
1376 input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
1378 case GPU_NODE_LINK_UNIFORM:
1379 input->source = GPU_SOURCE_UNIFORM;
1385 if (ELEM(input->source, GPU_SOURCE_CONSTANT, GPU_SOURCE_UNIFORM)) {
1386 memcpy(input->vec, link->data, type * sizeof(float));
1389 if (link->link_type != GPU_NODE_LINK_OUTPUT) {
1392 BLI_addtail(&node->inputs, input);
1396 static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
1406 BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
1412 * Link stack uniform buffer.
1413 * This is called for the input/output sockets that are note connected.
1415 static GPUNodeLink *gpu_uniformbuffer_link(
1416 GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index, const eNodeSocketInOut in_out)
1418 bNodeSocket *socket;
1420 if (in_out == SOCK_IN) {
1421 socket = BLI_findlink(&node->inputs, index);
1424 socket = BLI_findlink(&node->outputs, index);
1427 BLI_assert(socket != NULL);
1428 BLI_assert(socket->in_out == in_out);
1430 if ((socket->flag & SOCK_HIDE_VALUE) == 0) {
1432 switch (socket->type) {
1435 bNodeSocketValueFloat *socket_data = socket->default_value;
1436 link = GPU_uniform(&socket_data->value);
1441 bNodeSocketValueVector *socket_data = socket->default_value;
1442 link = GPU_uniform(socket_data->value);
1447 bNodeSocketValueRGBA *socket_data = socket->default_value;
1448 link = GPU_uniform(socket_data->value);
1456 if (in_out == SOCK_IN) {
1457 GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link);
1464 static void gpu_node_input_socket(GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
1467 gpu_node_input_link(node, sock->link, sock->type);
1469 else if ((material != NULL) && (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) {
1470 gpu_node_input_link(node, sock->link, sock->type);
1473 gpu_node_input_link(node, GPU_constant(sock->vec), sock->type);
1477 static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
1479 GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1481 output->type = type;
1482 output->node = node;
1485 *link = output->link = GPU_node_link_create();
1486 output->link->link_type = GPU_NODE_LINK_OUTPUT;
1487 output->link->output = output;
1489 /* note: the caller owns the reference to the link, GPUOutput
1490 * merely points to it, and if the node is destroyed it will
1491 * set that pointer to NULL */
1494 BLI_addtail(&node->outputs, output);
1497 void GPU_inputs_free(ListBase *inputs)
1501 for (input = inputs->first; input; input = input->next) {
1503 gpu_node_link_free(input->link);
1506 BLI_freelistN(inputs);
1509 static void gpu_node_free(GPUNode *node)
1513 GPU_inputs_free(&node->inputs);
1515 for (output = node->outputs.first; output; output = output->next)
1517 output->link->output = NULL;
1518 gpu_node_link_free(output->link);
1521 BLI_freelistN(&node->outputs);
1525 static void gpu_nodes_free(ListBase *nodes)
1529 while ((node = BLI_pophead(nodes))) {
1530 gpu_node_free(node);
1534 /* vertex attributes */
1536 void GPU_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1542 /* convert attributes requested by node inputs to an array of layers,
1543 * checking for duplicates and assigning id's starting from zero. */
1545 memset(attribs, 0, sizeof(*attribs));
1547 for (node = nodes->first; node; node = node->next) {
1548 for (input = node->inputs.first; input; input = input->next) {
1549 if (input->source == GPU_SOURCE_ATTRIB) {
1550 for (a = 0; a < attribs->totlayer; a++) {
1551 if (attribs->layer[a].type == input->attribtype &&
1552 STREQ(attribs->layer[a].name, input->attribname))
1558 if (a < GPU_MAX_ATTRIB) {
1559 if (a == attribs->totlayer) {
1560 input->attribid = attribs->totlayer++;
1561 input->attribfirst = true;
1563 attribs->layer[a].type = input->attribtype;
1564 attribs->layer[a].attribid = input->attribid;
1566 attribs->layer[a].name, input->attribname,
1567 sizeof(attribs->layer[a].name));
1570 input->attribid = attribs->layer[a].attribid;
1578 /* varargs linking */
1580 GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
1582 GPUNodeLink *link = GPU_node_link_create();
1583 link->link_type = GPU_NODE_LINK_ATTRIB;
1584 link->attribname = name;
1585 /* Fall back to the UV layer, which matches old behavior. */
1586 if (type == CD_AUTO_FROM_NAME && name[0] == '\0') {
1587 link->attribtype = CD_MTFACE;
1590 link->attribtype = type;
1595 GPUNodeLink *GPU_constant(float *num)
1597 GPUNodeLink *link = GPU_node_link_create();
1598 link->link_type = GPU_NODE_LINK_CONSTANT;
1603 GPUNodeLink *GPU_uniform(float *num)
1605 GPUNodeLink *link = GPU_node_link_create();
1606 link->link_type = GPU_NODE_LINK_UNIFORM;
1611 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1613 GPUNodeLink *link = GPU_node_link_create();
1614 link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
1616 link->iuser = iuser;
1617 link->image_isdata = is_data;
1621 GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row)
1623 GPUNodeLink *link = GPU_node_link_create();
1624 link->link_type = GPU_NODE_LINK_COLORBAND;
1625 link->coba = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
1630 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1632 GPUNodeLink *link = GPU_node_link_create();
1633 link->link_type = GPU_NODE_LINK_BUILTIN;
1634 link->builtin = builtin;
1638 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1641 GPUFunction *function;
1642 GPUNodeLink *link, **linkptr;
1646 function = gpu_lookup_function(name);
1648 fprintf(stderr, "GPU failed to find function %s\n", name);
1652 node = GPU_node_begin(name);
1654 va_start(params, name);
1655 for (i = 0; i < function->totparam; i++) {
1656 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1657 linkptr = va_arg(params, GPUNodeLink **);
1658 gpu_node_output(node, function->paramtype[i], linkptr);
1661 link = va_arg(params, GPUNodeLink *);
1662 gpu_node_input_link(node, link, function->paramtype[i]);
1667 gpu_material_add_node(mat, node);
1672 bool GPU_stack_link(GPUMaterial *material, bNode *bnode, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1675 GPUFunction *function;
1676 GPUNodeLink *link, **linkptr;
1678 int i, totin, totout;
1680 function = gpu_lookup_function(name);
1682 fprintf(stderr, "GPU failed to find function %s\n", name);
1686 node = GPU_node_begin(name);
1691 for (i = 0; !in[i].end; i++) {
1692 if (in[i].type != GPU_NONE) {
1693 gpu_node_input_socket(material, bnode, node, &in[i], i);
1700 for (i = 0; !out[i].end; i++) {
1701 if (out[i].type != GPU_NONE) {
1702 gpu_node_output(node, out[i].type, &out[i].link);
1708 va_start(params, out);
1709 for (i = 0; i < function->totparam; i++) {
1710 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1712 linkptr = va_arg(params, GPUNodeLink **);
1713 gpu_node_output(node, function->paramtype[i], linkptr);
1720 link = va_arg(params, GPUNodeLink *);
1722 gpu_node_input_socket(NULL, NULL, node, link->socket, -1);
1724 gpu_node_input_link(node, link, function->paramtype[i]);
1732 gpu_material_add_node(material, node);
1737 GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index)
1739 return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT);
1742 /* Pass create/free */
1744 static void gpu_nodes_tag(GPUNodeLink *link)
1752 node = link->output->node;
1757 for (input = node->inputs.first; input; input = input->next)
1759 gpu_nodes_tag(input->link);
1762 void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1764 GPUNode *node, *next;
1766 for (node = nodes->first; node; node = node->next)
1769 gpu_nodes_tag(outlink);
1771 for (node = nodes->first; node; node = next) {
1775 BLI_remlink(nodes, node);
1776 gpu_node_free(node);
1781 static bool gpu_pass_is_valid(GPUPass *pass)
1783 /* Shader is not null if compilation is successful. */
1784 return (pass->compiled == false || pass->shader != NULL);
1787 GPUPass *GPU_generate_pass(
1788 GPUMaterial *material,
1789 GPUNodeLink *frag_outlink,
1790 struct GPUVertexAttribs *attribs,
1793 const char *vert_code,
1794 const char *geom_code,
1795 const char *frag_lib,
1796 const char *defines)
1798 char *vertexcode, *geometrycode, *fragmentcode;
1799 GPUPass *pass = NULL, *pass_hash = NULL;
1801 /* prune unused nodes */
1802 GPU_nodes_prune(nodes, frag_outlink);
1804 GPU_nodes_get_vertex_attributes(nodes, attribs);
1807 char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, builtins);
1809 /* Cache lookup: Reuse shaders already compiled */
1810 uint32_t hash = gpu_pass_hash(fragmentgen, defines, attribs);
1811 pass_hash = gpu_pass_cache_lookup(hash);
1813 if (pass_hash && (pass_hash->next == NULL || pass_hash->next->hash != hash)) {
1814 /* No collision, just return the pass. */
1815 MEM_freeN(fragmentgen);
1816 if (!gpu_pass_is_valid(pass_hash)) {
1817 /* Shader has already been created but failed to compile. */
1820 pass_hash->refcount += 1;
1824 /* Either the shader is not compiled or there is a hash collision...
1825 * continue generating the shader strings. */
1826 char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
1828 geometrycode = code_generate_geometry(nodes, geom_code);
1829 vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL));
1830 fragmentcode = BLI_strdupcat(tmp, fragmentgen);
1832 MEM_freeN(fragmentgen);
1836 /* Cache lookup: Reuse shaders already compiled */
1837 pass = gpu_pass_cache_resolve_collision(pass_hash, vertexcode, geometrycode, fragmentcode, defines, hash);
1841 /* Cache hit. Reuse the same GPUPass and GPUShader. */
1842 if (!gpu_pass_is_valid(pass)) {
1843 /* Shader has already been created but failed to compile. */
1847 MEM_SAFE_FREE(vertexcode);
1848 MEM_SAFE_FREE(fragmentcode);
1849 MEM_SAFE_FREE(geometrycode);
1851 pass->refcount += 1;
1854 /* We still create a pass even if shader compilation
1855 * fails to avoid trying to compile again and again. */
1856 pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1857 pass->shader = NULL;
1860 pass->vertexcode = vertexcode;
1861 pass->fragmentcode = fragmentcode;
1862 pass->geometrycode = geometrycode;
1863 pass->defines = (defines) ? BLI_strdup(defines) : NULL;
1864 pass->compiled = false;
1866 BLI_spin_lock(&pass_cache_spin);
1867 if (pass_hash != NULL) {
1868 /* Add after the first pass having the same hash. */
1869 pass->next = pass_hash->next;
1870 pass_hash->next = pass;
1873 /* No other pass have same hash, just prepend to the list. */
1874 BLI_LINKS_PREPEND(pass_cache, pass);
1876 BLI_spin_unlock(&pass_cache_spin);
1882 static int count_active_texture_sampler(GPUShader *shader, char *source)
1884 char *code = source;
1885 int samplers_id[64]; /* Remember this is per stage. */
1886 int sampler_len = 0;
1888 while ((code = strstr(code, "uniform "))) {
1889 /* Move past "uniform". */
1891 /* Skip following spaces. */
1892 while (*code == ' ') { code++; }
1893 /* Skip "i" from potential isamplers. */
1894 if (*code == 'i') { code++; }
1895 /* Skip following spaces. */
1896 if (gpu_str_prefix(code, "sampler")) {
1897 /* Move past "uniform". */
1899 /* Skip sampler type suffix. */
1900 while (*code != ' ' && *code != '\0') { code++; }
1901 /* Skip following spaces. */
1902 while (*code == ' ') { code++; }
1904 if (*code != '\0') {
1905 char sampler_name[64];
1906 code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name));
1907 int id = GPU_shader_get_uniform_ensure(shader, sampler_name);
1912 /* Catch duplicates. */
1913 bool is_duplicate = false;
1914 for (int i = 0; i < sampler_len; ++i) {
1915 if (samplers_id[i] == id) {
1916 is_duplicate = true;
1920 if (!is_duplicate) {
1921 samplers_id[sampler_len] = id;
1931 static bool gpu_pass_shader_validate(GPUPass *pass)
1933 if (pass->shader == NULL) {
1937 /* NOTE: The only drawback of this method is that it will count a sampler
1938 * used in the fragment shader and only declared (but not used) in the vertex
1939 * shader as used by both. But this corner case is not happening for now. */
1940 int vert_samplers_len = count_active_texture_sampler(pass->shader, pass->vertexcode);
1941 int frag_samplers_len = count_active_texture_sampler(pass->shader, pass->fragmentcode);
1943 int total_samplers_len = vert_samplers_len + frag_samplers_len;
1945 /* Validate against opengl limit. */
1946 if ((frag_samplers_len > GPU_max_textures_frag()) ||
1947 (frag_samplers_len > GPU_max_textures_vert()))
1952 if (pass->geometrycode) {
1953 int geom_samplers_len = count_active_texture_sampler(pass->shader, pass->geometrycode);
1954 total_samplers_len += geom_samplers_len;
1955 if (geom_samplers_len > GPU_max_textures_geom()) {
1960 return (total_samplers_len <= GPU_max_textures());
1963 void GPU_pass_compile(GPUPass *pass, const char *shname)
1965 if (!pass->compiled) {
1966 pass->shader = GPU_shader_create(
1974 /* NOTE: Some drivers / gpu allows more active samplers than the opengl limit.
1975 * We need to make sure to count active samplers to avoid undefined behavior. */
1976 if (!gpu_pass_shader_validate(pass)) {
1977 if (pass->shader != NULL) {
1978 fprintf(stderr, "GPUShader: error: too many samplers in shader.\n");
1979 GPU_shader_free(pass->shader);
1981 pass->shader = NULL;
1983 pass->compiled = true;
1987 void GPU_pass_release(GPUPass *pass)
1989 BLI_assert(pass->refcount > 0);
1993 static void gpu_pass_free(GPUPass *pass)
1995 BLI_assert(pass->refcount == 0);
1997 GPU_shader_free(pass->shader);
1999 MEM_SAFE_FREE(pass->fragmentcode);
2000 MEM_SAFE_FREE(pass->geometrycode);
2001 MEM_SAFE_FREE(pass->vertexcode);
2002 MEM_SAFE_FREE(pass->defines);
2006 void GPU_pass_free_nodes(ListBase *nodes)
2008 gpu_nodes_free(nodes);
2011 void GPU_pass_cache_garbage_collect(void)
2013 static int lasttime = 0;
2014 const int shadercollectrate = 60; /* hardcoded for now. */
2015 int ctime = (int)PIL_check_seconds_timer();
2017 if (ctime < shadercollectrate + lasttime)
2022 BLI_spin_lock(&pass_cache_spin);
2023 GPUPass *next, **prev_pass = &pass_cache;
2024 for (GPUPass *pass = pass_cache; pass; pass = next) {
2026 if (pass->refcount == 0) {
2027 /* Remove from list */
2029 gpu_pass_free(pass);
2032 prev_pass = &pass->next;
2035 BLI_spin_unlock(&pass_cache_spin);
2038 void GPU_pass_cache_init(void)
2040 BLI_spin_init(&pass_cache_spin);
2043 void GPU_pass_cache_free(void)
2045 BLI_spin_lock(&pass_cache_spin);
2046 while (pass_cache) {
2047 GPUPass *next = pass_cache->next;
2048 gpu_pass_free(pass_cache);
2051 BLI_spin_unlock(&pass_cache_spin);
2053 BLI_spin_end(&pass_cache_spin);