Cycles: Experiment with use of runtime tag instead of set for SVM generation

This gives about 2x speedup (3.2sec vs. 11.9sec with 32716 handled nodes) when
updating shader for the shader tree.

Reviewers: brecht, juicyfruit, dingto, lukasstockner97

Differential Revision: https://developer.blender.org/D1700
This commit is contained in:
Sergey Sharybin 2015-12-29 20:42:20 +05:00
parent 0ffc603553
commit 0b4abd08b3
2 changed files with 31 additions and 4 deletions

@ -415,24 +415,25 @@ void SVMCompiler::generate_svm_nodes(const ShaderNodeSet& nodes,
CompilerState *state) CompilerState *state)
{ {
ShaderNodeSet& done = state->nodes_done; ShaderNodeSet& done = state->nodes_done;
vector<bool>& done_flag = state->nodes_done_flag;
bool nodes_done; bool nodes_done;
do { do {
nodes_done = true; nodes_done = true;
foreach(ShaderNode *node, nodes) { foreach(ShaderNode *node, nodes) {
if(done.find(node) == done.end()) { if(!done_flag[node->id]) {
bool inputs_done = true; bool inputs_done = true;
foreach(ShaderInput *input, node->inputs) foreach(ShaderInput *input, node->inputs)
if(!node_skip_input(node, input)) if(!node_skip_input(node, input))
if(input->link && done.find(input->link->parent) == done.end()) if(input->link && !done_flag[input->link->parent->id])
inputs_done = false; inputs_done = false;
if(inputs_done) { if(inputs_done) {
generate_node(node, done); generate_node(node, done);
done.insert(node); done.insert(node);
done_flag[node->id] = true;
} }
else else
nodes_done = false; nodes_done = false;
@ -697,7 +698,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
} }
if(generate) { if(generate) {
CompilerState state; CompilerState state(graph);
generate_multi_closure(clin->link->parent, generate_multi_closure(clin->link->parent,
clin->link->parent, clin->link->parent,
&state); &state);
@ -844,5 +845,16 @@ string SVMCompiler::Summary::full_report() const
return report; return report;
} }
/* Global state of the compiler. */
SVMCompiler::CompilerState::CompilerState(ShaderGraph *graph)
{
int max_id = 0;
foreach(ShaderNode *node, graph->nodes) {
max_id = max(node->id, max_id);
}
nodes_done_flag.resize(max_id + 1, false);
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

@ -154,11 +154,26 @@ protected:
/* Global state of the compiler accessible from the compilation routines. */ /* Global state of the compiler accessible from the compilation routines. */
struct CompilerState { struct CompilerState {
CompilerState(ShaderGraph *graph);
/* ** Global state, used by various compilation steps. ** */
/* Set of nodes which were already compiled. */ /* Set of nodes which were already compiled. */
ShaderNodeSet nodes_done; ShaderNodeSet nodes_done;
/* Set of closures which were already compiled. */ /* Set of closures which were already compiled. */
ShaderNodeSet closure_done; ShaderNodeSet closure_done;
/* ** SVM nodes generation state ** */
/* Flag whether the node with corresponding ID was already compiled or
* not. Array element with index i corresponds to a node with such if.
*
* TODO(sergey): This is actually a copy of nodes_done just in another
* notation. We can de-duplicate this storage actually after switching
* all areas to use this flags array.
*/
vector<bool> nodes_done_flag;
}; };
void stack_backup(StackBackup& backup, ShaderNodeSet& done); void stack_backup(StackBackup& backup, ShaderNodeSet& done);