Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/svm.cpp')
-rw-r--r--intern/cycles/render/svm.cpp268
1 files changed, 194 insertions, 74 deletions
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index d0bd34915df..f3d39c1bd72 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -76,9 +76,14 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
if(shader->use_mis && shader->has_surface_emission)
scene->light_manager->need_update = true;
+ SVMCompiler::Summary summary;
SVMCompiler compiler(scene->shader_manager, scene->image_manager);
compiler.background = ((int)i == scene->default_background);
- compiler.compile(shader, svm_nodes, i);
+ compiler.compile(scene, shader, svm_nodes, i, &summary);
+
+ VLOG(1) << "Compilation summary:\n"
+ << "Shader name: " << shader->name << "\n"
+ << summary.full_report();
}
dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size());
@@ -121,7 +126,7 @@ int SVMCompiler::stack_size(ShaderSocketType type)
{
int size = 0;
- switch (type) {
+ switch(type) {
case SHADER_SOCKET_FLOAT:
case SHADER_SOCKET_INT:
size = 1;
@@ -180,7 +185,7 @@ void SVMCompiler::stack_clear_offset(ShaderSocketType type, int offset)
active_stack.users[offset + i]--;
}
-void SVMCompiler::stack_backup(StackBackup& backup, set<ShaderNode*>& done)
+void SVMCompiler::stack_backup(StackBackup& backup, ShaderNodeSet& done)
{
backup.done = done;
backup.stack = active_stack;
@@ -193,7 +198,7 @@ void SVMCompiler::stack_backup(StackBackup& backup, set<ShaderNode*>& done)
}
}
-void SVMCompiler::stack_restore(StackBackup& backup, set<ShaderNode*>& done)
+void SVMCompiler::stack_restore(StackBackup& backup, ShaderNodeSet& done)
{
int i = 0;
@@ -263,7 +268,7 @@ void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
}
}
-void SVMCompiler::stack_clear_users(ShaderNode *node, set<ShaderNode*>& done)
+void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet& done)
{
/* optimization we should add:
* find and lower user counts for outputs for which all inputs are done.
@@ -366,14 +371,18 @@ bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
return false;
}
-void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies,
- const set<ShaderNode*>& done,
+void SVMCompiler::find_dependencies(ShaderNodeSet& dependencies,
+ const ShaderNodeSet& done,
ShaderInput *input,
ShaderNode *skip_node)
{
ShaderNode *node = (input->link)? input->link->parent: NULL;
- if(node && done.find(node) == done.end() && node != skip_node) {
+ if(node != NULL &&
+ done.find(node) == done.end() &&
+ node != skip_node &&
+ dependencies.find(node) == dependencies.end())
+ {
foreach(ShaderInput *in, node->inputs)
if(!node_skip_input(node, in))
find_dependencies(dependencies, done, in, skip_node);
@@ -382,41 +391,53 @@ void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies,
}
}
-void SVMCompiler::generate_node(ShaderNode *node, set<ShaderNode*>& done)
+void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet& done)
{
node->compile(*this);
stack_clear_users(node, done);
stack_clear_temporary(node);
- if(current_type == SHADER_TYPE_VOLUME) {
+ if(current_type == SHADER_TYPE_SURFACE) {
if(node->has_spatial_varying())
- current_shader->has_heterogeneous_volume = true;
+ current_shader->has_surface_spatial_varying = true;
+ }
+ else if(current_type == SHADER_TYPE_VOLUME) {
+ if(node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
}
if(node->has_object_dependency()) {
current_shader->has_object_dependency = true;
}
+
+ if(node->has_integrator_dependency()) {
+ current_shader->has_integrator_dependency = true;
+ }
}
-void SVMCompiler::generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done)
+void SVMCompiler::generate_svm_nodes(const ShaderNodeSet& nodes,
+ CompilerState *state)
{
- bool nodes_done;
+ ShaderNodeSet& done = state->nodes_done;
+ vector<bool>& done_flag = state->nodes_done_flag;
+ bool nodes_done;
do {
nodes_done = true;
foreach(ShaderNode *node, nodes) {
- if(done.find(node) == done.end()) {
+ if(!done_flag[node->id]) {
bool inputs_done = true;
foreach(ShaderInput *input, node->inputs)
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;
if(inputs_done) {
generate_node(node, done);
done.insert(node);
+ done_flag[node->id] = true;
}
else
nodes_done = false;
@@ -425,14 +446,15 @@ void SVMCompiler::generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNo
} while(!nodes_done);
}
-void SVMCompiler::generate_closure_node(ShaderNode *node, set<ShaderNode*>& done)
+void SVMCompiler::generate_closure_node(ShaderNode *node,
+ CompilerState *state)
{
/* execute dependencies for closure */
foreach(ShaderInput *in, node->inputs) {
if(!node_skip_input(node, in) && in->link) {
- set<ShaderNode*> dependencies;
- find_dependencies(dependencies, done, in);
- generate_svm_nodes(dependencies, done);
+ ShaderNodeSet dependencies;
+ find_dependencies(dependencies, state->nodes_done, in);
+ generate_svm_nodes(dependencies, state);
}
}
@@ -448,7 +470,7 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, set<ShaderNode*>& done
mix_weight_offset = SVM_STACK_INVALID;
/* compile closure itself */
- generate_node(node, done);
+ generate_node(node, state->nodes_done);
mix_weight_offset = SVM_STACK_INVALID;
@@ -467,32 +489,32 @@ void SVMCompiler::generate_closure_node(ShaderNode *node, set<ShaderNode*>& done
void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
ShaderNode *node,
- set<ShaderNode*>& done,
- set<ShaderNode*>& closure_done,
- const set<ShaderNode*>& shared)
+ CompilerState *state,
+ const ShaderNodeSet& shared)
{
if(shared.find(node) != shared.end()) {
- generate_multi_closure(root_node, node, done, closure_done);
+ generate_multi_closure(root_node, node, state);
}
else {
foreach(ShaderInput *in, node->inputs) {
if(in->type == SHADER_SOCKET_CLOSURE && in->link)
- generated_shared_closure_nodes(root_node, in->link->parent,
- done, closure_done, shared);
+ generated_shared_closure_nodes(root_node,
+ in->link->parent,
+ state,
+ shared);
}
}
}
void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
ShaderNode *node,
- set<ShaderNode*>& done,
- set<ShaderNode*>& closure_done)
+ CompilerState *state)
{
/* only generate once */
- if(closure_done.find(node) != closure_done.end())
+ if(state->closure_done.find(node) != state->closure_done.end())
return;
- closure_done.insert(node);
+ state->closure_done.insert(node);
if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
/* weighting is already taken care of in ShaderGraph::transform_multi_closure */
@@ -506,23 +528,25 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
if(facin && facin->link) {
/* mix closure: generate instructions to compute mix weight */
- set<ShaderNode*> dependencies;
- find_dependencies(dependencies, done, facin);
- generate_svm_nodes(dependencies, done);
+ ShaderNodeSet dependencies;
+ find_dependencies(dependencies, state->nodes_done, facin);
+ generate_svm_nodes(dependencies, state);
stack_assign(facin);
/* execute shared dependencies. this is needed to allow skipping
* of zero weight closures and their dependencies later, so we
* ensure that they only skip dependencies that are unique to them */
- set<ShaderNode*> cl1deps, cl2deps, shareddeps;
+ ShaderNodeSet cl1deps, cl2deps, shareddeps;
- find_dependencies(cl1deps, done, cl1in);
- find_dependencies(cl2deps, done, cl2in);
+ find_dependencies(cl1deps, state->nodes_done, cl1in);
+ find_dependencies(cl2deps, state->nodes_done, cl2in);
+ ShaderNodeIDComparator node_id_comp;
set_intersection(cl1deps.begin(), cl1deps.end(),
cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()));
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
/* it's possible some nodes are not shared between this mix node
* inputs, but still needed to be always executed, this mainly
@@ -530,28 +554,34 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
* node or so */
if(root_node != node) {
foreach(ShaderInput *in, root_node->inputs) {
- set<ShaderNode*> rootdeps;
- find_dependencies(rootdeps, done, in, node);
+ ShaderNodeSet rootdeps;
+ find_dependencies(rootdeps, state->nodes_done, in, node);
set_intersection(rootdeps.begin(), rootdeps.end(),
cl1deps.begin(), cl1deps.end(),
- std::inserter(shareddeps, shareddeps.begin()));
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
set_intersection(rootdeps.begin(), rootdeps.end(),
cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()));
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
}
}
if(!shareddeps.empty()) {
if(cl1in->link) {
- generated_shared_closure_nodes(root_node, cl1in->link->parent,
- done, closure_done, shareddeps);
+ generated_shared_closure_nodes(root_node,
+ cl1in->link->parent,
+ state,
+ shareddeps);
}
if(cl2in->link) {
- generated_shared_closure_nodes(root_node, cl2in->link->parent,
- done, closure_done, shareddeps);
+ generated_shared_closure_nodes(root_node,
+ cl2in->link->parent,
+ state,
+ shareddeps);
}
- generate_svm_nodes(shareddeps, done);
+ generate_svm_nodes(shareddeps, state);
}
/* generate instructions for input closure 1 */
@@ -560,7 +590,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 0, facin->stack_offset, 0));
int node_jump_skip_index = svm_nodes.size() - 1;
- generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl1in->link->parent, state);
/* fill in jump instruction location to be after closure */
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
@@ -572,7 +602,7 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, facin->stack_offset, 0));
int node_jump_skip_index = svm_nodes.size() - 1;
- generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl2in->link->parent, state);
/* fill in jump instruction location to be after closure */
svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
@@ -586,16 +616,17 @@ void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
* to skip closures here because was already optimized due to
* fixed weight or add closure that always needs both */
if(cl1in->link)
- generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl1in->link->parent, state);
if(cl2in->link)
- generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
+ generate_multi_closure(root_node, cl2in->link->parent, state);
}
}
else {
- generate_closure_node(node, done);
+ generate_closure_node(node, state);
}
- done.insert(node);
+ state->nodes_done.insert(node);
+ state->nodes_done_flag[node->id] = true;
}
@@ -624,7 +655,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
ShaderNode *node = graph->output();
ShaderInput *clin = NULL;
- switch (type) {
+ switch(type) {
case SHADER_TYPE_SURFACE:
clin = node->input("Surface");
break;
@@ -654,7 +685,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
if(clin->link) {
bool generate = false;
- switch (type) {
+ switch(type) {
case SHADER_TYPE_SURFACE: /* generate surface shader */
generate = true;
shader->has_surface = true;
@@ -672,9 +703,10 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
}
if(generate) {
- set<ShaderNode*> done, closure_done;
- generate_multi_closure(clin->link->parent, clin->link->parent,
- done, closure_done);
+ CompilerState state(graph);
+ generate_multi_closure(clin->link->parent,
+ clin->link->parent,
+ &state);
}
}
@@ -691,19 +723,38 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
add_node(NODE_END, 0, 0, 0);
}
-void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int index)
+void SVMCompiler::compile(Scene *scene,
+ Shader *shader,
+ vector<int4>& global_svm_nodes,
+ int index,
+ Summary *summary)
{
/* copy graph for shader with bump mapping */
ShaderNode *node = shader->graph->output();
+ int start_num_svm_nodes = global_svm_nodes.size();
+
+ const double time_start = time_dt();
if(node->input("Surface")->link && node->input("Displacement")->link)
if(!shader->graph_bump)
shader->graph_bump = shader->graph->copy();
/* finalize */
- shader->graph->finalize(false, false);
- if(shader->graph_bump)
- shader->graph_bump->finalize(true, false);
+ {
+ scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
+ shader->graph->finalize(scene,
+ false,
+ false,
+ shader->has_integrator_dependency);
+ }
+
+ if(shader->graph_bump) {
+ scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
+ shader->graph_bump->finalize(scene,
+ true,
+ false,
+ shader->has_integrator_dependency);
+ }
current_shader = shader;
@@ -714,32 +765,101 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
shader->has_bssrdf_bump = false;
shader->has_volume = false;
shader->has_displacement = false;
- shader->has_heterogeneous_volume = false;
+ shader->has_surface_spatial_varying = false;
+ shader->has_volume_spatial_varying = false;
shader->has_object_dependency = false;
+ shader->has_integrator_dependency = false;
/* generate surface shader */
- compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- global_svm_nodes[index*2 + 0].y = global_svm_nodes.size();
- global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
- global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
+ {
+ scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
+ global_svm_nodes[index*2 + 0].y = global_svm_nodes.size();
+ global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
+ global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
+ }
if(shader->graph_bump) {
+ scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
}
/* generate volume shader */
- compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
- global_svm_nodes[index*2 + 0].z = global_svm_nodes.size();
- global_svm_nodes[index*2 + 1].z = global_svm_nodes.size();
- global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
+ {
+ scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ global_svm_nodes[index*2 + 0].z = global_svm_nodes.size();
+ global_svm_nodes[index*2 + 1].z = global_svm_nodes.size();
+ global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
+ }
/* generate displacement shader */
- compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
- global_svm_nodes[index*2 + 0].w = global_svm_nodes.size();
- global_svm_nodes[index*2 + 1].w = global_svm_nodes.size();
- global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
+ {
+ scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ global_svm_nodes[index*2 + 0].w = global_svm_nodes.size();
+ global_svm_nodes[index*2 + 1].w = global_svm_nodes.size();
+ global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
+ }
+
+ /* Fill in summary information. */
+ if(summary != NULL) {
+ summary->time_total = time_dt() - time_start;
+ summary->peak_stack_usage = max_stack_use;
+ summary->num_svm_nodes = global_svm_nodes.size() - start_num_svm_nodes;
+ }
+}
+
+/* Compiler summary implementation. */
+
+SVMCompiler::Summary::Summary()
+ : num_svm_nodes(0),
+ peak_stack_usage(0),
+ time_finalize(0.0),
+ time_finalize_bump(0.0),
+ time_generate_surface(0.0),
+ time_generate_bump(0.0),
+ time_generate_volume(0.0),
+ time_generate_displacement(0.0),
+ time_total(0.0)
+{
+}
+
+string SVMCompiler::Summary::full_report() const
+{
+ string report = "";
+ report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
+ report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
+
+ report += string_printf("Time (in seconds):\n");
+ report += string_printf(" Finalize: %f\n", time_finalize);
+ report += string_printf(" Bump finalize: %f\n", time_finalize_bump);
+ report += string_printf("Finalize: %f\n", time_finalize +
+ time_finalize_bump);
+ report += string_printf(" Surface: %f\n", time_generate_surface);
+ report += string_printf(" Bump: %f\n", time_generate_bump);
+ report += string_printf(" Volume: %f\n", time_generate_volume);
+ report += string_printf(" Displacement: %f\n", time_generate_displacement);
+ report += string_printf("Generate: %f\n", time_generate_surface +
+ time_generate_bump +
+ time_generate_volume +
+ time_generate_displacement);
+ report += string_printf("Total: %f\n", time_total);
+
+ 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