4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2005 Blender Foundation.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): Brecht Van Lommel.
30 * ***** END GPL LICENSE BLOCK *****
35 #include "MEM_guardedalloc.h"
37 #include "DNA_customdata_types.h"
38 #include "DNA_image_types.h"
39 #include "DNA_listBase.h"
40 #include "DNA_material_types.h"
42 #include "BLI_dynstr.h"
43 #include "BLI_blenlib.h"
44 #include "BLI_ghash.h"
47 #include "BKE_global.h"
48 #include "BKE_utildefines.h"
50 #include "GPU_material.h"
51 #include "GPU_extensions.h"
53 #include "BLO_sys_types.h" // for intptr_t support
55 #include "gpu_codegen.h"
62 #define vsnprintf _vsnprintf
65 #define snprintf _snprintf
69 extern char datatoc_gpu_shader_material_glsl[];
70 extern char datatoc_gpu_shader_vertex_glsl[];
72 /* structs and defines */
74 typedef enum GPUDataSource {
75 GPU_SOURCE_VEC_UNIFORM,
82 static char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
83 0, 0, 0, 0, "mat3", 0, 0, 0, 0, 0, 0, "mat4"};
86 struct GPUNode *next, *prev;
113 GPUTexture *dynamictex;
117 struct GPUOutput *output;
120 typedef struct GPUOutput {
121 struct GPUOutput *next, *prev;
124 int type; /* data type = length of vector/matrix */
125 GPUNodeLink *link; /* output link */
126 int id; /* unique id as created by code generator */
129 typedef struct GPUInput {
130 struct GPUInput *next, *prev;
134 int type; /* datatype */
135 int source; /* data source */
137 int id; /* unique id as created by code generator */
138 int texid; /* number for multitexture */
139 int attribid; /* id for vertex attributes */
140 int bindtex; /* input is responsible for binding the texture? */
141 int definetex; /* input is responsible for defining the pixel? */
142 int textarget; /* GL_TEXTURE_* */
143 int textype; /* datatype */
145 struct Image *ima; /* image */
146 struct ImageUser *iuser;/* image user */
147 float *dynamicvec; /* vector data in case it is dynamic */
148 GPUTexture *tex; /* input texture, only set at runtime */
149 int shaderloc; /* id from opengl */
150 char shadername[32]; /* name in shader */
152 float vec[16]; /* vector data */
154 int dynamictex; /* dynamic? */
155 int attribtype; /* attribute type */
156 char attribname[32]; /* attribute name */
157 int attribfirst; /* this is the first one that is bound */
158 GPUBuiltin builtin; /* builtin uniform */
162 struct GPUPass *next, *prev;
165 struct GPUOutput *output;
166 struct GPUShader *shader;
169 /* Strings utility */
171 static void BLI_dynstr_printf(DynStr *dynstr, const char *format, ...)
177 va_start(args, format);
178 retval = vsnprintf(str, sizeof(str), format, args);
181 if (retval >= sizeof(str))
182 fprintf(stderr, "BLI_dynstr_printf: limit exceeded\n");
184 BLI_dynstr_append(dynstr, str);
187 /* GLSL code parsing for finding function definitions.
188 * These are stored in a hash for lookup when creating a material. */
190 static GHash *FUNCTION_HASH= NULL;
191 /*static char *FUNCTION_PROTOTYPES= NULL;
192 static GPUShader *FUNCTION_LIB= NULL;*/
194 static int gpu_str_prefix(char *str, char *prefix)
196 while(*str && *prefix) {
204 return (*prefix == '\0');
207 static char *gpu_str_skip_token(char *str, char *token, int max)
211 /* skip a variable/function name */
213 if(ELEM6(*str, ' ', '(', ')', ',', '\t', '\n'))
216 if(token && len < max-1) {
228 /* skip the next special characters:
229 * note the missing ')' */
231 if(ELEM5(*str, ' ', '(', ',', '\t', '\n'))
240 static void gpu_parse_functions_string(GHash *hash, char *code)
242 GPUFunction *function;
245 while((code = strstr(code, "void "))) {
246 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
248 code = gpu_str_skip_token(code, NULL, 0);
249 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
252 while(*code && *code != ')') {
253 /* test if it's an input or output */
254 qual = FUNCTION_QUAL_IN;
255 if(gpu_str_prefix(code, "out "))
256 qual = FUNCTION_QUAL_OUT;
257 if(gpu_str_prefix(code, "inout "))
258 qual = FUNCTION_QUAL_INOUT;
259 if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
260 code = gpu_str_skip_token(code, NULL, 0);
264 for(i=1; i<=16; i++) {
265 if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
271 if(!type && gpu_str_prefix(code, "sampler2DShadow"))
273 if(!type && gpu_str_prefix(code, "sampler1D"))
275 if(!type && gpu_str_prefix(code, "sampler2D"))
280 code = gpu_str_skip_token(code, NULL, 0);
281 code = gpu_str_skip_token(code, NULL, 0);
282 function->paramqual[function->totparam]= qual;
283 function->paramtype[function->totparam]= type;
284 function->totparam++;
287 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
292 if(strlen(function->name) == 0 || function->totparam == 0) {
293 fprintf(stderr, "GPU functions parse error.\n");
298 BLI_ghash_insert(hash, function->name, function);
303 static char *gpu_generate_function_prototyps(GHash *hash)
305 DynStr *ds = BLI_dynstr_new();
307 GPUFunction *function;
308 char *name, *prototypes;
311 /* automatically generate function prototypes to add to the top of the
312 * generated code, to avoid have to add the actual code & recompile all */
313 ghi = BLI_ghashIterator_new(hash);
315 for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
316 name = BLI_ghashIterator_getValue(ghi);
317 function = BLI_ghashIterator_getValue(ghi);
319 BLI_dynstr_printf(ds, "void %s(", name);
320 for(a=0; a<function->totparam; a++) {
321 if(function->paramqual[a] == FUNCTION_QUAL_OUT)
322 BLI_dynstr_append(ds, "out ");
323 else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
324 BLI_dynstr_append(ds, "inout ");
326 if(function->paramtype[a] == GPU_TEX1D)
327 BLI_dynstr_append(ds, "sampler1D");
328 else if(function->paramtype[a] == GPU_TEX2D)
329 BLI_dynstr_append(ds, "sampler2D");
330 else if(function->paramtype[a] == GPU_SHADOW2D)
331 BLI_dynstr_append(ds, "sampler2DShadow");
333 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
335 //BLI_dynstr_printf(ds, " param%d", a);
337 if(a != function->totparam-1)
338 BLI_dynstr_append(ds, ", ");
340 BLI_dynstr_append(ds, ");\n");
343 BLI_dynstr_append(ds, "\n");
345 prototypes = BLI_dynstr_get_cstring(ds);
352 GPUFunction *GPU_lookup_function(char *name)
355 FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
356 gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl);
357 /*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
358 FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/
361 return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, name);
364 void GPU_extensions_exit(void)
366 extern Material defmaterial; // render module abuse...
368 if(defmaterial.gpumaterial.first)
369 GPU_material_free(&defmaterial);
372 BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
373 FUNCTION_HASH = NULL;
375 /*if(FUNCTION_PROTOTYPES) {
376 MEM_freeN(FUNCTION_PROTOTYPES);
377 FUNCTION_PROTOTYPES = NULL;
380 GPU_shader_free(FUNCTION_LIB);
385 /* GLSL code generation */
387 static void codegen_convert_datatype(DynStr *ds, int from, int to, char *tmp, int id)
391 snprintf(name, sizeof(name), "%s%d", tmp, id);
394 BLI_dynstr_append(ds, name);
396 else if (to == GPU_FLOAT) {
397 if (from == GPU_VEC4)
398 BLI_dynstr_printf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
399 else if (from == GPU_VEC3)
400 BLI_dynstr_printf(ds, "dot(%s, vec3(0.33))", name);
401 else if (from == GPU_VEC2)
402 BLI_dynstr_printf(ds, "%s.r", name);
404 else if (to == GPU_VEC2) {
405 if (from == GPU_VEC4)
406 BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
407 else if (from == GPU_VEC3)
408 BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
409 else if (from == GPU_FLOAT)
410 BLI_dynstr_printf(ds, "vec2(%s, 1.0)", name);
412 else if (to == GPU_VEC3) {
413 if (from == GPU_VEC4)
414 BLI_dynstr_printf(ds, "%s.rgb", name);
415 else if (from == GPU_VEC2)
416 BLI_dynstr_printf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
417 else if (from == GPU_FLOAT)
418 BLI_dynstr_printf(ds, "vec3(%s, %s, %s)", name, name, name);
421 if (from == GPU_VEC3)
422 BLI_dynstr_printf(ds, "vec4(%s, 1.0)", name);
423 else if (from == GPU_VEC2)
424 BLI_dynstr_printf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
425 else if (from == GPU_FLOAT)
426 BLI_dynstr_printf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
430 static void codegen_print_datatype(DynStr *ds, int type, float *data)
434 BLI_dynstr_printf(ds, "%s(", GPU_DATATYPE_STR[type]);
436 for(i=0; i<type; i++) {
437 BLI_dynstr_printf(ds, "%f", data[i]);
439 BLI_dynstr_append(ds, ")");
441 BLI_dynstr_append(ds, ", ");
445 static int codegen_input_has_texture(GPUInput *input)
452 return input->tex != 0;
455 char *GPU_builtin_name(GPUBuiltin builtin)
457 if(builtin == GPU_VIEW_MATRIX)
459 else if(builtin == GPU_OBJECT_MATRIX)
461 else if(builtin == GPU_INVERSE_VIEW_MATRIX)
462 return "unfinvviewmat";
463 else if(builtin == GPU_INVERSE_OBJECT_MATRIX)
464 return "unfinvobmat";
465 else if(builtin == GPU_VIEW_POSITION)
466 return "varposition";
467 else if(builtin == GPU_VIEW_NORMAL)
469 else if(builtin == GPU_OBCOLOR)
475 static void codegen_set_unique_ids(ListBase *nodes)
477 GHash *bindhash, *definehash;
481 int id = 1, texid = 0;
483 bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
484 definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
486 for (node=nodes->first; node; node=node->next) {
487 for (input=node->inputs.first; input; input=input->next) {
488 /* set id for unique names of uniform variables */
491 input->definetex = 0;
493 /* set texid used for settings texture slot with multitexture */
494 if (codegen_input_has_texture(input) &&
495 ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) {
497 /* input is texture from buffer, assign only one texid per
498 buffer to avoid sampling the same texture twice */
499 if (!BLI_ghash_haskey(bindhash, input->link)) {
500 input->texid = texid++;
502 BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
505 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
507 else if(input->ima) {
508 /* input is texture from image, assign only one texid per
509 buffer to avoid sampling the same texture twice */
510 if (!BLI_ghash_haskey(bindhash, input->ima)) {
511 input->texid = texid++;
513 BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
516 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
519 /* input is user created texture, we know there there is
520 only one, so assign new texid */
522 input->texid = texid++;
525 /* make sure this pixel is defined exactly once */
526 if (input->source == GPU_SOURCE_TEX_PIXEL) {
528 if (!BLI_ghash_haskey(definehash, input->ima)) {
529 input->definetex = 1;
530 BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
534 if (!BLI_ghash_haskey(definehash, input->link)) {
535 input->definetex = 1;
536 BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
543 for (output=node->outputs.first; output; output=output->next)
544 /* set id for unique names of tmp variables storing output */
548 BLI_ghash_free(bindhash, NULL, NULL);
549 BLI_ghash_free(definehash, NULL, NULL);
552 static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
560 for (node=nodes->first; node; node=node->next) {
561 for (input=node->inputs.first; input; input=input->next) {
562 if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
563 /* create exactly one sampler for each texture */
564 if (codegen_input_has_texture(input) && input->bindtex)
565 BLI_dynstr_printf(ds, "uniform %s samp%d;\n",
566 (input->textype == GPU_TEX1D)? "sampler1D":
567 (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
570 else if(input->source == GPU_SOURCE_BUILTIN) {
571 /* only define each builting uniform/varying once */
572 if(!(builtins & input->builtin)) {
573 builtins |= input->builtin;
574 name = GPU_builtin_name(input->builtin);
576 if(gpu_str_prefix(name, "unf")) {
577 BLI_dynstr_printf(ds, "uniform %s %s;\n",
578 GPU_DATATYPE_STR[input->type], name);
581 BLI_dynstr_printf(ds, "varying %s %s;\n",
582 GPU_DATATYPE_STR[input->type], name);
586 else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
587 if(input->dynamicvec) {
588 /* only create uniforms for dynamic vectors */
589 BLI_dynstr_printf(ds, "uniform %s unf%d;\n",
590 GPU_DATATYPE_STR[input->type], input->id);
593 /* for others use const so the compiler can do folding */
594 BLI_dynstr_printf(ds, "const %s cons%d = ",
595 GPU_DATATYPE_STR[input->type], input->id);
596 codegen_print_datatype(ds, input->type, input->vec);
597 BLI_dynstr_append(ds, ";\n");
600 else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
601 BLI_dynstr_printf(ds, "varying %s var%d;\n",
602 GPU_DATATYPE_STR[input->type], input->attribid);
607 BLI_dynstr_append(ds, "\n");
610 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
616 for (node=nodes->first; node; node=node->next) {
617 /* load pixels from textures */
618 for (input=node->inputs.first; input; input=input->next) {
619 if (input->source == GPU_SOURCE_TEX_PIXEL) {
620 if (codegen_input_has_texture(input) && input->definetex) {
621 BLI_dynstr_printf(ds, "\tvec4 tex%d = texture2D(", input->texid);
622 BLI_dynstr_printf(ds, "samp%d, gl_TexCoord[%d].st);\n",
623 input->texid, input->texid);
628 /* declare temporary variables for node output storage */
629 for (output=node->outputs.first; output; output=output->next)
630 BLI_dynstr_printf(ds, "\t%s tmp%d;\n",
631 GPU_DATATYPE_STR[output->type], output->id);
634 BLI_dynstr_append(ds, "\n");
637 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
643 for (node=nodes->first; node; node=node->next) {
644 BLI_dynstr_printf(ds, "\t%s(", node->name);
646 for (input=node->inputs.first; input; input=input->next) {
647 if (input->source == GPU_SOURCE_TEX) {
648 BLI_dynstr_printf(ds, "samp%d", input->texid);
650 BLI_dynstr_printf(ds, ", gl_TexCoord[%d].st", input->texid);
652 else if (input->source == GPU_SOURCE_TEX_PIXEL) {
653 if (input->link && input->link->output)
654 codegen_convert_datatype(ds, input->link->output->type, input->type,
655 "tmp", input->link->output->id);
657 codegen_convert_datatype(ds, input->link->output->type, input->type,
658 "tex", input->texid);
660 else if(input->source == GPU_SOURCE_BUILTIN)
661 BLI_dynstr_printf(ds, "%s", GPU_builtin_name(input->builtin));
662 else if(input->source == GPU_SOURCE_VEC_UNIFORM) {
663 if(input->dynamicvec)
664 BLI_dynstr_printf(ds, "unf%d", input->id);
666 BLI_dynstr_printf(ds, "cons%d", input->id);
668 else if (input->source == GPU_SOURCE_ATTRIB)
669 BLI_dynstr_printf(ds, "var%d", input->attribid);
671 BLI_dynstr_append(ds, ", ");
674 for (output=node->outputs.first; output; output=output->next) {
675 BLI_dynstr_printf(ds, "tmp%d", output->id);
677 BLI_dynstr_append(ds, ", ");
680 BLI_dynstr_append(ds, ");\n");
683 BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
684 codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
685 BLI_dynstr_append(ds, ";\n");
688 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *name)
690 DynStr *ds = BLI_dynstr_new();
693 /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
695 codegen_set_unique_ids(nodes);
696 codegen_print_uniforms_functions(ds, nodes);
699 // BLI_dynstr_printf(ds, "/* %s */\n", name);
701 BLI_dynstr_append(ds, "void main(void)\n");
702 BLI_dynstr_append(ds, "{\n");
704 codegen_declare_tmps(ds, nodes);
705 codegen_call_functions(ds, nodes, output);
707 BLI_dynstr_append(ds, "}\n");
710 code = BLI_dynstr_get_cstring(ds);
713 //if(G.f & G_DEBUG) printf("%s\n", code);
718 static char *code_generate_vertex(ListBase *nodes)
720 DynStr *ds = BLI_dynstr_new();
725 for (node=nodes->first; node; node=node->next) {
726 for (input=node->inputs.first; input; input=input->next) {
727 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
728 BLI_dynstr_printf(ds, "attribute %s att%d;\n",
729 GPU_DATATYPE_STR[input->type], input->attribid);
730 BLI_dynstr_printf(ds, "varying %s var%d;\n",
731 GPU_DATATYPE_STR[input->type], input->attribid);
736 BLI_dynstr_append(ds, "\n");
737 BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
739 for (node=nodes->first; node; node=node->next)
740 for (input=node->inputs.first; input; input=input->next)
741 if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
742 if(input->attribtype == CD_TANGENT) /* silly exception */
743 BLI_dynstr_printf(ds, "\tvar%d = gl_NormalMatrix * ", input->attribid);
745 BLI_dynstr_printf(ds, "\tvar%d = ", input->attribid);
747 BLI_dynstr_printf(ds, "att%d;\n", input->attribid);
750 BLI_dynstr_append(ds, "}\n\n");
752 code = BLI_dynstr_get_cstring(ds);
756 //if(G.f & G_DEBUG) printf("%s\n", code);
761 /* GPU pass binding/unbinding */
763 GPUShader *GPU_pass_shader(GPUPass *pass)
768 void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
770 GPUShader *shader = pass->shader;
772 GPUInput *next, *input;
773 ListBase *inputs = &pass->inputs;
776 memset(inputs, 0, sizeof(*inputs));
781 GPU_shader_bind(shader);
783 for (node=nodes->first; node; node=node->next) {
785 for (input=node->inputs.first; input; input=next, z++) {
788 /* attributes don't need to be bound, they already have
789 * an id that the drawing functions will use */
790 if(input->source == GPU_SOURCE_ATTRIB ||
791 input->source == GPU_SOURCE_BUILTIN)
794 if (input->ima || input->tex)
795 snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
797 snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
799 /* pass non-dynamic uniforms to opengl */
802 if(input->ima || input->tex) {
806 else if(input->dynamicvec)
810 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
814 BLI_remlink(&node->inputs, input);
815 BLI_addtail(inputs, input);
820 GPU_shader_unbind(shader);
823 void GPU_pass_bind(GPUPass *pass, double time)
826 GPUShader *shader = pass->shader;
827 ListBase *inputs = &pass->inputs;
832 GPU_shader_bind(shader);
834 /* now bind the textures */
835 for (input=inputs->first; input; input=input->next) {
837 input->tex = GPU_texture_from_blender(input->ima, input->iuser, time);
839 if(input->ima || input->tex) {
841 GPU_texture_bind(input->tex, input->texid);
842 GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
848 void GPU_pass_update_uniforms(GPUPass *pass)
851 GPUShader *shader = pass->shader;
852 ListBase *inputs = &pass->inputs;
857 /* pass dynamic inputs to opengl, others were removed */
858 for (input=inputs->first; input; input=input->next)
859 if(!(input->ima || input->tex))
860 GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
864 void GPU_pass_unbind(GPUPass *pass)
867 GPUShader *shader = pass->shader;
868 ListBase *inputs = &pass->inputs;
873 for (input=inputs->first; input; input=input->next) {
876 GPU_texture_unbind(input->tex);
881 GPU_shader_unbind(shader);
884 /* Node Link Functions */
886 GPUNodeLink *GPU_node_link_create(int type)
888 GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
895 void GPU_node_link_free(GPUNodeLink *link)
900 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
902 if (link->users == 0) {
904 link->output->link = NULL;
911 GPUNode *GPU_node_begin(char *name)
913 GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
920 void GPU_node_end(GPUNode *node)
925 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
932 outnode = link->output->node;
933 name = outnode->name;
935 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
936 input = MEM_dupallocN(outnode->inputs.first);
939 input->link->users++;
940 BLI_addtail(&node->inputs, input);
945 input = MEM_callocN(sizeof(GPUInput), "GPUInput");
949 /* builtin uniform */
951 input->source = GPU_SOURCE_BUILTIN;
952 input->builtin = link->builtin;
956 else if(link->output) {
957 /* link to a node output */
959 input->source = GPU_SOURCE_TEX_PIXEL;
963 else if(link->dynamictex) {
964 /* dynamic texture, GPUTexture is updated/deleted externally */
966 input->source = GPU_SOURCE_TEX;
968 input->tex = link->dynamictex;
969 input->textarget = GL_TEXTURE_2D;
970 input->textype = type;
971 input->dynamictex = 1;
974 else if(link->texture) {
975 /* small texture created on the fly, like for colorbands */
976 input->type = GPU_VEC4;
977 input->source = GPU_SOURCE_TEX;
978 input->textype = type;
980 if (type == GPU_TEX1D) {
981 input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1);
982 input->textarget = GL_TEXTURE_1D;
985 input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2);
986 input->textarget = GL_TEXTURE_2D;
989 MEM_freeN(link->ptr1);
992 else if(link->image) {
994 input->type = GPU_VEC4;
995 input->source = GPU_SOURCE_TEX;
997 input->ima = link->ptr1;
998 input->textarget = GL_TEXTURE_2D;
999 input->textype = GPU_TEX2D;
1002 else if(link->attribtype) {
1003 /* vertex attribute */
1005 input->source = GPU_SOURCE_ATTRIB;
1007 input->attribtype = link->attribtype;
1008 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
1012 /* uniform vector */
1014 input->source = GPU_SOURCE_VEC_UNIFORM;
1016 memcpy(input->vec, link->ptr1, type*sizeof(float));
1018 input->dynamicvec= link->ptr1;
1022 BLI_addtail(&node->inputs, input);
1025 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1030 gpu_node_input_link(node, sock->link, sock->type);
1033 link = GPU_node_link_create(0);
1034 link->ptr1 = sock->vec;
1035 gpu_node_input_link(node, link, sock->type);
1039 void GPU_node_output(GPUNode *node, int type, char *name, GPUNodeLink **link)
1041 GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1043 output->type = type;
1044 output->node = node;
1047 *link = output->link = GPU_node_link_create(type);
1048 output->link->output = output;
1050 /* note: the caller owns the reference to the linkfer, GPUOutput
1051 merely points to it, and if the node is destroyed it will
1052 set that pointer to NULL */
1055 BLI_addtail(&node->outputs, output);
1058 void GPU_inputs_free(ListBase *inputs)
1062 for(input=inputs->first; input; input=input->next) {
1064 GPU_node_link_free(input->link);
1065 else if(input->tex && !input->dynamictex)
1066 GPU_texture_free(input->tex);
1069 BLI_freelistN(inputs);
1072 void GPU_node_free(GPUNode *node)
1076 GPU_inputs_free(&node->inputs);
1078 for (output=node->outputs.first; output; output=output->next)
1080 output->link->output = NULL;
1081 GPU_node_link_free(output->link);
1084 BLI_freelistN(&node->outputs);
1088 void GPU_nodes_free(ListBase *nodes)
1092 while (nodes->first) {
1093 node = nodes->first;
1094 BLI_remlink(nodes, node);
1095 GPU_node_free(node);
1099 /* vertex attributes */
1101 void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1107 /* convert attributes requested by node inputs to an array of layers,
1108 * checking for duplicates and assigning id's starting from zero. */
1110 memset(attribs, 0, sizeof(*attribs));
1112 for(node=nodes->first; node; node=node->next) {
1113 for(input=node->inputs.first; input; input=input->next) {
1114 if(input->source == GPU_SOURCE_ATTRIB) {
1115 for(a=0; a<attribs->totlayer; a++) {
1116 if(attribs->layer[a].type == input->attribtype &&
1117 strcmp(attribs->layer[a].name, input->attribname) == 0)
1121 if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) {
1122 input->attribid = attribs->totlayer++;
1123 input->attribfirst = 1;
1125 attribs->layer[a].type = input->attribtype;
1126 attribs->layer[a].glindex = input->attribid;
1127 BLI_strncpy(attribs->layer[a].name, input->attribname,
1128 sizeof(attribs->layer[a].name));
1131 input->attribid = attribs->layer[a].glindex;
1137 void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1144 for(node=nodes->first; node; node=node->next)
1145 for(input=node->inputs.first; input; input=input->next)
1146 if(input->source == GPU_SOURCE_BUILTIN)
1147 *builtin |= input->builtin;
1150 /* varargs linking */
1152 GPUNodeLink *GPU_attribute(int type, char *name)
1154 GPUNodeLink *link = GPU_node_link_create(0);
1156 link->attribtype= type;
1157 link->attribname= name;
1162 GPUNodeLink *GPU_uniform(float *num)
1164 GPUNodeLink *link = GPU_node_link_create(0);
1172 GPUNodeLink *GPU_dynamic_uniform(float *num)
1174 GPUNodeLink *link = GPU_node_link_create(0);
1183 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
1185 GPUNodeLink *link = GPU_node_link_create(0);
1194 GPUNodeLink *GPU_texture(int size, float *pixels)
1196 GPUNodeLink *link = GPU_node_link_create(0);
1199 link->texturesize = size;
1205 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex)
1207 GPUNodeLink *link = GPU_node_link_create(0);
1210 link->dynamictex = tex;
1215 GPUNodeLink *GPU_socket(GPUNodeStack *sock)
1217 GPUNodeLink *link = GPU_node_link_create(0);
1224 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1226 GPUNodeLink *link = GPU_node_link_create(0);
1228 link->builtin= builtin;
1233 int GPU_link(GPUMaterial *mat, char *name, ...)
1236 GPUFunction *function;
1237 GPUNodeLink *link, **linkptr;
1241 function = GPU_lookup_function(name);
1243 fprintf(stderr, "GPU failed to find function %s\n", name);
1247 node = GPU_node_begin(name);
1249 va_start(params, name);
1250 for(i=0; i<function->totparam; i++) {
1251 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
1252 linkptr= va_arg(params, GPUNodeLink**);
1253 GPU_node_output(node, function->paramtype[i], "", linkptr);
1256 link= va_arg(params, GPUNodeLink*);
1257 gpu_node_input_link(node, link, function->paramtype[i]);
1264 gpu_material_add_node(mat, node);
1269 int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1272 GPUFunction *function;
1273 GPUNodeLink *link, **linkptr;
1275 int i, totin, totout;
1277 function = GPU_lookup_function(name);
1279 fprintf(stderr, "GPU failed to find function %s\n", name);
1283 node = GPU_node_begin(name);
1288 for(i = 0; in[i].type != GPU_NONE; i++) {
1289 gpu_node_input_socket(node, &in[i]);
1295 for(i = 0; out[i].type != GPU_NONE; i++) {
1296 GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
1301 va_start(params, out);
1302 for(i=0; i<function->totparam; i++) {
1303 if(function->paramqual[i] != FUNCTION_QUAL_IN) {
1305 linkptr= va_arg(params, GPUNodeLink**);
1306 GPU_node_output(node, function->paramtype[i], "", linkptr);
1313 link= va_arg(params, GPUNodeLink*);
1315 gpu_node_input_socket(node, link->socket);
1317 gpu_node_input_link(node, link, function->paramtype[i]);
1327 gpu_material_add_node(mat, node);
1332 int GPU_link_changed(GPUNodeLink *link)
1339 node = link->output->node;
1342 if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
1343 input = node->inputs.first;
1344 return (input->link != NULL);
1353 /* Pass create/free */
1355 void gpu_nodes_tag(GPUNodeLink *link)
1363 node = link->output->node;
1368 for(input=node->inputs.first; input; input=input->next)
1370 gpu_nodes_tag(input->link);
1373 void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1375 GPUNode *node, *next;
1377 for(node=nodes->first; node; node=node->next)
1380 gpu_nodes_tag(outlink);
1382 for(node=nodes->first; node; node=next) {
1386 BLI_remlink(nodes, node);
1387 GPU_node_free(node);
1392 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
1396 char *vertexcode, *fragmentcode;
1398 /*if(!FUNCTION_LIB) {
1399 GPU_nodes_free(nodes);
1403 /* prune unused nodes */
1404 gpu_nodes_prune(nodes, outlink);
1406 gpu_nodes_get_vertex_attributes(nodes, attribs);
1407 gpu_nodes_get_builtin_flag(nodes, builtins);
1409 /* generate code and compile with opengl */
1410 fragmentcode = code_generate_fragment(nodes, outlink->output, name);
1411 vertexcode = code_generate_vertex(nodes);
1412 shader = GPU_shader_create(vertexcode, fragmentcode, datatoc_gpu_shader_material_glsl); /*FUNCTION_LIB);*/
1413 MEM_freeN(fragmentcode);
1414 MEM_freeN(vertexcode);
1418 memset(attribs, 0, sizeof(*attribs));
1419 memset(builtins, 0, sizeof(*builtins));
1420 GPU_nodes_free(nodes);
1425 pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1427 pass->output = outlink->output;
1428 pass->shader = shader;
1430 /* extract dynamic inputs and throw away nodes */
1431 GPU_nodes_extract_dynamic_inputs(pass, nodes);
1432 GPU_nodes_free(nodes);
1437 void GPU_pass_free(GPUPass *pass)
1439 GPU_shader_free(pass->shader);
1440 GPU_inputs_free(&pass->inputs);