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