Blender V2.61 - r43446

gpu_codegen.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Brecht Van Lommel.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "GL/glew.h"
00034 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "DNA_customdata_types.h"
00038 #include "DNA_image_types.h"
00039 #include "DNA_material_types.h"
00040 
00041 #include "BLI_blenlib.h"
00042 #include "BLI_utildefines.h"
00043 #include "BLI_dynstr.h"
00044 #include "BLI_ghash.h"
00045 #include "BLI_heap.h"
00046 
00047 #include "GPU_material.h"
00048 #include "GPU_extensions.h"
00049 
00050 #include "BLO_sys_types.h" // for intptr_t support
00051 
00052 #include "gpu_codegen.h"
00053 
00054 #include "node_util.h" /* For muting node stuff... */
00055 
00056 #include <string.h>
00057 #include <stdarg.h>
00058 
00059 extern char datatoc_gpu_shader_material_glsl[];
00060 extern char datatoc_gpu_shader_vertex_glsl[];
00061 
00062 
00063 static char *glsl_material_library = NULL;
00064 
00065 
00066 /* structs and defines */
00067 
00068 static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
00069     NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
00070 
00071 /* GLSL code parsing for finding function definitions.
00072  * These are stored in a hash for lookup when creating a material. */
00073 
00074 static GHash *FUNCTION_HASH= NULL;
00075 /*static char *FUNCTION_PROTOTYPES= NULL;
00076 static GPUShader *FUNCTION_LIB= NULL;*/
00077 
00078 static int gpu_str_prefix(const char *str, const char *prefix)
00079 {
00080     while(*str && *prefix) {
00081         if(*str != *prefix)
00082             return 0;
00083 
00084         str++;
00085         prefix++;
00086     }
00087     
00088     return (*prefix == '\0');
00089 }
00090 
00091 static char *gpu_str_skip_token(char *str, char *token, int max)
00092 {
00093     int len = 0;
00094 
00095     /* skip a variable/function name */
00096     while(*str) {
00097         if(ELEM7(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
00098             break;
00099         else {
00100             if(token && len < max-1) {
00101                 *token= *str;
00102                 token++;
00103                 len++;
00104             }
00105             str++;
00106         }
00107     }
00108 
00109     if(token)
00110         *token= '\0';
00111 
00112     /* skip the next special characters:
00113      * note the missing ')' */
00114     while(*str) {
00115         if(ELEM6(*str, ' ', '(', ',', '\t', '\n', '\r'))
00116             str++;
00117         else
00118             break;
00119     }
00120 
00121     return str;
00122 }
00123 
00124 static void gpu_parse_functions_string(GHash *hash, char *code)
00125 {
00126     GPUFunction *function;
00127     int i, type, qual;
00128 
00129     while((code = strstr(code, "void "))) {
00130         function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
00131 
00132         code = gpu_str_skip_token(code, NULL, 0);
00133         code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
00134 
00135         /* get parameters */
00136         while(*code && *code != ')') {
00137             /* test if it's an input or output */
00138             qual = FUNCTION_QUAL_IN;
00139             if(gpu_str_prefix(code, "out "))
00140                 qual = FUNCTION_QUAL_OUT;
00141             if(gpu_str_prefix(code, "inout "))
00142                 qual = FUNCTION_QUAL_INOUT;
00143             if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in "))
00144                 code = gpu_str_skip_token(code, NULL, 0);
00145 
00146             /* test for type */
00147             type= 0;
00148             for(i=1; i<=16; i++) {
00149                 if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
00150                     type= i;
00151                     break;
00152                 }
00153             }
00154 
00155             if(!type && gpu_str_prefix(code, "sampler2DShadow"))
00156                 type= GPU_SHADOW2D;
00157             if(!type && gpu_str_prefix(code, "sampler2D"))
00158                 type= GPU_TEX2D;
00159 
00160             if(type) {
00161                 /* add paramater */
00162                 code = gpu_str_skip_token(code, NULL, 0);
00163                 code = gpu_str_skip_token(code, NULL, 0);
00164                 function->paramqual[function->totparam]= qual;
00165                 function->paramtype[function->totparam]= type;
00166                 function->totparam++;
00167             }
00168             else {
00169                 fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
00170                 break;
00171             }
00172         }
00173 
00174         if(function->name[0] == '\0' || function->totparam == 0) {
00175             fprintf(stderr, "GPU functions parse error.\n");
00176             MEM_freeN(function);
00177             break;
00178         }
00179 
00180         BLI_ghash_insert(hash, function->name, function);
00181     }
00182 }
00183 
00184 #if 0
00185 static char *gpu_generate_function_prototyps(GHash *hash)
00186 {
00187     DynStr *ds = BLI_dynstr_new();
00188     GHashIterator *ghi;
00189     GPUFunction *function;
00190     char *name, *prototypes;
00191     int a;
00192     
00193     /* automatically generate function prototypes to add to the top of the
00194      * generated code, to avoid have to add the actual code & recompile all */
00195     ghi = BLI_ghashIterator_new(hash);
00196 
00197     for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
00198         name = BLI_ghashIterator_getValue(ghi);
00199         function = BLI_ghashIterator_getValue(ghi);
00200 
00201         BLI_dynstr_appendf(ds, "void %s(", name);
00202         for(a=0; a<function->totparam; a++) {
00203             if(function->paramqual[a] == FUNCTION_QUAL_OUT)
00204                 BLI_dynstr_append(ds, "out ");
00205             else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
00206                 BLI_dynstr_append(ds, "inout ");
00207 
00208             if(function->paramtype[a] == GPU_TEX2D)
00209                 BLI_dynstr_append(ds, "sampler2D");
00210             else if(function->paramtype[a] == GPU_SHADOW2D)
00211                 BLI_dynstr_append(ds, "sampler2DShadow");
00212             else
00213                 BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
00214                 
00215             //BLI_dynstr_appendf(ds, " param%d", a);
00216             
00217             if(a != function->totparam-1)
00218                 BLI_dynstr_append(ds, ", ");
00219         }
00220         BLI_dynstr_append(ds, ");\n");
00221     }
00222 
00223     BLI_dynstr_append(ds, "\n");
00224 
00225     prototypes = BLI_dynstr_get_cstring(ds);
00226     BLI_dynstr_free(ds);
00227 
00228     return prototypes;
00229 }
00230 #endif
00231 
00232 GPUFunction *GPU_lookup_function(const char *name)
00233 {
00234     if(!FUNCTION_HASH) {
00235         FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "GPU_lookup_function gh");
00236         gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
00237         /*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
00238         FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/
00239     }
00240 
00241     return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
00242 }
00243 
00244 void GPU_codegen_init(void)
00245 {
00246     GPU_code_generate_glsl_lib();
00247 }
00248 
00249 void GPU_codegen_exit(void)
00250 {
00251     extern Material defmaterial;    // render module abuse...
00252 
00253     if(defmaterial.gpumaterial.first)
00254         GPU_material_free(&defmaterial);
00255 
00256     if(FUNCTION_HASH) {
00257         BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN);
00258         FUNCTION_HASH = NULL;
00259     }
00260 
00261     if(glsl_material_library) {
00262         MEM_freeN(glsl_material_library);
00263         glsl_material_library = NULL;
00264     }
00265 
00266     /*if(FUNCTION_PROTOTYPES) {
00267         MEM_freeN(FUNCTION_PROTOTYPES);
00268         FUNCTION_PROTOTYPES = NULL;
00269     }*/
00270     /*if(FUNCTION_LIB) {
00271         GPU_shader_free(FUNCTION_LIB);
00272         FUNCTION_LIB = NULL;
00273     }*/
00274 }
00275 
00276 /* GLSL code generation */
00277 
00278 static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
00279 {
00280     char name[1024];
00281 
00282     BLI_snprintf(name, sizeof(name), "%s%d", tmp, id);
00283 
00284     if (from == to) {
00285         BLI_dynstr_append(ds, name);
00286     }
00287     else if (to == GPU_FLOAT) {
00288         if (from == GPU_VEC4)
00289             BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
00290         else if (from == GPU_VEC3)
00291             BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
00292         else if (from == GPU_VEC2)
00293             BLI_dynstr_appendf(ds, "%s.r", name);
00294     }
00295     else if (to == GPU_VEC2) {
00296         if (from == GPU_VEC4)
00297             BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
00298         else if (from == GPU_VEC3)
00299             BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
00300         else if (from == GPU_FLOAT)
00301             BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
00302     }
00303     else if (to == GPU_VEC3) {
00304         if (from == GPU_VEC4)
00305             BLI_dynstr_appendf(ds, "%s.rgb", name);
00306         else if (from == GPU_VEC2)
00307             BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name);
00308         else if (from == GPU_FLOAT)
00309             BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name);
00310     }
00311     else {
00312         if (from == GPU_VEC3)
00313             BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name);
00314         else if (from == GPU_VEC2)
00315             BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
00316         else if (from == GPU_FLOAT)
00317             BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
00318     }
00319 }
00320 
00321 static void codegen_print_datatype(DynStr *ds, int type, float *data)
00322 {
00323     int i;
00324 
00325     BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
00326 
00327     for(i=0; i<type; i++) {
00328         BLI_dynstr_appendf(ds, "%f", data[i]);
00329         if(i == type-1)
00330             BLI_dynstr_append(ds, ")");
00331         else
00332             BLI_dynstr_append(ds, ", ");
00333     }
00334 }
00335 
00336 static int codegen_input_has_texture(GPUInput *input)
00337 {
00338     if (input->link)
00339         return 0;
00340     else if(input->ima)
00341         return 1;
00342     else
00343         return input->tex != NULL;
00344 }
00345 
00346 const char *GPU_builtin_name(GPUBuiltin builtin)
00347 {
00348     if(builtin == GPU_VIEW_MATRIX)
00349         return "unfviewmat";
00350     else if(builtin == GPU_OBJECT_MATRIX)
00351         return "unfobmat";
00352     else if(builtin == GPU_INVERSE_VIEW_MATRIX)
00353         return "unfinvviewmat";
00354     else if(builtin == GPU_INVERSE_OBJECT_MATRIX)
00355         return "unfinvobmat";
00356     else if(builtin == GPU_VIEW_POSITION)
00357         return "varposition";
00358     else if(builtin == GPU_VIEW_NORMAL)
00359         return "varnormal";
00360     else if(builtin == GPU_OBCOLOR)
00361         return "unfobcolor";
00362     else if(builtin == GPU_AUTO_BUMPSCALE)
00363         return "unfobautobumpscale";
00364     else
00365         return "";
00366 }
00367 
00368 static void codegen_set_unique_ids(ListBase *nodes)
00369 {
00370     GHash *bindhash, *definehash;
00371     GPUNode *node;
00372     GPUInput *input;
00373     GPUOutput *output;
00374     int id = 1, texid = 0;
00375 
00376     bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "codegen_set_unique_ids1 gh");
00377     definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "codegen_set_unique_ids2 gh");
00378 
00379     for (node=nodes->first; node; node=node->next) {
00380         for (input=node->inputs.first; input; input=input->next) {
00381             /* set id for unique names of uniform variables */
00382             input->id = id++;
00383             input->bindtex = 0;
00384             input->definetex = 0;
00385 
00386             /* set texid used for settings texture slot with multitexture */
00387             if (codegen_input_has_texture(input) &&
00388                 ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) {
00389                 if (input->link) {
00390                     /* input is texture from buffer, assign only one texid per
00391                        buffer to avoid sampling the same texture twice */
00392                     if (!BLI_ghash_haskey(bindhash, input->link)) {
00393                         input->texid = texid++;
00394                         input->bindtex = 1;
00395                         BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
00396                     }
00397                     else
00398                         input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
00399                 }
00400                 else if(input->ima) {
00401                     /* input is texture from image, assign only one texid per
00402                        buffer to avoid sampling the same texture twice */
00403                     if (!BLI_ghash_haskey(bindhash, input->ima)) {
00404                         input->texid = texid++;
00405                         input->bindtex = 1;
00406                         BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
00407                     }
00408                     else
00409                         input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
00410                 }
00411                 else {
00412                     if (!BLI_ghash_haskey(bindhash, input->tex)) {
00413                         /* input is user created texture, check tex pointer */
00414                         input->texid = texid++;
00415                         input->bindtex = 1;
00416                         BLI_ghash_insert(bindhash, input->tex, SET_INT_IN_POINTER(input->texid));
00417                     }
00418                     else
00419                         input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->tex));
00420                 }
00421 
00422                 /* make sure this pixel is defined exactly once */
00423                 if (input->source == GPU_SOURCE_TEX_PIXEL) {
00424                     if(input->ima) {
00425                         if (!BLI_ghash_haskey(definehash, input->ima)) {
00426                             input->definetex = 1;
00427                             BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
00428                         }
00429                     }
00430                     else {
00431                         if (!BLI_ghash_haskey(definehash, input->link)) {
00432                             input->definetex = 1;
00433                             BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
00434                         }
00435                     }
00436                 }
00437             }
00438         }
00439 
00440         for (output=node->outputs.first; output; output=output->next)
00441             /* set id for unique names of tmp variables storing output */
00442             output->id = id++;
00443     }
00444 
00445     BLI_ghash_free(bindhash, NULL, NULL);
00446     BLI_ghash_free(definehash, NULL, NULL);
00447 }
00448 
00449 static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
00450 {
00451     GPUNode *node;
00452     GPUInput *input;
00453     const char *name;
00454     int builtins = 0;
00455 
00456     /* print uniforms */
00457     for (node=nodes->first; node; node=node->next) {
00458         for (input=node->inputs.first; input; input=input->next) {
00459             if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
00460                 /* create exactly one sampler for each texture */
00461                 if (codegen_input_has_texture(input) && input->bindtex)
00462                     BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
00463                         (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
00464                         input->texid);
00465             }
00466             else if(input->source == GPU_SOURCE_BUILTIN) {
00467                 /* only define each builting uniform/varying once */
00468                 if(!(builtins & input->builtin)) {
00469                     builtins |= input->builtin;
00470                     name = GPU_builtin_name(input->builtin);
00471 
00472                     if(gpu_str_prefix(name, "unf")) {
00473                         BLI_dynstr_appendf(ds, "uniform %s %s;\n",
00474                             GPU_DATATYPE_STR[input->type], name);
00475                     }
00476                     else {
00477                         BLI_dynstr_appendf(ds, "varying %s %s;\n",
00478                             GPU_DATATYPE_STR[input->type], name);
00479                     }
00480                 }
00481             }
00482             else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
00483                 if(input->dynamicvec) {
00484                     /* only create uniforms for dynamic vectors */
00485                     BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
00486                         GPU_DATATYPE_STR[input->type], input->id);
00487                 }
00488                 else {
00489                     /* for others use const so the compiler can do folding */
00490                     BLI_dynstr_appendf(ds, "const %s cons%d = ",
00491                         GPU_DATATYPE_STR[input->type], input->id);
00492                     codegen_print_datatype(ds, input->type, input->vec);
00493                     BLI_dynstr_append(ds, ";\n");
00494                 }
00495             }
00496             else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
00497                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
00498                     GPU_DATATYPE_STR[input->type], input->attribid);
00499             }
00500         }
00501     }
00502 
00503     BLI_dynstr_append(ds, "\n");
00504 }
00505 
00506 static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
00507 {
00508     GPUNode *node;
00509     GPUInput *input;
00510     GPUOutput *output;
00511 
00512     for (node=nodes->first; node; node=node->next) {
00513         /* load pixels from textures */
00514         for (input=node->inputs.first; input; input=input->next) {
00515             if (input->source == GPU_SOURCE_TEX_PIXEL) {
00516                 if (codegen_input_has_texture(input) && input->definetex) {
00517                     BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
00518                     BLI_dynstr_appendf(ds, "samp%d, gl_TexCoord[%d].st);\n",
00519                         input->texid, input->texid);
00520                 }
00521             }
00522         }
00523 
00524         /* declare temporary variables for node output storage */
00525         for (output=node->outputs.first; output; output=output->next)
00526             BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
00527                 GPU_DATATYPE_STR[output->type], output->id);
00528     }
00529 
00530     BLI_dynstr_append(ds, "\n");
00531 }
00532 
00533 static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
00534 {
00535     GPUNode *node;
00536     GPUInput *input;
00537     GPUOutput *output;
00538 
00539     for (node=nodes->first; node; node=node->next) {
00540         BLI_dynstr_appendf(ds, "\t%s(", node->name);
00541         
00542         for (input=node->inputs.first; input; input=input->next) {
00543             if (input->source == GPU_SOURCE_TEX) {
00544                 BLI_dynstr_appendf(ds, "samp%d", input->texid);
00545                 if (input->link)
00546                     BLI_dynstr_appendf(ds, ", gl_TexCoord[%d].st", input->texid);
00547             }
00548             else if (input->source == GPU_SOURCE_TEX_PIXEL) {
00549                 codegen_convert_datatype(ds, input->link->output->type, input->type,
00550                     "tmp", input->link->output->id);
00551             }
00552             else if(input->source == GPU_SOURCE_BUILTIN)
00553                 BLI_dynstr_appendf(ds, "%s", GPU_builtin_name(input->builtin));
00554             else if(input->source == GPU_SOURCE_VEC_UNIFORM) {
00555                 if(input->dynamicvec)
00556                     BLI_dynstr_appendf(ds, "unf%d", input->id);
00557                 else
00558                     BLI_dynstr_appendf(ds, "cons%d", input->id);
00559             }
00560             else if (input->source == GPU_SOURCE_ATTRIB)
00561                 BLI_dynstr_appendf(ds, "var%d", input->attribid);
00562 
00563             BLI_dynstr_append(ds, ", ");
00564         }
00565 
00566         for (output=node->outputs.first; output; output=output->next) {
00567             BLI_dynstr_appendf(ds, "tmp%d", output->id);
00568             if (output->next)
00569                 BLI_dynstr_append(ds, ", ");
00570         }
00571 
00572         BLI_dynstr_append(ds, ");\n");
00573     }
00574 
00575     BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
00576     codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
00577     BLI_dynstr_append(ds, ";\n");
00578 }
00579 
00580 static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *UNUSED(name))
00581 {
00582     DynStr *ds = BLI_dynstr_new();
00583     char *code;
00584 
00585     /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
00586 
00587     codegen_set_unique_ids(nodes);
00588     codegen_print_uniforms_functions(ds, nodes);
00589 
00590     //if(G.f & G_DEBUG)
00591     //  BLI_dynstr_appendf(ds, "/* %s */\n", name);
00592 
00593     BLI_dynstr_append(ds, "void main(void)\n");
00594     BLI_dynstr_append(ds, "{\n");
00595 
00596     codegen_declare_tmps(ds, nodes);
00597     codegen_call_functions(ds, nodes, output);
00598 
00599     BLI_dynstr_append(ds, "}\n");
00600 
00601     /* create shader */
00602     code = BLI_dynstr_get_cstring(ds);
00603     BLI_dynstr_free(ds);
00604 
00605     //if(G.f & G_DEBUG) printf("%s\n", code);
00606 
00607     return code;
00608 }
00609 
00610 static char *code_generate_vertex(ListBase *nodes)
00611 {
00612     DynStr *ds = BLI_dynstr_new();
00613     GPUNode *node;
00614     GPUInput *input;
00615     char *code;
00616     
00617     for (node=nodes->first; node; node=node->next) {
00618         for (input=node->inputs.first; input; input=input->next) {
00619             if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
00620                 BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
00621                     GPU_DATATYPE_STR[input->type], input->attribid);
00622                 BLI_dynstr_appendf(ds, "varying %s var%d;\n",
00623                     GPU_DATATYPE_STR[input->type], input->attribid);
00624             }
00625         }
00626     }
00627 
00628     BLI_dynstr_append(ds, "\n");
00629     BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
00630 
00631     for (node=nodes->first; node; node=node->next)
00632         for (input=node->inputs.first; input; input=input->next)
00633             if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
00634                 if(input->attribtype == CD_TANGENT) /* silly exception */
00635                 {
00636                     BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
00637                     BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
00638                 }
00639                 else
00640                     BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
00641             }
00642 
00643     BLI_dynstr_append(ds, "}\n\n");
00644 
00645     code = BLI_dynstr_get_cstring(ds);
00646 
00647     BLI_dynstr_free(ds);
00648 
00649     //if(G.f & G_DEBUG) printf("%s\n", code);
00650 
00651     return code;
00652 }
00653 
00654 int GPU_bicubic_bump_support(void)
00655 {
00656     return GLEW_ARB_texture_gather && GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
00657 }
00658 
00659 void GPU_code_generate_glsl_lib(void)
00660 {
00661     DynStr *ds;
00662 
00663     /* only initialize the library once */
00664     if(glsl_material_library)
00665         return;
00666 
00667     ds = BLI_dynstr_new();
00668 
00669     if(GPU_bicubic_bump_support()){
00670         BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n"
00671                 "#version 130\n"
00672                 "#extension GL_ARB_texture_gather: enable\n"
00673                 "#extension GL_ARB_texture_query_lod: enable\n"
00674                 "#define BUMP_BICUBIC\n");
00675     }
00676     BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
00677 
00678 
00679     glsl_material_library = BLI_dynstr_get_cstring(ds);
00680 
00681     BLI_dynstr_free(ds);
00682 }
00683 
00684 
00685 /* GPU pass binding/unbinding */
00686 
00687 GPUShader *GPU_pass_shader(GPUPass *pass)
00688 {
00689     return pass->shader;
00690 }
00691 
00692 static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
00693 {
00694     GPUShader *shader = pass->shader;
00695     GPUNode *node;
00696     GPUInput *next, *input;
00697     ListBase *inputs = &pass->inputs;
00698     int extract, z;
00699 
00700     memset(inputs, 0, sizeof(*inputs));
00701 
00702     if(!shader)
00703         return;
00704 
00705     GPU_shader_bind(shader);
00706 
00707     for (node=nodes->first; node; node=node->next) {
00708         z = 0;
00709         for (input=node->inputs.first; input; input=next, z++) {
00710             next = input->next;
00711 
00712             /* attributes don't need to be bound, they already have
00713              * an id that the drawing functions will use */
00714             if(input->source == GPU_SOURCE_ATTRIB ||
00715                input->source == GPU_SOURCE_BUILTIN)
00716                 continue;
00717 
00718             if (input->ima || input->tex)
00719                 BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
00720             else
00721                 BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
00722 
00723             /* pass non-dynamic uniforms to opengl */
00724             extract = 0;
00725 
00726             if(input->ima || input->tex) {
00727                 if (input->bindtex)
00728                     extract = 1;
00729             }
00730             else if(input->dynamicvec)
00731                 extract = 1;
00732 
00733             if(extract)
00734                 input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
00735 
00736             /* extract nodes */
00737             if(extract) {
00738                 BLI_remlink(&node->inputs, input);
00739                 BLI_addtail(inputs, input);
00740             }
00741         }
00742     }
00743 
00744     GPU_shader_unbind(shader);
00745 }
00746 
00747 void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
00748 {
00749     GPUInput *input;
00750     GPUShader *shader = pass->shader;
00751     ListBase *inputs = &pass->inputs;
00752 
00753     if (!shader)
00754         return;
00755 
00756     GPU_shader_bind(shader);
00757 
00758     /* now bind the textures */
00759     for (input=inputs->first; input; input=input->next) {
00760         if (input->ima)
00761             input->tex = GPU_texture_from_blender(input->ima, input->iuser, time, mipmap);
00762 
00763         if(input->tex && input->bindtex) {
00764             GPU_texture_bind(input->tex, input->texid);
00765             GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
00766         }
00767     }
00768 }
00769 
00770 void GPU_pass_update_uniforms(GPUPass *pass)
00771 {
00772     GPUInput *input;
00773     GPUShader *shader = pass->shader;
00774     ListBase *inputs = &pass->inputs;
00775 
00776     if (!shader)
00777         return;
00778 
00779     /* pass dynamic inputs to opengl, others were removed */
00780     for (input=inputs->first; input; input=input->next)
00781         if(!(input->ima || input->tex))
00782             GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
00783                 input->dynamicvec);
00784 }
00785 
00786 void GPU_pass_unbind(GPUPass *pass)
00787 {
00788     GPUInput *input;
00789     GPUShader *shader = pass->shader;
00790     ListBase *inputs = &pass->inputs;
00791 
00792     if (!shader)
00793         return;
00794 
00795     for (input=inputs->first; input; input=input->next) {
00796         if(input->tex && input->bindtex)
00797             GPU_texture_unbind(input->tex);
00798 
00799         if (input->ima)
00800             input->tex = NULL;
00801     }
00802     
00803     GPU_shader_unbind(shader);
00804 }
00805 
00806 /* Node Link Functions */
00807 
00808 static GPUNodeLink *GPU_node_link_create(int type)
00809 {
00810     GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
00811     link->type = type;
00812     link->users++;
00813 
00814     return link;
00815 }
00816 
00817 static void GPU_node_link_free(GPUNodeLink *link)
00818 {
00819     link->users--;
00820 
00821     if (link->users < 0)
00822         fprintf(stderr, "GPU_node_link_free: negative refcount\n");
00823     
00824     if (link->users == 0) {
00825         if (link->output)
00826             link->output->link = NULL;
00827         MEM_freeN(link);
00828     }
00829 }
00830 
00831 /* Node Functions */
00832 
00833 static GPUNode *GPU_node_begin(const char *name)
00834 {
00835     GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
00836 
00837     node->name= name;
00838 
00839     return node;
00840 }
00841 
00842 static void GPU_node_end(GPUNode *UNUSED(node))
00843 {
00844     /* empty */
00845 }
00846 
00847 static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
00848 {
00849     GPUInput *input;
00850     GPUNode *outnode;
00851     const char *name;
00852 
00853     if(link->output) {
00854         outnode = link->output->node;
00855         name = outnode->name;
00856 
00857         if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
00858             input = MEM_dupallocN(outnode->inputs.first);
00859             input->type = type;
00860             if(input->link)
00861                 input->link->users++;
00862             BLI_addtail(&node->inputs, input);
00863             return;
00864         }
00865     }
00866     
00867     input = MEM_callocN(sizeof(GPUInput), "GPUInput");
00868     input->node = node;
00869 
00870     if(link->builtin) {
00871         /* builtin uniform */
00872         input->type = type;
00873         input->source = GPU_SOURCE_BUILTIN;
00874         input->builtin = link->builtin;
00875 
00876         MEM_freeN(link);
00877     }
00878     else if(link->output) {
00879         /* link to a node output */
00880         input->type = type;
00881         input->source = GPU_SOURCE_TEX_PIXEL;
00882         input->link = link;
00883         link->users++;
00884     }
00885     else if(link->dynamictex) {
00886         /* dynamic texture, GPUTexture is updated/deleted externally */
00887         input->type = type;
00888         input->source = GPU_SOURCE_TEX;
00889 
00890         input->tex = link->dynamictex;
00891         input->textarget = GL_TEXTURE_2D;
00892         input->textype = type;
00893         input->dynamictex = 1;
00894         input->dynamicdata = link->ptr2;
00895         MEM_freeN(link);
00896     }
00897     else if(link->texture) {
00898         /* small texture created on the fly, like for colorbands */
00899         input->type = GPU_VEC4;
00900         input->source = GPU_SOURCE_TEX;
00901         input->textype = type;
00902 
00903         //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
00904         input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
00905         input->textarget = GL_TEXTURE_2D;
00906 
00907         MEM_freeN(link->ptr1);
00908         MEM_freeN(link);
00909     }
00910     else if(link->image) {
00911         /* blender image */
00912         input->type = GPU_VEC4;
00913         input->source = GPU_SOURCE_TEX;
00914 
00915         input->ima = link->ptr1;
00916         input->iuser = link->ptr2;
00917         input->textarget = GL_TEXTURE_2D;
00918         input->textype = GPU_TEX2D;
00919         MEM_freeN(link);
00920     }
00921     else if(link->attribtype) {
00922         /* vertex attribute */
00923         input->type = type;
00924         input->source = GPU_SOURCE_ATTRIB;
00925 
00926         input->attribtype = link->attribtype;
00927         BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
00928         MEM_freeN(link);
00929     }
00930     else {
00931         /* uniform vector */
00932         input->type = type;
00933         input->source = GPU_SOURCE_VEC_UNIFORM;
00934 
00935         memcpy(input->vec, link->ptr1, type*sizeof(float));
00936         if(link->dynamic) {
00937             input->dynamicvec= link->ptr1;
00938             input->dynamictype= link->dynamictype;
00939             input->dynamicdata= link->ptr2;
00940         }
00941         MEM_freeN(link);
00942     }
00943 
00944     BLI_addtail(&node->inputs, input);
00945 }
00946 
00947 static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
00948 {
00949     GPUNodeLink *link;
00950 
00951     if(sock->link) {
00952         gpu_node_input_link(node, sock->link, sock->type);
00953     }
00954     else {
00955         link = GPU_node_link_create(0);
00956         link->ptr1 = sock->vec;
00957         gpu_node_input_link(node, link, sock->type);
00958     }
00959 }
00960 
00961 static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
00962 {
00963     GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
00964 
00965     output->type = type;
00966     output->node = node;
00967 
00968     if (link) {
00969         *link = output->link = GPU_node_link_create(type);
00970         output->link->output = output;
00971 
00972         /* note: the caller owns the reference to the linkfer, GPUOutput
00973            merely points to it, and if the node is destroyed it will
00974            set that pointer to NULL */
00975     }
00976 
00977     BLI_addtail(&node->outputs, output);
00978 }
00979 
00980 static void GPU_inputs_free(ListBase *inputs)
00981 {
00982     GPUInput *input;
00983 
00984     for(input=inputs->first; input; input=input->next) {
00985         if(input->link)
00986             GPU_node_link_free(input->link);
00987         else if(input->tex && !input->dynamictex)
00988             GPU_texture_free(input->tex);
00989     }
00990 
00991     BLI_freelistN(inputs);
00992 }
00993 
00994 static void GPU_node_free(GPUNode *node)
00995 {
00996     GPUOutput *output;
00997 
00998     GPU_inputs_free(&node->inputs);
00999 
01000     for (output=node->outputs.first; output; output=output->next)
01001         if (output->link) {
01002             output->link->output = NULL;
01003             GPU_node_link_free(output->link);
01004         }
01005 
01006     BLI_freelistN(&node->outputs);
01007     MEM_freeN(node);
01008 }
01009 
01010 static void GPU_nodes_free(ListBase *nodes)
01011 {
01012     GPUNode *node;
01013 
01014     while (nodes->first) {
01015         node = nodes->first;
01016         BLI_remlink(nodes, node);
01017         GPU_node_free(node);
01018     }
01019 }
01020 
01021 /* vertex attributes */
01022 
01023 static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
01024 {
01025     GPUNode *node;
01026     GPUInput *input;
01027     int a;
01028 
01029     /* convert attributes requested by node inputs to an array of layers,
01030      * checking for duplicates and assigning id's starting from zero. */
01031 
01032     memset(attribs, 0, sizeof(*attribs));
01033 
01034     for(node=nodes->first; node; node=node->next) {
01035         for(input=node->inputs.first; input; input=input->next) {
01036             if(input->source == GPU_SOURCE_ATTRIB) {
01037                 for(a=0; a<attribs->totlayer; a++) {
01038                     if(attribs->layer[a].type == input->attribtype &&
01039                         strcmp(attribs->layer[a].name, input->attribname) == 0)
01040                         break;
01041                 }
01042 
01043                 if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) {
01044                     input->attribid = attribs->totlayer++;
01045                     input->attribfirst = 1;
01046 
01047                     attribs->layer[a].type = input->attribtype;
01048                     attribs->layer[a].attribid = input->attribid;
01049                     BLI_strncpy(attribs->layer[a].name, input->attribname,
01050                         sizeof(attribs->layer[a].name));
01051                 }
01052                 else
01053                     input->attribid = attribs->layer[a].attribid;
01054             }
01055         }
01056     }
01057 }
01058 
01059 static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
01060 {
01061     GPUNode *node;
01062     GPUInput *input;
01063     
01064     *builtin= 0;
01065 
01066     for(node=nodes->first; node; node=node->next)
01067         for(input=node->inputs.first; input; input=input->next)
01068             if(input->source == GPU_SOURCE_BUILTIN)
01069                 *builtin |= input->builtin;
01070 }
01071 
01072 /* varargs linking  */
01073 
01074 GPUNodeLink *GPU_attribute(int type, const char *name)
01075 {
01076     GPUNodeLink *link = GPU_node_link_create(0);
01077 
01078     link->attribtype= type;
01079     link->attribname= name;
01080 
01081     return link;
01082 }
01083 
01084 GPUNodeLink *GPU_uniform(float *num)
01085 {
01086     GPUNodeLink *link = GPU_node_link_create(0);
01087 
01088     link->ptr1= num;
01089     link->ptr2= NULL;
01090 
01091     return link;
01092 }
01093 
01094 GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
01095 {
01096     GPUNodeLink *link = GPU_node_link_create(0);
01097 
01098     link->ptr1= num;
01099     link->ptr2= data;
01100     link->dynamic= 1;
01101     link->dynamictype = dynamictype;
01102 
01103 
01104     return link;
01105 }
01106 
01107 GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
01108 {
01109     GPUNodeLink *link = GPU_node_link_create(0);
01110 
01111     link->image= 1;
01112     link->ptr1= ima;
01113     link->ptr2= iuser;
01114 
01115     return link;
01116 }
01117 
01118 GPUNodeLink *GPU_texture(int size, float *pixels)
01119 {
01120     GPUNodeLink *link = GPU_node_link_create(0);
01121 
01122     link->texture = 1;
01123     link->texturesize = size;
01124     link->ptr1= pixels;
01125 
01126     return link;
01127 }
01128 
01129 GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
01130 {
01131     GPUNodeLink *link = GPU_node_link_create(0);
01132 
01133     link->dynamic = 1;
01134     link->dynamictex = tex;
01135     link->dynamictype = dynamictype;
01136     link->ptr2 = data;
01137 
01138     return link;
01139 }
01140 
01141 GPUNodeLink *GPU_socket(GPUNodeStack *sock)
01142 {
01143     GPUNodeLink *link = GPU_node_link_create(0);
01144 
01145     link->socket= sock;
01146 
01147     return link;
01148 }
01149 
01150 GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
01151 {
01152     GPUNodeLink *link = GPU_node_link_create(0);
01153 
01154     link->builtin= builtin;
01155 
01156     return link;
01157 }
01158 
01159 int GPU_link(GPUMaterial *mat, const char *name, ...)
01160 {
01161     GPUNode *node;
01162     GPUFunction *function;
01163     GPUNodeLink *link, **linkptr;
01164     va_list params;
01165     int i;
01166 
01167     function = GPU_lookup_function(name);
01168     if(!function) {
01169         fprintf(stderr, "GPU failed to find function %s\n", name);
01170         return 0;
01171     }
01172 
01173     node = GPU_node_begin(name);
01174 
01175     va_start(params, name);
01176     for(i=0; i<function->totparam; i++) {
01177         if(function->paramqual[i] != FUNCTION_QUAL_IN) {
01178             linkptr= va_arg(params, GPUNodeLink**);
01179             GPU_node_output(node, function->paramtype[i], "", linkptr);
01180         }
01181         else {
01182             link= va_arg(params, GPUNodeLink*);
01183             gpu_node_input_link(node, link, function->paramtype[i]);
01184         }
01185     }
01186     va_end(params);
01187 
01188     GPU_node_end(node);
01189 
01190     gpu_material_add_node(mat, node);
01191 
01192     return 1;
01193 }
01194 
01195 int GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
01196 {
01197     GPUNode *node;
01198     GPUFunction *function;
01199     GPUNodeLink *link, **linkptr;
01200     va_list params;
01201     int i, totin, totout;
01202 
01203     function = GPU_lookup_function(name);
01204     if(!function) {
01205         fprintf(stderr, "GPU failed to find function %s\n", name);
01206         return 0;
01207     }
01208 
01209     node = GPU_node_begin(name);
01210     totin = 0;
01211     totout = 0;
01212 
01213     if(in) {
01214         for(i = 0; in[i].type != GPU_NONE; i++) {
01215             gpu_node_input_socket(node, &in[i]);
01216             totin++;
01217         }
01218     }
01219     
01220     if(out) {
01221         for(i = 0; out[i].type != GPU_NONE; i++) {
01222             GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
01223             totout++;
01224         }
01225     }
01226 
01227     va_start(params, out);
01228     for(i=0; i<function->totparam; i++) {
01229         if(function->paramqual[i] != FUNCTION_QUAL_IN) {
01230             if(totout == 0) {
01231                 linkptr= va_arg(params, GPUNodeLink**);
01232                 GPU_node_output(node, function->paramtype[i], "", linkptr);
01233             }
01234             else
01235                 totout--;
01236         }
01237         else {
01238             if(totin == 0) {
01239                 link= va_arg(params, GPUNodeLink*);
01240                 if(link->socket)
01241                     gpu_node_input_socket(node, link->socket);
01242                 else
01243                     gpu_node_input_link(node, link, function->paramtype[i]);
01244             }
01245             else
01246                 totin--;
01247         }
01248     }
01249     va_end(params);
01250 
01251     GPU_node_end(node);
01252 
01253     gpu_material_add_node(mat, node);
01254     
01255     return 1;
01256 }
01257 
01258 int GPU_stack_link_mute(GPUMaterial *mat, const char *name, LinkInOutsMuteNode *mlnk)
01259 {
01260     GPUNode *node;
01261     GPUFunction *function;
01262     int i;
01263 
01264     function = GPU_lookup_function(name);
01265     if(!function) {
01266         fprintf(stderr, "GPU failed to find function %s\n", name);
01267         return 0;
01268     }
01269 
01270     for(i = 0; i < mlnk->num_outs; i++) {
01271         node = GPU_node_begin(name);
01272         gpu_node_input_socket(node, (GPUNodeStack*)mlnk->in);
01273         GPU_node_output(node, ((GPUNodeStack*)mlnk->outs+i)->type, ((GPUNodeStack*)mlnk->outs+i)->name,
01274                         &((GPUNodeStack*)mlnk->outs+i)->link);
01275         GPU_node_end(node);
01276 
01277         gpu_material_add_node(mat, node);
01278     }
01279 
01280     return 1;
01281 }
01282 
01283 int GPU_link_changed(GPUNodeLink *link)
01284 {
01285     GPUNode *node;
01286     GPUInput *input;
01287     const char *name;
01288 
01289     if(link->output) {
01290         node = link->output->node;
01291         name = node->name;
01292 
01293         if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
01294             input = node->inputs.first;
01295             return (input->link != NULL);
01296         }
01297 
01298         return 1;
01299     }
01300     else
01301         return 0;
01302 }
01303 
01304 /* Pass create/free */
01305 
01306 static void gpu_nodes_tag(GPUNodeLink *link)
01307 {
01308     GPUNode *node;
01309     GPUInput *input;
01310 
01311     if(!link->output)
01312         return;
01313 
01314     node = link->output->node;
01315     if(node->tag)
01316         return;
01317     
01318     node->tag= 1;
01319     for(input=node->inputs.first; input; input=input->next)
01320         if(input->link)
01321             gpu_nodes_tag(input->link);
01322 }
01323 
01324 static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
01325 {
01326     GPUNode *node, *next;
01327 
01328     for(node=nodes->first; node; node=node->next)
01329         node->tag= 0;
01330 
01331     gpu_nodes_tag(outlink);
01332 
01333     for(node=nodes->first; node; node=next) {
01334         next = node->next;
01335 
01336         if(!node->tag) {
01337             BLI_remlink(nodes, node);
01338             GPU_node_free(node);
01339         }
01340     }
01341 }
01342 
01343 GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
01344 {
01345     GPUShader *shader;
01346     GPUPass *pass;
01347     char *vertexcode, *fragmentcode;
01348 
01349     /*if(!FUNCTION_LIB) {
01350         GPU_nodes_free(nodes);
01351         return NULL;
01352     }*/
01353 
01354     /* prune unused nodes */
01355     gpu_nodes_prune(nodes, outlink);
01356 
01357     gpu_nodes_get_vertex_attributes(nodes, attribs);
01358     gpu_nodes_get_builtin_flag(nodes, builtins);
01359 
01360     /* generate code and compile with opengl */
01361     fragmentcode = code_generate_fragment(nodes, outlink->output, name);
01362     vertexcode = code_generate_vertex(nodes);
01363     shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library); /*FUNCTION_LIB);*/
01364 
01365     /* failed? */
01366     if (!shader) {
01367         memset(attribs, 0, sizeof(*attribs));
01368         memset(builtins, 0, sizeof(*builtins));
01369         GPU_nodes_free(nodes);
01370         return NULL;
01371     }
01372     
01373     /* create pass */
01374     pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
01375 
01376     pass->output = outlink->output;
01377     pass->shader = shader;
01378     pass->fragmentcode = fragmentcode;
01379     pass->vertexcode = vertexcode;
01380     pass->libcode = glsl_material_library;
01381 
01382     /* extract dynamic inputs and throw away nodes */
01383     GPU_nodes_extract_dynamic_inputs(pass, nodes);
01384     GPU_nodes_free(nodes);
01385 
01386     return pass;
01387 }
01388 
01389 void GPU_pass_free(GPUPass *pass)
01390 {
01391     GPU_shader_free(pass->shader);
01392     GPU_inputs_free(&pass->inputs);
01393     if (pass->fragmentcode)
01394         MEM_freeN(pass->fragmentcode);
01395     if (pass->vertexcode)
01396         MEM_freeN(pass->vertexcode);
01397     MEM_freeN(pass);
01398 }
01399