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