Blender V2.61 - r43446
|
00001 /* 00002 * Copyright 2011, Blender Foundation. 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 00019 #include "device.h" 00020 #include "graph.h" 00021 #include "light.h" 00022 #include "mesh.h" 00023 #include "scene.h" 00024 #include "shader.h" 00025 #include "svm.h" 00026 00027 #include "util_debug.h" 00028 #include "util_foreach.h" 00029 #include "util_progress.h" 00030 00031 CCL_NAMESPACE_BEGIN 00032 00033 /* Shader Manager */ 00034 00035 SVMShaderManager::SVMShaderManager() 00036 { 00037 } 00038 00039 SVMShaderManager::~SVMShaderManager() 00040 { 00041 } 00042 00043 void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) 00044 { 00045 if(!need_update) 00046 return; 00047 00048 /* test if we need to update */ 00049 device_free(device, dscene); 00050 00051 /* svm_nodes */ 00052 vector<int4> svm_nodes; 00053 size_t i; 00054 00055 for(i = 0; i < scene->shaders.size(); i++) { 00056 svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); 00057 svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); 00058 } 00059 00060 bool sunsky_done = false; 00061 bool use_multi_closure = device->support_full_kernel(); 00062 00063 for(i = 0; i < scene->shaders.size(); i++) { 00064 Shader *shader = scene->shaders[i]; 00065 00066 if(progress.get_cancel()) return; 00067 00068 assert(shader->graph); 00069 00070 if(shader->sample_as_light && shader->has_surface_emission) 00071 scene->light_manager->need_update = true; 00072 00073 SVMCompiler compiler(scene->shader_manager, scene->image_manager, 00074 use_multi_closure); 00075 compiler.sunsky = (sunsky_done)? NULL: &dscene->data.sunsky; 00076 compiler.background = ((int)i == scene->default_background); 00077 compiler.compile(shader, svm_nodes, i); 00078 if(!compiler.sunsky) 00079 sunsky_done = true; 00080 } 00081 00082 dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size()); 00083 device->tex_alloc("__svm_nodes", dscene->svm_nodes); 00084 00085 for(i = 0; i < scene->shaders.size(); i++) { 00086 Shader *shader = scene->shaders[i]; 00087 shader->need_update = false; 00088 } 00089 00090 device_update_common(device, dscene, scene, progress); 00091 00092 need_update = false; 00093 } 00094 00095 void SVMShaderManager::device_free(Device *device, DeviceScene *dscene) 00096 { 00097 device_free_common(device, dscene); 00098 00099 device->tex_free(dscene->svm_nodes); 00100 dscene->svm_nodes.clear(); 00101 } 00102 00103 /* Graph Compiler */ 00104 00105 SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_, bool use_multi_closure_) 00106 { 00107 shader_manager = shader_manager_; 00108 image_manager = image_manager_; 00109 sunsky = NULL; 00110 max_stack_use = 0; 00111 current_type = SHADER_TYPE_SURFACE; 00112 current_shader = NULL; 00113 background = false; 00114 mix_weight_offset = SVM_STACK_INVALID; 00115 use_multi_closure = use_multi_closure_; 00116 } 00117 00118 int SVMCompiler::stack_size(ShaderSocketType type) 00119 { 00120 if(type == SHADER_SOCKET_FLOAT) 00121 return 1; 00122 else if(type == SHADER_SOCKET_COLOR) 00123 return 3; 00124 else if(type == SHADER_SOCKET_VECTOR) 00125 return 3; 00126 else if(type == SHADER_SOCKET_NORMAL) 00127 return 3; 00128 else if(type == SHADER_SOCKET_POINT) 00129 return 3; 00130 else if(type == SHADER_SOCKET_CLOSURE) 00131 return 0; 00132 00133 assert(0); 00134 return 0; 00135 } 00136 00137 int SVMCompiler::stack_find_offset(ShaderSocketType type) 00138 { 00139 int size = stack_size(type); 00140 int offset = -1; 00141 00142 /* find free space in stack & mark as used */ 00143 for(int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) { 00144 if(active_stack.users[i]) num_unused = 0; 00145 else num_unused++; 00146 00147 if(num_unused == size) { 00148 offset = i+1 - size; 00149 max_stack_use = max(i+1, max_stack_use); 00150 00151 while(i >= offset) 00152 active_stack.users[i--] = 1; 00153 00154 return offset; 00155 } 00156 } 00157 00158 fprintf(stderr, "Out of SVM stack space.\n"); 00159 assert(0); 00160 00161 return offset; 00162 } 00163 00164 void SVMCompiler::stack_backup(StackBackup& backup, set<ShaderNode*>& done) 00165 { 00166 backup.done = done; 00167 backup.stack = active_stack; 00168 00169 foreach(ShaderNode *node, current_graph->nodes) { 00170 foreach(ShaderInput *input, node->inputs) 00171 backup.offsets.push_back(input->stack_offset); 00172 foreach(ShaderOutput *output, node->outputs) 00173 backup.offsets.push_back(output->stack_offset); 00174 } 00175 } 00176 00177 void SVMCompiler::stack_restore(StackBackup& backup, set<ShaderNode*>& done) 00178 { 00179 int i = 0; 00180 00181 done = backup.done; 00182 active_stack = backup.stack; 00183 00184 foreach(ShaderNode *node, current_graph->nodes) { 00185 foreach(ShaderInput *input, node->inputs) 00186 input->stack_offset = backup.offsets[i++]; 00187 foreach(ShaderOutput *output, node->outputs) 00188 output->stack_offset = backup.offsets[i++]; 00189 } 00190 } 00191 00192 void SVMCompiler::stack_assign(ShaderInput *input) 00193 { 00194 /* stack offset assign? */ 00195 if(input->stack_offset == SVM_STACK_INVALID) { 00196 if(input->link) { 00197 /* linked to output -> use output offset */ 00198 input->stack_offset = input->link->stack_offset; 00199 } 00200 else { 00201 /* not linked to output -> add nodes to load default value */ 00202 input->stack_offset = stack_find_offset(input->type); 00203 00204 if(input->type == SHADER_SOCKET_FLOAT) { 00205 add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset); 00206 } 00207 else if(input->type == SHADER_SOCKET_VECTOR || 00208 input->type == SHADER_SOCKET_NORMAL || 00209 input->type == SHADER_SOCKET_POINT || 00210 input->type == SHADER_SOCKET_COLOR) { 00211 00212 add_node(NODE_VALUE_V, input->stack_offset); 00213 add_node(NODE_VALUE_V, input->value); 00214 } 00215 else /* should not get called for closure */ 00216 assert(0); 00217 } 00218 } 00219 } 00220 00221 void SVMCompiler::stack_assign(ShaderOutput *output) 00222 { 00223 /* if no stack offset assigned yet, find one */ 00224 if(output->stack_offset == SVM_STACK_INVALID) 00225 output->stack_offset = stack_find_offset(output->type); 00226 } 00227 00228 void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output) 00229 { 00230 if(output->stack_offset == SVM_STACK_INVALID) { 00231 assert(input->link); 00232 assert(stack_size(output->type) == stack_size(input->link->type)); 00233 00234 output->stack_offset = input->link->stack_offset; 00235 00236 int size = stack_size(output->type); 00237 00238 for(int i = 0; i < size; i++) 00239 active_stack.users[output->stack_offset + i]++; 00240 } 00241 } 00242 00243 void SVMCompiler::stack_clear_users(ShaderNode *node, set<ShaderNode*>& done) 00244 { 00245 /* optimization we should add: 00246 find and lower user counts for outputs for which all inputs are done. 00247 this is done before the node is compiled, under the assumption that the 00248 node will first load all inputs from the stack and then writes its 00249 outputs. this used to work, but was disabled because it gave trouble 00250 with inputs getting stack positions assigned */ 00251 00252 foreach(ShaderInput *input, node->inputs) { 00253 ShaderOutput *output = input->link; 00254 00255 if(output && output->stack_offset != SVM_STACK_INVALID) { 00256 bool all_done = true; 00257 00258 /* optimization we should add: verify if in->parent is actually used */ 00259 foreach(ShaderInput *in, output->links) 00260 if(in->parent != node && done.find(in->parent) == done.end()) 00261 all_done = false; 00262 00263 if(all_done) { 00264 int size = stack_size(output->type); 00265 00266 for(int i = 0; i < size; i++) 00267 active_stack.users[output->stack_offset + i]--; 00268 00269 output->stack_offset = SVM_STACK_INVALID; 00270 00271 foreach(ShaderInput *in, output->links) 00272 in->stack_offset = SVM_STACK_INVALID; 00273 } 00274 } 00275 } 00276 } 00277 00278 void SVMCompiler::stack_clear_temporary(ShaderNode *node) 00279 { 00280 foreach(ShaderInput *input, node->inputs) { 00281 if(!input->link && input->stack_offset != SVM_STACK_INVALID) { 00282 int size = stack_size(input->type); 00283 00284 for(int i = 0; i < size; i++) 00285 active_stack.users[input->stack_offset + i]--; 00286 00287 input->stack_offset = SVM_STACK_INVALID; 00288 } 00289 } 00290 } 00291 00292 uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w) 00293 { 00294 assert(x <= 255); 00295 assert(y <= 255); 00296 assert(z <= 255); 00297 assert(w <= 255); 00298 00299 return (x) | (y << 8) | (z << 16) | (w << 24); 00300 } 00301 00302 void SVMCompiler::add_node(int a, int b, int c, int d) 00303 { 00304 svm_nodes.push_back(make_int4(a, b, c, d)); 00305 } 00306 00307 void SVMCompiler::add_node(NodeType type, int a, int b, int c) 00308 { 00309 svm_nodes.push_back(make_int4(type, a, b, c)); 00310 } 00311 00312 void SVMCompiler::add_node(NodeType type, const float3& f) 00313 { 00314 svm_nodes.push_back(make_int4(type, 00315 __float_as_int(f.x), 00316 __float_as_int(f.y), 00317 __float_as_int(f.z))); 00318 } 00319 00320 void SVMCompiler::add_node(const float4& f) 00321 { 00322 svm_nodes.push_back(make_int4( 00323 __float_as_int(f.x), 00324 __float_as_int(f.y), 00325 __float_as_int(f.z), 00326 __float_as_int(f.w))); 00327 } 00328 00329 uint SVMCompiler::attribute(ustring name) 00330 { 00331 return shader_manager->get_attribute_id(name); 00332 } 00333 00334 uint SVMCompiler::attribute(Attribute::Standard std) 00335 { 00336 return shader_manager->get_attribute_id(std); 00337 } 00338 00339 bool SVMCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) 00340 { 00341 /* nasty exception .. */ 00342 if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) 00343 return true; 00344 00345 return false; 00346 } 00347 00348 void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input) 00349 { 00350 ShaderNode *node = (input->link)? input->link->parent: NULL; 00351 00352 if(node && done.find(node) == done.end()) { 00353 foreach(ShaderInput *in, node->inputs) 00354 if(!node_skip_input(node, in)) 00355 find_dependencies(dependencies, done, in); 00356 00357 dependencies.insert(node); 00358 } 00359 } 00360 00361 void SVMCompiler::generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done) 00362 { 00363 bool nodes_done; 00364 00365 do { 00366 nodes_done = true; 00367 00368 foreach(ShaderNode *node, nodes) { 00369 if(done.find(node) == done.end()) { 00370 bool inputs_done = true; 00371 00372 foreach(ShaderInput *input, node->inputs) 00373 if(!node_skip_input(node, input)) 00374 if(input->link && done.find(input->link->parent) == done.end()) 00375 inputs_done = false; 00376 00377 if(inputs_done) { 00378 node->compile(*this); 00379 stack_clear_users(node, done); 00380 stack_clear_temporary(node); 00381 done.insert(node); 00382 } 00383 else 00384 nodes_done = false; 00385 } 00386 } 00387 } while(!nodes_done); 00388 } 00389 00390 void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done) 00391 { 00392 if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { 00393 ShaderInput *fin = node->input("Fac"); 00394 ShaderInput *cl1in = node->input("Closure1"); 00395 ShaderInput *cl2in = node->input("Closure2"); 00396 00397 /* execute dependencies for mix weight */ 00398 if(fin) { 00399 set<ShaderNode*> dependencies; 00400 find_dependencies(dependencies, done, fin); 00401 generate_svm_nodes(dependencies, done); 00402 00403 /* add mix node */ 00404 stack_assign(fin); 00405 } 00406 00407 int mix_offset = svm_nodes.size(); 00408 00409 if(fin) 00410 add_node(NODE_MIX_CLOSURE, fin->stack_offset, 0, 0); 00411 else 00412 add_node(NODE_ADD_CLOSURE, 0, 0, 0); 00413 00414 /* generate code for closure 1 00415 note we backup all compiler state and restore it afterwards, so one 00416 closure choice doesn't influence the other*/ 00417 if(cl1in->link) { 00418 StackBackup backup; 00419 stack_backup(backup, done); 00420 00421 generate_closure(cl1in->link->parent, done); 00422 add_node(NODE_END, 0, 0, 0); 00423 00424 stack_restore(backup, done); 00425 } 00426 else 00427 add_node(NODE_END, 0, 0, 0); 00428 00429 /* generate code for closure 2 */ 00430 int cl2_offset = svm_nodes.size(); 00431 00432 if(cl2in->link) { 00433 StackBackup backup; 00434 stack_backup(backup, done); 00435 00436 generate_closure(cl2in->link->parent, done); 00437 add_node(NODE_END, 0, 0, 0); 00438 00439 stack_restore(backup, done); 00440 } 00441 else 00442 add_node(NODE_END, 0, 0, 0); 00443 00444 /* set jump for mix node, -1 because offset is already 00445 incremented when this jump is added to it */ 00446 svm_nodes[mix_offset].z = cl2_offset - mix_offset - 1; 00447 00448 done.insert(node); 00449 stack_clear_users(node, done); 00450 stack_clear_temporary(node); 00451 } 00452 else { 00453 /* execute dependencies for closure */ 00454 foreach(ShaderInput *in, node->inputs) { 00455 if(!node_skip_input(node, in) && in->link) { 00456 set<ShaderNode*> dependencies; 00457 find_dependencies(dependencies, done, in); 00458 generate_svm_nodes(dependencies, done); 00459 } 00460 } 00461 00462 /* compile closure itself */ 00463 node->compile(*this); 00464 stack_clear_users(node, done); 00465 stack_clear_temporary(node); 00466 00467 if(node->name == ustring("emission")) 00468 current_shader->has_surface_emission = true; 00469 if(node->name == ustring("transparent")) 00470 current_shader->has_surface_transparent = true; 00471 00472 /* end node is added outside of this */ 00473 } 00474 } 00475 00476 void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset) 00477 { 00478 /* todo: the weaks point here is that unlike the single closure sampling 00479 we will evaluate all nodes even if they are used as input for closures 00480 that are unused. it's not clear what would be the best way to skip such 00481 nodes at runtime, especially if they are tangled up */ 00482 00483 if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { 00484 ShaderInput *fin = node->input("Fac"); 00485 ShaderInput *cl1in = node->input("Closure1"); 00486 ShaderInput *cl2in = node->input("Closure2"); 00487 00488 uint out1_offset = SVM_STACK_INVALID; 00489 uint out2_offset = SVM_STACK_INVALID; 00490 00491 if(fin) { 00492 /* mix closure */ 00493 set<ShaderNode*> dependencies; 00494 find_dependencies(dependencies, done, fin); 00495 generate_svm_nodes(dependencies, done); 00496 00497 stack_assign(fin); 00498 00499 if(cl1in->link) 00500 out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT); 00501 if(cl2in->link) 00502 out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT); 00503 00504 add_node(NODE_MIX_CLOSURE, 00505 encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset)); 00506 } 00507 else { 00508 /* add closure */ 00509 out1_offset = in_offset; 00510 out2_offset = in_offset; 00511 } 00512 00513 if(cl1in->link) { 00514 generate_multi_closure(cl1in->link->parent, done, out1_offset); 00515 00516 if(fin) 00517 active_stack.users[out1_offset]--; 00518 } 00519 00520 if(cl2in->link) { 00521 generate_multi_closure(cl2in->link->parent, done, out2_offset); 00522 00523 if(fin) 00524 active_stack.users[out2_offset]--; 00525 } 00526 } 00527 else { 00528 /* execute dependencies for closure */ 00529 foreach(ShaderInput *in, node->inputs) { 00530 if(!node_skip_input(node, in) && in->link) { 00531 set<ShaderNode*> dependencies; 00532 find_dependencies(dependencies, done, in); 00533 generate_svm_nodes(dependencies, done); 00534 } 00535 } 00536 00537 mix_weight_offset = in_offset; 00538 00539 /* compile closure itself */ 00540 node->compile(*this); 00541 stack_clear_users(node, done); 00542 stack_clear_temporary(node); 00543 00544 mix_weight_offset = SVM_STACK_INVALID; 00545 00546 if(node->name == ustring("emission")) 00547 current_shader->has_surface_emission = true; 00548 if(node->name == ustring("transparent")) 00549 current_shader->has_surface_transparent = true; 00550 00551 /* end node is added outside of this */ 00552 } 00553 } 00554 00555 00556 void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type) 00557 { 00558 /* Converting a shader graph into svm_nodes that can be executed 00559 * sequentially on the virtual machine is fairly simple. We can keep 00560 * looping over nodes and each time all the inputs of a node are 00561 * ready, we add svm_nodes for it that read the inputs from the 00562 * stack and write outputs back to the stack. 00563 * 00564 * With the SVM, we always sample only a single closure. We can think 00565 * of all closures nodes as a binary tree with mix closures as inner 00566 * nodes and other closures as leafs. The SVM will traverse that tree, 00567 * each time deciding to go left or right depending on the mix weights, 00568 * until a closure is found. 00569 * 00570 * We only execute nodes that are needed for the mix weights and chosen 00571 * closure. 00572 */ 00573 00574 current_type = type; 00575 current_graph = graph; 00576 00577 /* get input in output node */ 00578 ShaderNode *node = graph->output(); 00579 ShaderInput *clin = NULL; 00580 00581 if(type == SHADER_TYPE_SURFACE) 00582 clin = node->input("Surface"); 00583 else if(type == SHADER_TYPE_VOLUME) 00584 clin = node->input("Volume"); 00585 else if(type == SHADER_TYPE_DISPLACEMENT) 00586 clin = node->input("Displacement"); 00587 else 00588 assert(0); 00589 00590 /* clear all compiler state */ 00591 memset(&active_stack, 0, sizeof(active_stack)); 00592 svm_nodes.clear(); 00593 00594 foreach(ShaderNode *node, graph->nodes) { 00595 foreach(ShaderInput *input, node->inputs) 00596 input->stack_offset = SVM_STACK_INVALID; 00597 foreach(ShaderOutput *output, node->outputs) 00598 output->stack_offset = SVM_STACK_INVALID; 00599 } 00600 00601 if(clin->link) { 00602 bool generate = false; 00603 if(type == SHADER_TYPE_SURFACE) { 00604 /* generate surface shader */ 00605 generate = true; 00606 shader->has_surface = true; 00607 } 00608 else if(type == SHADER_TYPE_VOLUME) { 00609 /* generate volume shader */ 00610 generate = true; 00611 shader->has_volume = true; 00612 } 00613 else if(type == SHADER_TYPE_DISPLACEMENT) { 00614 /* generate displacement shader */ 00615 generate = true; 00616 shader->has_displacement = true; 00617 } 00618 00619 if(generate) { 00620 set<ShaderNode*> done; 00621 00622 if(use_multi_closure) 00623 generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); 00624 else 00625 generate_closure(clin->link->parent, done); 00626 } 00627 } 00628 00629 /* compile output node */ 00630 node->compile(*this); 00631 00632 add_node(NODE_END, 0, 0, 0); 00633 } 00634 00635 void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int index) 00636 { 00637 /* copy graph for shader with bump mapping */ 00638 ShaderNode *node = shader->graph->output(); 00639 00640 if(node->input("Surface")->link && node->input("Displacement")->link) 00641 if(!shader->graph_bump) 00642 shader->graph_bump = shader->graph->copy(); 00643 00644 /* finalize */ 00645 shader->graph->finalize(false, false); 00646 if(shader->graph_bump) 00647 shader->graph_bump->finalize(true, false); 00648 00649 current_shader = shader; 00650 00651 shader->has_surface = false; 00652 shader->has_surface_emission = false; 00653 shader->has_surface_transparent = false; 00654 shader->has_volume = false; 00655 shader->has_displacement = false; 00656 00657 /* generate surface shader */ 00658 compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); 00659 global_svm_nodes[index*2 + 0].y = global_svm_nodes.size(); 00660 global_svm_nodes[index*2 + 1].y = global_svm_nodes.size(); 00661 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); 00662 00663 if(shader->graph_bump) { 00664 compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); 00665 global_svm_nodes[index*2 + 1].y = global_svm_nodes.size(); 00666 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); 00667 } 00668 00669 /* generate volume shader */ 00670 compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); 00671 global_svm_nodes[index*2 + 0].z = global_svm_nodes.size(); 00672 global_svm_nodes[index*2 + 1].z = global_svm_nodes.size(); 00673 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); 00674 00675 /* generate displacement shader */ 00676 compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); 00677 global_svm_nodes[index*2 + 0].w = global_svm_nodes.size(); 00678 global_svm_nodes[index*2 + 1].w = global_svm_nodes.size(); 00679 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); 00680 } 00681 00682 CCL_NAMESPACE_END 00683