Code cleanup: de-duplicate codegen texid assignment
[blender.git] / source / blender / gpu / intern / gpu_codegen.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_codegen.c
29  *  \ingroup gpu
30  *
31  * Convert material node-trees to GLSL.
32  */
33
34 #include "GPU_glew.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_customdata_types.h"
39 #include "DNA_image_types.h"
40 #include "DNA_material_types.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_utildefines.h"
44 #include "BLI_dynstr.h"
45 #include "BLI_ghash.h"
46
47 #include "GPU_material.h"
48 #include "GPU_extensions.h"
49
50 #include "BLI_sys_types.h" // for intptr_t support
51
52 #include "gpu_codegen.h"
53
54 #include <string.h>
55 #include <stdarg.h>
56
57 extern char datatoc_gpu_shader_material_glsl[];
58 extern char datatoc_gpu_shader_vertex_glsl[];
59 extern char datatoc_gpu_shader_vertex_world_glsl[];
60
61
62 static char *glsl_material_library = NULL;
63
64
65 /* type definitions and constants */
66
67 enum {
68         MAX_FUNCTION_NAME = 64
69 };
70 enum {
71         MAX_PARAMETER = 32
72 };
73
74 typedef enum {
75         FUNCTION_QUAL_IN,
76         FUNCTION_QUAL_OUT,
77         FUNCTION_QUAL_INOUT
78 } GPUFunctionQual;
79
80 typedef struct GPUFunction {
81         char name[MAX_FUNCTION_NAME];
82         GPUType paramtype[MAX_PARAMETER];
83         GPUFunctionQual paramqual[MAX_PARAMETER];
84         int totparam;
85 } GPUFunction;
86
87 /* Indices match the GPUType enum */
88 static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
89         NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
90
91 /* GLSL code parsing for finding function definitions.
92  * These are stored in a hash for lookup when creating a material. */
93
94 static GHash *FUNCTION_HASH= NULL;
95 /* static char *FUNCTION_PROTOTYPES= NULL;
96  * static GPUShader *FUNCTION_LIB= NULL;*/
97
98 static int gpu_str_prefix(const char *str, const char *prefix)
99 {
100         while (*str && *prefix) {
101                 if (*str != *prefix)
102                         return 0;
103
104                 str++;
105                 prefix++;
106         }
107         
108         return (*prefix == '\0');
109 }
110
111 static char *gpu_str_skip_token(char *str, char *token, int max)
112 {
113         int len = 0;
114
115         /* skip a variable/function name */
116         while (*str) {
117                 if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
118                         break;
119                 else {
120                         if (token && len < max-1) {
121                                 *token= *str;
122                                 token++;
123                                 len++;
124                         }
125                         str++;
126                 }
127         }
128
129         if (token)
130                 *token= '\0';
131
132         /* skip the next special characters:
133          * note the missing ')' */
134         while (*str) {
135                 if (ELEM(*str, ' ', '(', ',', '\t', '\n', '\r'))
136                         str++;
137                 else
138                         break;
139         }
140
141         return str;
142 }
143
144 static void gpu_parse_functions_string(GHash *hash, char *code)
145 {
146         GPUFunction *function;
147         GPUType type;
148         GPUFunctionQual qual;
149         int i;
150
151         while ((code = strstr(code, "void "))) {
152                 function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
153
154                 code = gpu_str_skip_token(code, NULL, 0);
155                 code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
156
157                 /* get parameters */
158                 while (*code && *code != ')') {
159                         /* test if it's an input or output */
160                         qual = FUNCTION_QUAL_IN;
161                         if (gpu_str_prefix(code, "out "))
162                                 qual = FUNCTION_QUAL_OUT;
163                         if (gpu_str_prefix(code, "inout "))
164                                 qual = FUNCTION_QUAL_INOUT;
165                         if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
166                                 code = gpu_str_skip_token(code, NULL, 0);
167
168                         /* test for type */
169                         type= GPU_NONE;
170                         for (i=1; i<=16; i++) {
171                                 if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
172                                         type= i;
173                                         break;
174                                 }
175                         }
176
177                         if (!type && gpu_str_prefix(code, "sampler2DShadow"))
178                                 type= GPU_SHADOW2D;
179                         if (!type && gpu_str_prefix(code, "sampler2D"))
180                                 type= GPU_TEX2D;
181
182                         if (type) {
183                                 /* add parameter */
184                                 code = gpu_str_skip_token(code, NULL, 0);
185                                 code = gpu_str_skip_token(code, NULL, 0);
186                                 function->paramqual[function->totparam]= qual;
187                                 function->paramtype[function->totparam]= type;
188                                 function->totparam++;
189                         }
190                         else {
191                                 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
192                                 break;
193                         }
194                 }
195
196                 if (function->name[0] == '\0' || function->totparam == 0) {
197                         fprintf(stderr, "GPU functions parse error.\n");
198                         MEM_freeN(function);
199                         break;
200                 }
201
202                 BLI_ghash_insert(hash, function->name, function);
203         }
204 }
205
206 #if 0
207 static char *gpu_generate_function_prototyps(GHash *hash)
208 {
209         DynStr *ds = BLI_dynstr_new();
210         GHashIterator *ghi;
211         GPUFunction *function;
212         char *name, *prototypes;
213         int a;
214         
215         /* automatically generate function prototypes to add to the top of the
216          * generated code, to avoid have to add the actual code & recompile all */
217         ghi = BLI_ghashIterator_new(hash);
218
219         for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
220                 name = BLI_ghashIterator_getValue(ghi);
221                 function = BLI_ghashIterator_getValue(ghi);
222
223                 BLI_dynstr_appendf(ds, "void %s(", name);
224                 for (a=0; a<function->totparam; a++) {
225                         if (function->paramqual[a] == FUNCTION_QUAL_OUT)
226                                 BLI_dynstr_append(ds, "out ");
227                         else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
228                                 BLI_dynstr_append(ds, "inout ");
229
230                         if (function->paramtype[a] == GPU_TEX2D)
231                                 BLI_dynstr_append(ds, "sampler2D");
232                         else if (function->paramtype[a] == GPU_SHADOW2D)
233                                 BLI_dynstr_append(ds, "sampler2DShadow");
234                         else
235                                 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
236                                 
237                         //BLI_dynstr_appendf(ds, " param%d", a);
238                         
239                         if (a != function->totparam-1)
240                                 BLI_dynstr_append(ds, ", ");
241                 }
242                 BLI_dynstr_append(ds, ");\n");
243         }
244
245         BLI_dynstr_append(ds, "\n");
246
247         prototypes = BLI_dynstr_get_cstring(ds);
248         BLI_dynstr_free(ds);
249
250         return prototypes;
251 }
252 #endif
253
254 static GPUFunction *gpu_lookup_function(const char *name)
255 {
256         if (!FUNCTION_HASH) {
257                 FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
258                 gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
259         }
260
261         return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
262 }
263
264 void gpu_codegen_init(void)
265 {
266         GPU_code_generate_glsl_lib();
267 }
268
269 void gpu_codegen_exit(void)
270 {
271         extern Material defmaterial;    // render module abuse...
272
273         if (defmaterial.gpumaterial.first)
274                 GPU_material_free(&defmaterial.gpumaterial);
275
276         if (FUNCTION_HASH) {
277                 BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
278                 FUNCTION_HASH = NULL;
279         }
280
281         GPU_shader_free_builtin_shaders();
282
283         if (glsl_material_library) {
284                 MEM_freeN(glsl_material_library);
285                 glsl_material_library = NULL;
286         }
287
288         /*if (FUNCTION_PROTOTYPES) {
289                 MEM_freeN(FUNCTION_PROTOTYPES);
290                 FUNCTION_PROTOTYPES = NULL;
291         }*/
292         /*if (FUNCTION_LIB) {
293                 GPU_shader_free(FUNCTION_LIB);
294                 FUNCTION_LIB = NULL;
295         }*/
296 }
297
298 /* GLSL code generation */
299
300 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
301 {
302         char name[1024];
303
304         BLI_snprintf(name, sizeof(name), "%s%d", tmp, id);
305
306         if (from == to) {
307                 BLI_dynstr_append(ds, name);
308         }
309         else if (to == GPU_FLOAT) {
310                 if (from == GPU_VEC4)
311                         BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
312                 else if (from == GPU_VEC3)
313                         BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
314                 else if (from == GPU_VEC2)
315                         BLI_dynstr_appendf(ds, "%s.r", name);
316         }
317         else if (to == GPU_VEC2) {
318                 if (from == GPU_VEC4)
319                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
320                 else if (from == GPU_VEC3)
321                         BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
322                 else if (from == GPU_FLOAT)
323                         BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
324         }
325         else if (to == GPU_VEC3) {
326                 if (from == GPU_VEC4)
327                         BLI_dynstr_appendf(ds, "%s.rgb", name);
328                 else if (from == GPU_VEC2)
329                         BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
330                 else if (from == GPU_FLOAT)
331                         BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name);
332         }
333         else {
334                 if (from == GPU_VEC3)
335                         BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name);
336                 else if (from == GPU_VEC2)
337                         BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
338                 else if (from == GPU_FLOAT)
339                         BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
340         }
341 }
342
343 static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
344 {
345         int i;
346
347         BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
348
349         for (i=0; i<type; i++) {
350                 BLI_dynstr_appendf(ds, "%f", data[i]);
351                 if (i == type-1)
352                         BLI_dynstr_append(ds, ")");
353                 else
354                         BLI_dynstr_append(ds, ", ");
355         }
356 }
357
358 static int codegen_input_has_texture(GPUInput *input)
359 {
360         if (input->link)
361                 return 0;
362         else if (input->ima || input->prv)
363                 return 1;
364         else
365                 return input->tex != NULL;
366 }
367
368 const char *GPU_builtin_name(GPUBuiltin builtin)
369 {
370         if (builtin == GPU_VIEW_MATRIX)
371                 return "unfviewmat";
372         else if (builtin == GPU_OBJECT_MATRIX)
373                 return "unfobmat";
374         else if (builtin == GPU_INVERSE_VIEW_MATRIX)
375                 return "unfinvviewmat";
376         else if (builtin == GPU_INVERSE_OBJECT_MATRIX)
377                 return "unfinvobmat";
378         else if (builtin == GPU_VIEW_POSITION)
379                 return "varposition";
380         else if (builtin == GPU_VIEW_NORMAL)
381                 return "varnormal";
382         else if (builtin == GPU_OBCOLOR)
383                 return "unfobcolor";
384         else if (builtin == GPU_AUTO_BUMPSCALE)
385                 return "unfobautobumpscale";
386         else
387                 return "";
388 }
389
390 /* assign only one texid per buffer to avoid sampling the same texture twice */
391 static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
392 {
393         if (BLI_ghash_haskey(bindhash, key)) {
394                 /* Reuse existing texid */
395                 input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, key));
396         }
397         else {
398                 /* Allocate new texid */
399                 input->texid = *texid;
400                 (*texid)++;
401                 input->bindtex = true;
402                 BLI_ghash_insert(bindhash, key, SET_INT_IN_POINTER(input->texid));
403         }
404 }
405
406 static void codegen_set_unique_ids(ListBase *nodes)
407 {
408         GHash *bindhash, *definehash;
409         GPUNode *node;
410         GPUInput *input;
411         GPUOutput *output;
412         int id = 1, texid = 0;
413
414         bindhash= BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
415         definehash= BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
416
417         for (node=nodes->first; node; node=node->next) {
418                 for (input=node->inputs.first; input; input=input->next) {
419                         /* set id for unique names of uniform variables */
420                         input->id = id++;
421                         input->bindtex = false;
422                         input->definetex = false;
423
424                         /* set texid used for settings texture slot with multitexture */
425                         if (codegen_input_has_texture(input) &&
426                             ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)))
427                         {
428                                 /* assign only one texid per buffer to avoid sampling
429                                  * the same texture twice */
430                                 if (input->link) {
431                                         /* input is texture from buffer */
432                                         codegen_set_texid(bindhash, input, &texid, input->link);
433                                 }
434                                 else if (input->ima) {
435                                         /* input is texture from image */
436                                         codegen_set_texid(bindhash, input, &texid, input->ima);
437                                 }
438                                 else if (input->prv) {
439                                         /* input is texture from preview render */
440                                         codegen_set_texid(bindhash, input, &texid, input->prv);
441                                 }
442                                 else if (input->tex) {
443                                         /* input is user created texture, check tex pointer */
444                                         codegen_set_texid(bindhash, input, &texid, input->tex);
445                                 }
446
447                                 /* make sure this pixel is defined exactly once */
448                                 if (input->source == GPU_SOURCE_TEX_PIXEL) {
449                                         if (input->ima) {
450                                                 if (!BLI_ghash_haskey(definehash, input->ima)) {
451                                                         input->definetex = true;
452                                                         BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
453                                                 }
454                                         }
455                                         else {
456                                                 if (!BLI_ghash_haskey(definehash, input->link)) {
457                                                         input->definetex = true;
458                                                         BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
459                                                 }
460                                         }
461                                 }
462                         }
463                 }
464
465                 for (output=node->outputs.first; output; output=output->next)
466                         /* set id for unique names of tmp variables storing output */
467                         output->id = id++;
468         }
469
470         BLI_ghash_free(bindhash, NULL, NULL);
471         BLI_ghash_free(definehash, NULL, NULL);
472 }
473
474 static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
475 {
476         GPUNode *node;
477         GPUInput *input;
478         const char *name;
479         int builtins = 0;
480
481         /* print uniforms */
482         for (node=nodes->first; node; node=node->next) {
483                 for (input=node->inputs.first; input; input=input->next) {
484                         if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
485                                 /* create exactly one sampler for each texture */
486                                 if (codegen_input_has_texture(input) && input->bindtex)
487                                         BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
488                                                 (input->textype == GPU_TEX2D) ? "sampler2D" : "sampler2DShadow",
489                                                 input->texid);
490                         }
491                         else if (input->source == GPU_SOURCE_BUILTIN) {
492                                 /* only define each builting uniform/varying once */
493                                 if (!(builtins & input->builtin)) {
494                                         builtins |= input->builtin;
495                                         name = GPU_builtin_name(input->builtin);
496
497                                         if (gpu_str_prefix(name, "unf")) {
498                                                 BLI_dynstr_appendf(ds, "uniform %s %s;\n",
499                                                         GPU_DATATYPE_STR[input->type], name);
500                                         }
501                                         else {
502                                                 BLI_dynstr_appendf(ds, "varying %s %s;\n",
503                                                         GPU_DATATYPE_STR[input->type], name);
504                                         }
505                                 }
506                         }
507                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
508                                 if (input->dynamicvec) {
509                                         /* only create uniforms for dynamic vectors */
510                                         BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
511                                                 GPU_DATATYPE_STR[input->type], input->id);
512                                 }
513                                 else {
514                                         /* for others use const so the compiler can do folding */
515                                         BLI_dynstr_appendf(ds, "const %s cons%d = ",
516                                                 GPU_DATATYPE_STR[input->type], input->id);
517                                         codegen_print_datatype(ds, input->type, input->vec);
518                                         BLI_dynstr_append(ds, ";\n");
519                                 }
520                         }
521                         else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
522                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
523                                         GPU_DATATYPE_STR[input->type], input->attribid);
524                         }
525                 }
526         }
527
528         BLI_dynstr_append(ds, "\n");
529
530         return builtins;
531 }
532
533 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
534 {
535         GPUNode *node;
536         GPUInput *input;
537         GPUOutput *output;
538
539         for (node=nodes->first; node; node=node->next) {
540                 /* load pixels from textures */
541                 for (input=node->inputs.first; input; input=input->next) {
542                         if (input->source == GPU_SOURCE_TEX_PIXEL) {
543                                 if (codegen_input_has_texture(input) && input->definetex) {
544                                         BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
545                                         BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
546                                                 input->texid, input->texid);
547                                 }
548                         }
549                 }
550
551                 /* declare temporary variables for node output storage */
552                 for (output=node->outputs.first; output; output=output->next)
553                         BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
554                                 GPU_DATATYPE_STR[output->type], output->id);
555         }
556
557         BLI_dynstr_append(ds, "\n");
558 }
559
560 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
561 {
562         GPUNode *node;
563         GPUInput *input;
564         GPUOutput *output;
565
566         for (node=nodes->first; node; node=node->next) {
567                 BLI_dynstr_appendf(ds, "\t%s(", node->name);
568                 
569                 for (input=node->inputs.first; input; input=input->next) {
570                         if (input->source == GPU_SOURCE_TEX) {
571                                 BLI_dynstr_appendf(ds, "samp%d", input->texid);
572                                 if (input->link)
573                                         BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
574                         }
575                         else if (input->source == GPU_SOURCE_TEX_PIXEL) {
576                                 codegen_convert_datatype(ds, input->link->output->type, input->type,
577                                         "tmp", input->link->output->id);
578                         }
579                         else if (input->source == GPU_SOURCE_BUILTIN) {
580                                 if (input->builtin == GPU_VIEW_NORMAL)
581                                         BLI_dynstr_append(ds, "facingnormal");
582                                 else
583                                         BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
584                         }
585                         else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
586                                 if (input->dynamicvec)
587                                         BLI_dynstr_appendf(ds, "unf%d", input->id);
588                                 else
589                                         BLI_dynstr_appendf(ds, "cons%d", input->id);
590                         }
591                         else if (input->source == GPU_SOURCE_ATTRIB) {
592                                 BLI_dynstr_appendf(ds, "var%d", input->attribid);
593                         }
594                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
595                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL)
596                                         BLI_dynstr_append(ds, "gl_SecondaryColor");
597                                 else if (input->oglbuiltin == GPU_COLOR)
598                                         BLI_dynstr_append(ds, "gl_Color");
599                         }
600
601                         BLI_dynstr_append(ds, ", ");
602                 }
603
604                 for (output=node->outputs.first; output; output=output->next) {
605                         BLI_dynstr_appendf(ds, "tmp%d", output->id);
606                         if (output->next)
607                                 BLI_dynstr_append(ds, ", ");
608                 }
609
610                 BLI_dynstr_append(ds, ");\n");
611         }
612
613         BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
614         codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
615         BLI_dynstr_append(ds, ";\n");
616 }
617
618 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
619 {
620         DynStr *ds = BLI_dynstr_new();
621         char *code;
622         int builtins;
623
624         /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
625
626         codegen_set_unique_ids(nodes);
627         builtins = codegen_print_uniforms_functions(ds, nodes);
628
629         //if (G.debug & G_DEBUG)
630         //      BLI_dynstr_appendf(ds, "/* %s */\n", name);
631
632         BLI_dynstr_append(ds, "void main(void)\n");
633         BLI_dynstr_append(ds, "{\n");
634
635         if (builtins & GPU_VIEW_NORMAL)
636                 BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
637         
638         codegen_declare_tmps(ds, nodes);
639         codegen_call_functions(ds, nodes, output);
640
641         BLI_dynstr_append(ds, "}\n");
642
643         /* create shader */
644         code = BLI_dynstr_get_cstring(ds);
645         BLI_dynstr_free(ds);
646
647         //if (G.debug & G_DEBUG) printf("%s\n", code);
648
649         return code;
650 }
651
652 static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
653 {
654         DynStr *ds = BLI_dynstr_new();
655         GPUNode *node;
656         GPUInput *input;
657         char *code;
658         char *vertcode;
659         
660         for (node=nodes->first; node; node=node->next) {
661                 for (input=node->inputs.first; input; input=input->next) {
662                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
663                                 BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
664                                         GPU_DATATYPE_STR[input->type], input->attribid);
665                                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
666                                         GPU_DATATYPE_STR[input->type], input->attribid);
667                         }
668                 }
669         }
670
671         BLI_dynstr_append(ds, "\n");
672
673         switch (type) {
674                 case GPU_MATERIAL_TYPE_MESH:
675                         vertcode = datatoc_gpu_shader_vertex_glsl;
676                         break;
677                 case GPU_MATERIAL_TYPE_WORLD:
678                         vertcode = datatoc_gpu_shader_vertex_world_glsl;
679                         break;
680                 default:
681                         fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
682                         break;
683         }
684
685         BLI_dynstr_append(ds, vertcode);
686         
687         for (node=nodes->first; node; node=node->next)
688                 for (input=node->inputs.first; input; input=input->next)
689                         if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
690                                 if (input->attribtype == CD_TANGENT) { /* silly exception */
691                                         BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
692                                         BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
693                                 }
694                                 else
695                                         BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
696                         }
697                         /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
698                         else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
699                                 if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
700                                         /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
701                                          * between shader stages and we want the full range of the normal */
702                                         BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5, 0.5, 0.5) * varnormal + vec3(0.5, 0.5, 0.5);\n");
703                                         BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
704                                 }
705                                 else if (input->oglbuiltin == GPU_COLOR) {
706                                         BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
707                                 }
708                         }
709
710         BLI_dynstr_append(ds, "}\n\n");
711
712         code = BLI_dynstr_get_cstring(ds);
713
714         BLI_dynstr_free(ds);
715
716         //if (G.debug & G_DEBUG) printf("%s\n", code);
717
718         return code;
719 }
720
721 int GPU_bicubic_bump_support(void)
722 {
723         return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
724 }
725
726 void GPU_code_generate_glsl_lib(void)
727 {
728         DynStr *ds;
729
730         /* only initialize the library once */
731         if (glsl_material_library)
732                 return;
733
734         ds = BLI_dynstr_new();
735
736         BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
737
738
739         glsl_material_library = BLI_dynstr_get_cstring(ds);
740
741         BLI_dynstr_free(ds);
742 }
743
744
745 /* GPU pass binding/unbinding */
746
747 GPUShader *GPU_pass_shader(GPUPass *pass)
748 {
749         return pass->shader;
750 }
751
752 static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
753 {
754         GPUShader *shader = pass->shader;
755         GPUNode *node;
756         GPUInput *next, *input;
757         ListBase *inputs = &pass->inputs;
758         int extract, z;
759
760         memset(inputs, 0, sizeof(*inputs));
761
762         if (!shader)
763                 return;
764
765         GPU_shader_bind(shader);
766
767         for (node=nodes->first; node; node=node->next) {
768                 z = 0;
769                 for (input=node->inputs.first; input; input=next, z++) {
770                         next = input->next;
771
772                         /* attributes don't need to be bound, they already have
773                          * an id that the drawing functions will use */
774                         if (input->source == GPU_SOURCE_ATTRIB ||
775                             input->source == GPU_SOURCE_BUILTIN ||
776                             input->source == GPU_SOURCE_OPENGL_BUILTIN)
777                         {
778                                 continue;
779                         }
780
781                         if (input->ima || input->tex || input->prv)
782                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
783                         else
784                                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
785
786                         /* pass non-dynamic uniforms to opengl */
787                         extract = 0;
788
789                         if (input->ima || input->tex || input->prv) {
790                                 if (input->bindtex)
791                                         extract = 1;
792                         }
793                         else if (input->dynamicvec)
794                                 extract = 1;
795
796                         if (extract)
797                                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
798
799                         /* extract nodes */
800                         if (extract) {
801                                 BLI_remlink(&node->inputs, input);
802                                 BLI_addtail(inputs, input);
803                         }
804                 }
805         }
806
807         GPU_shader_unbind();
808 }
809
810 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
811 {
812         GPUInput *input;
813         GPUShader *shader = pass->shader;
814         ListBase *inputs = &pass->inputs;
815
816         if (!shader)
817                 return;
818
819         GPU_shader_bind(shader);
820
821         /* now bind the textures */
822         for (input=inputs->first; input; input=input->next) {
823                 if (input->ima)
824                         input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
825                 else if (input->prv)
826                         input->tex = GPU_texture_from_preview(input->prv, mipmap);
827
828                 if (input->tex && input->bindtex) {
829                         GPU_texture_bind(input->tex, input->texid);
830                         GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
831                 }
832                         
833         }
834 }
835
836 void GPU_pass_update_uniforms(GPUPass *pass)
837 {
838         GPUInput *input;
839         GPUShader *shader = pass->shader;
840         ListBase *inputs = &pass->inputs;
841
842         if (!shader)
843                 return;
844
845         /* pass dynamic inputs to opengl, others were removed */
846         for (input=inputs->first; input; input=input->next)
847                 if (!(input->ima || input->tex || input->prv))
848                         GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
849                                 input->dynamicvec);
850 }
851
852 void GPU_pass_unbind(GPUPass *pass)
853 {
854         GPUInput *input;
855         GPUShader *shader = pass->shader;
856         ListBase *inputs = &pass->inputs;
857
858         if (!shader)
859                 return;
860
861         for (input=inputs->first; input; input=input->next) {
862                 if (input->tex && input->bindtex)
863                         GPU_texture_unbind(input->tex);
864
865                 if (input->ima || input->prv)
866                         input->tex = NULL;
867         }
868         
869         GPU_shader_unbind();
870 }
871
872 /* Node Link Functions */
873
874 static GPUNodeLink *GPU_node_link_create(void)
875 {
876         GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
877         link->type = GPU_NONE;
878         link->users++;
879
880         return link;
881 }
882
883 static void gpu_node_link_free(GPUNodeLink *link)
884 {
885         link->users--;
886
887         if (link->users < 0)
888                 fprintf(stderr, "GPU_node_link_free: negative refcount\n");
889         
890         if (link->users == 0) {
891                 if (link->output)
892                         link->output->link = NULL;
893                 MEM_freeN(link);
894         }
895 }
896
897 /* Node Functions */
898
899 static GPUNode *GPU_node_begin(const char *name)
900 {
901         GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
902
903         node->name= name;
904
905         return node;
906 }
907
908 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
909 {
910         GPUInput *input;
911         GPUNode *outnode;
912         const char *name;
913
914         if (link->output) {
915                 outnode = link->output->node;
916                 name = outnode->name;
917
918                 if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
919                         input = MEM_dupallocN(outnode->inputs.first);
920                         input->type = type;
921                         if (input->link)
922                                 input->link->users++;
923                         BLI_addtail(&node->inputs, input);
924                         return;
925                 }
926         }
927         
928         input = MEM_callocN(sizeof(GPUInput), "GPUInput");
929         input->node = node;
930
931         if (link->builtin) {
932                 /* builtin uniform */
933                 input->type = type;
934                 input->source = GPU_SOURCE_BUILTIN;
935                 input->builtin = link->builtin;
936
937                 MEM_freeN(link);
938         }
939         else if (link->oglbuiltin) {
940                 /* builtin uniform */
941                 input->type = type;
942                 input->source = GPU_SOURCE_OPENGL_BUILTIN;
943                 input->oglbuiltin = link->oglbuiltin;
944
945                 MEM_freeN(link);
946         }
947         else if (link->output) {
948                 /* link to a node output */
949                 input->type = type;
950                 input->source = GPU_SOURCE_TEX_PIXEL;
951                 input->link = link;
952                 link->users++;
953         }
954         else if (link->dynamictex) {
955                 /* dynamic texture, GPUTexture is updated/deleted externally */
956                 input->type = type;
957                 input->source = GPU_SOURCE_TEX;
958
959                 input->tex = link->dynamictex;
960                 input->textarget = GL_TEXTURE_2D;
961                 input->textype = type;
962                 input->dynamictex = true;
963                 input->dynamicdata = link->ptr2;
964                 MEM_freeN(link);
965         }
966         else if (link->texture) {
967                 /* small texture created on the fly, like for colorbands */
968                 input->type = GPU_VEC4;
969                 input->source = GPU_SOURCE_TEX;
970                 input->textype = type;
971
972                 //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
973                 input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
974                 input->textarget = GL_TEXTURE_2D;
975
976                 MEM_freeN(link->ptr1);
977                 MEM_freeN(link);
978         }
979         else if (link->image) {
980                 /* blender image */
981                 input->type = GPU_VEC4;
982                 input->source = GPU_SOURCE_TEX;
983
984                 if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW)
985                         input->prv = link->ptr1;
986                 else {
987                         input->ima = link->ptr1;
988                         input->iuser = link->ptr2;
989                         input->image_isdata = link->image_isdata;
990                 }
991                 input->textarget = GL_TEXTURE_2D;
992                 input->textype = GPU_TEX2D;
993                 MEM_freeN(link);
994         }
995         else if (link->attribtype) {
996                 /* vertex attribute */
997                 input->type = type;
998                 input->source = GPU_SOURCE_ATTRIB;
999
1000                 input->attribtype = link->attribtype;
1001                 BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
1002                 MEM_freeN(link);
1003         }
1004         else {
1005                 /* uniform vector */
1006                 input->type = type;
1007                 input->source = GPU_SOURCE_VEC_UNIFORM;
1008
1009                 memcpy(input->vec, link->ptr1, type*sizeof(float));
1010                 if (link->dynamic) {
1011                         input->dynamicvec= link->ptr1;
1012                         input->dynamictype= link->dynamictype;
1013                         input->dynamicdata= link->ptr2;
1014                 }
1015                 MEM_freeN(link);
1016         }
1017
1018         BLI_addtail(&node->inputs, input);
1019 }
1020
1021 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
1022 {
1023         GPUNodeLink *link;
1024
1025         if (sock->link) {
1026                 gpu_node_input_link(node, sock->link, sock->type);
1027         }
1028         else {
1029                 link = GPU_node_link_create();
1030                 link->ptr1 = sock->vec;
1031                 gpu_node_input_link(node, link, sock->type);
1032         }
1033 }
1034
1035 static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
1036 {
1037         GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
1038
1039         output->type = type;
1040         output->node = node;
1041
1042         if (link) {
1043                 *link = output->link = GPU_node_link_create();
1044                 output->link->type = type;
1045                 output->link->output = output;
1046
1047                 /* note: the caller owns the reference to the linkfer, GPUOutput
1048                  * merely points to it, and if the node is destroyed it will
1049                  * set that pointer to NULL */
1050         }
1051
1052         BLI_addtail(&node->outputs, output);
1053 }
1054
1055 static void gpu_inputs_free(ListBase *inputs)
1056 {
1057         GPUInput *input;
1058
1059         for (input=inputs->first; input; input=input->next) {
1060                 if (input->link)
1061                         gpu_node_link_free(input->link);
1062                 else if (input->tex && !input->dynamictex)
1063                         GPU_texture_free(input->tex);
1064         }
1065
1066         BLI_freelistN(inputs);
1067 }
1068
1069 static void gpu_node_free(GPUNode *node)
1070 {
1071         GPUOutput *output;
1072
1073         gpu_inputs_free(&node->inputs);
1074
1075         for (output=node->outputs.first; output; output=output->next)
1076                 if (output->link) {
1077                         output->link->output = NULL;
1078                         gpu_node_link_free(output->link);
1079                 }
1080
1081         BLI_freelistN(&node->outputs);
1082         MEM_freeN(node);
1083 }
1084
1085 static void gpu_nodes_free(ListBase *nodes)
1086 {
1087         GPUNode *node;
1088
1089         while ((node = BLI_pophead(nodes))) {
1090                 gpu_node_free(node);
1091         }
1092 }
1093
1094 /* vertex attributes */
1095
1096 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
1097 {
1098         GPUNode *node;
1099         GPUInput *input;
1100         int a;
1101
1102         /* convert attributes requested by node inputs to an array of layers,
1103          * checking for duplicates and assigning id's starting from zero. */
1104
1105         memset(attribs, 0, sizeof(*attribs));
1106
1107         for (node=nodes->first; node; node=node->next) {
1108                 for (input=node->inputs.first; input; input=input->next) {
1109                         if (input->source == GPU_SOURCE_ATTRIB) {
1110                                 for (a=0; a<attribs->totlayer; a++) {
1111                                         if (attribs->layer[a].type == input->attribtype &&
1112                                             strcmp(attribs->layer[a].name, input->attribname) == 0)
1113                                         {
1114                                                 break;
1115                                         }
1116                                 }
1117
1118                                 if (a < GPU_MAX_ATTRIB) {
1119                                         if (a == attribs->totlayer) {
1120                                                 input->attribid = attribs->totlayer++;
1121                                                 input->attribfirst = 1;
1122
1123                                                 attribs->layer[a].type = input->attribtype;
1124                                                 attribs->layer[a].attribid = input->attribid;
1125                                                 BLI_strncpy(attribs->layer[a].name, input->attribname,
1126                                                             sizeof(attribs->layer[a].name));
1127                                         }
1128                                         else {
1129                                                 input->attribid = attribs->layer[a].attribid;
1130                                         }
1131                                 }
1132                         }
1133                 }
1134         }
1135 }
1136
1137 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
1138 {
1139         GPUNode *node;
1140         GPUInput *input;
1141         
1142         *builtin= 0;
1143
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;
1148 }
1149
1150 /* varargs linking  */
1151
1152 GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
1153 {
1154         GPUNodeLink *link = GPU_node_link_create();
1155
1156         link->attribtype= type;
1157         link->attribname= name;
1158
1159         return link;
1160 }
1161
1162 GPUNodeLink *GPU_uniform(float *num)
1163 {
1164         GPUNodeLink *link = GPU_node_link_create();
1165
1166         link->ptr1= num;
1167         link->ptr2= NULL;
1168
1169         return link;
1170 }
1171
1172 GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
1173 {
1174         GPUNodeLink *link = GPU_node_link_create();
1175
1176         link->ptr1= num;
1177         link->ptr2= data;
1178         link->dynamic= true;
1179         link->dynamictype = dynamictype;
1180
1181
1182         return link;
1183 }
1184
1185 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
1186 {
1187         GPUNodeLink *link = GPU_node_link_create();
1188
1189         link->image = GPU_NODE_LINK_IMAGE_BLENDER;
1190         link->ptr1 = ima;
1191         link->ptr2 = iuser;
1192         link->image_isdata = is_data;
1193
1194         return link;
1195 }
1196
1197 GPUNodeLink *GPU_image_preview(PreviewImage *prv)
1198 {
1199         GPUNodeLink *link = GPU_node_link_create();
1200         
1201         link->image= GPU_NODE_LINK_IMAGE_PREVIEW;
1202         link->ptr1= prv;
1203         
1204         return link;
1205 }
1206
1207
1208 GPUNodeLink *GPU_texture(int size, float *pixels)
1209 {
1210         GPUNodeLink *link = GPU_node_link_create();
1211
1212         link->texture = true;
1213         link->texturesize = size;
1214         link->ptr1= pixels;
1215
1216         return link;
1217 }
1218
1219 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
1220 {
1221         GPUNodeLink *link = GPU_node_link_create();
1222
1223         link->dynamic = true;
1224         link->dynamictex = tex;
1225         link->dynamictype = dynamictype;
1226         link->ptr2 = data;
1227
1228         return link;
1229 }
1230
1231 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
1232 {
1233         GPUNodeLink *link = GPU_node_link_create();
1234
1235         link->builtin= builtin;
1236
1237         return link;
1238 }
1239
1240 GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
1241 {
1242         GPUNodeLink *link = GPU_node_link_create();
1243
1244         link->oglbuiltin = builtin;
1245
1246         return link;
1247 }
1248
1249 bool GPU_link(GPUMaterial *mat, const char *name, ...)
1250 {
1251         GPUNode *node;
1252         GPUFunction *function;
1253         GPUNodeLink *link, **linkptr;
1254         va_list params;
1255         int i;
1256
1257         function = gpu_lookup_function(name);
1258         if (!function) {
1259                 fprintf(stderr, "GPU failed to find function %s\n", name);
1260                 return 0;
1261         }
1262
1263         node = GPU_node_begin(name);
1264
1265         va_start(params, name);
1266         for (i=0; i<function->totparam; i++) {
1267                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1268                         linkptr= va_arg(params, GPUNodeLink**);
1269                         gpu_node_output(node, function->paramtype[i], linkptr);
1270                 }
1271                 else {
1272                         link= va_arg(params, GPUNodeLink*);
1273                         gpu_node_input_link(node, link, function->paramtype[i]);
1274                 }
1275         }
1276         va_end(params);
1277
1278         gpu_material_add_node(mat, node);
1279
1280         return 1;
1281 }
1282
1283 bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
1284 {
1285         GPUNode *node;
1286         GPUFunction *function;
1287         GPUNodeLink *link, **linkptr;
1288         va_list params;
1289         int i, totin, totout;
1290
1291         function = gpu_lookup_function(name);
1292         if (!function) {
1293                 fprintf(stderr, "GPU failed to find function %s\n", name);
1294                 return 0;
1295         }
1296
1297         node = GPU_node_begin(name);
1298         totin = 0;
1299         totout = 0;
1300
1301         if (in) {
1302                 for (i = 0; in[i].type != GPU_NONE; i++) {
1303                         gpu_node_input_socket(node, &in[i]);
1304                         totin++;
1305                 }
1306         }
1307         
1308         if (out) {
1309                 for (i = 0; out[i].type != GPU_NONE; i++) {
1310                         gpu_node_output(node, out[i].type, &out[i].link);
1311                         totout++;
1312                 }
1313         }
1314
1315         va_start(params, out);
1316         for (i=0; i<function->totparam; i++) {
1317                 if (function->paramqual[i] != FUNCTION_QUAL_IN) {
1318                         if (totout == 0) {
1319                                 linkptr= va_arg(params, GPUNodeLink**);
1320                                 gpu_node_output(node, function->paramtype[i], linkptr);
1321                         }
1322                         else
1323                                 totout--;
1324                 }
1325                 else {
1326                         if (totin == 0) {
1327                                 link= va_arg(params, GPUNodeLink*);
1328                                 if (link->socket)
1329                                         gpu_node_input_socket(node, link->socket);
1330                                 else
1331                                         gpu_node_input_link(node, link, function->paramtype[i]);
1332                         }
1333                         else
1334                                 totin--;
1335                 }
1336         }
1337         va_end(params);
1338
1339         gpu_material_add_node(mat, node);
1340         
1341         return 1;
1342 }
1343
1344 int GPU_link_changed(GPUNodeLink *link)
1345 {
1346         GPUNode *node;
1347         GPUInput *input;
1348         const char *name;
1349
1350         if (link->output) {
1351                 node = link->output->node;
1352                 name = node->name;
1353
1354                 if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
1355                         input = node->inputs.first;
1356                         return (input->link != NULL);
1357                 }
1358
1359                 return 1;
1360         }
1361         else
1362                 return 0;
1363 }
1364
1365 /* Pass create/free */
1366
1367 static void gpu_nodes_tag(GPUNodeLink *link)
1368 {
1369         GPUNode *node;
1370         GPUInput *input;
1371
1372         if (!link->output)
1373                 return;
1374
1375         node = link->output->node;
1376         if (node->tag)
1377                 return;
1378         
1379         node->tag = true;
1380         for (input=node->inputs.first; input; input=input->next)
1381                 if (input->link)
1382                         gpu_nodes_tag(input->link);
1383 }
1384
1385 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
1386 {
1387         GPUNode *node, *next;
1388
1389         for (node=nodes->first; node; node=node->next)
1390                 node->tag = false;
1391
1392         gpu_nodes_tag(outlink);
1393
1394         for (node=nodes->first; node; node=next) {
1395                 next = node->next;
1396
1397                 if (!node->tag) {
1398                         BLI_remlink(nodes, node);
1399                         gpu_node_free(node);
1400                 }
1401         }
1402 }
1403
1404 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
1405                                                    GPUVertexAttribs *attribs, int *builtins,
1406                                                    const GPUMatType type, const char *UNUSED(name))
1407 {
1408         GPUShader *shader;
1409         GPUPass *pass;
1410         char *vertexcode, *fragmentcode;
1411
1412         /*if (!FUNCTION_LIB) {
1413                 GPU_nodes_free(nodes);
1414                 return NULL;
1415         }*/
1416
1417         /* prune unused nodes */
1418         gpu_nodes_prune(nodes, outlink);
1419
1420         gpu_nodes_get_vertex_attributes(nodes, attribs);
1421         gpu_nodes_get_builtin_flag(nodes, builtins);
1422
1423         /* generate code and compile with opengl */
1424         fragmentcode = code_generate_fragment(nodes, outlink->output);
1425         vertexcode = code_generate_vertex(nodes, type);
1426         shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
1427
1428         /* failed? */
1429         if (!shader) {
1430                 if (fragmentcode)
1431                         MEM_freeN(fragmentcode);
1432                 if (vertexcode)
1433                         MEM_freeN(vertexcode);
1434                 memset(attribs, 0, sizeof(*attribs));
1435                 memset(builtins, 0, sizeof(*builtins));
1436                 gpu_nodes_free(nodes);
1437                 return NULL;
1438         }
1439         
1440         /* create pass */
1441         pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
1442
1443         pass->output = outlink->output;
1444         pass->shader = shader;
1445         pass->fragmentcode = fragmentcode;
1446         pass->vertexcode = vertexcode;
1447         pass->libcode = glsl_material_library;
1448
1449         /* extract dynamic inputs and throw away nodes */
1450         gpu_nodes_extract_dynamic_inputs(pass, nodes);
1451         gpu_nodes_free(nodes);
1452
1453         return pass;
1454 }
1455
1456 void GPU_pass_free(GPUPass *pass)
1457 {
1458         GPU_shader_free(pass->shader);
1459         gpu_inputs_free(&pass->inputs);
1460         if (pass->fragmentcode)
1461                 MEM_freeN(pass->fragmentcode);
1462         if (pass->vertexcode)
1463                 MEM_freeN(pass->vertexcode);
1464         MEM_freeN(pass);
1465 }
1466