Cycles: Optimize shaders earlier to skip unneccessary attributes for noninteractive rendering

Before, Cycles would first sync the shader exactly as shown in the UI, then determine and sync the used attributes and later optimize the shader.
Therefore, even completely unconnected nodes would cause unneccessary attributes to be synced.

The reason for this is to avoid frequent resyncs when editing shaders interactively, but it can still be avoided for noninteractive renders - which is what this commit does.

Reviewed by: sergey

Differential Revision: https://developer.blender.org/D2285
This commit is contained in:
Lukas Stockner 2016-12-14 23:47:39 +01:00
parent 086320a62e
commit 5aaa643947
5 changed files with 39 additions and 9 deletions

@ -28,6 +28,7 @@
#include "util_debug.h" #include "util_debug.h"
#include "util_string.h" #include "util_string.h"
#include "util_task.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
@ -1164,6 +1165,8 @@ void BlenderSync::sync_materials(bool update_all)
/* material loop */ /* material loop */
BL::BlendData::materials_iterator b_mat; BL::BlendData::materials_iterator b_mat;
TaskPool pool;
for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
Shader *shader; Shader *shader;
@ -1199,9 +1202,22 @@ void BlenderSync::sync_materials(bool update_all)
shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP; shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP;
shader->set_graph(graph); shader->set_graph(graph);
/* By simplifying the shader graph as soon as possible, some redundant shader nodes
* might be removed which prevents loading unneccessary attributes later.
*
* However, since graph simplification also accounts for e.g. mix weight, this would
* cause frequent expensive resyncs in interactive sessions, so for those sessions
* optimization is only performed right before compiling. */
if(!preview) {
pool.push(function_bind(&ShaderGraph::simplify, shader->graph, scene));
}
shader->tag_update(scene); shader->tag_update(scene);
} }
} }
pool.wait_work();
} }
/* Sync World */ /* Sync World */

@ -17,6 +17,7 @@
#include "attribute.h" #include "attribute.h"
#include "graph.h" #include "graph.h"
#include "nodes.h" #include "nodes.h"
#include "scene.h"
#include "shader.h" #include "shader.h"
#include "constant_fold.h" #include "constant_fold.h"
@ -195,6 +196,7 @@ bool ShaderNode::equals(const ShaderNode& other)
ShaderGraph::ShaderGraph() ShaderGraph::ShaderGraph()
{ {
finalized = false; finalized = false;
simplified = false;
num_node_ids = 0; num_node_ids = 0;
add(new OutputNode()); add(new OutputNode());
} }
@ -207,6 +209,8 @@ ShaderGraph::~ShaderGraph()
ShaderNode *ShaderGraph::add(ShaderNode *node) ShaderNode *ShaderGraph::add(ShaderNode *node)
{ {
assert(!finalized); assert(!finalized);
simplified = false;
node->id = num_node_ids++; node->id = num_node_ids++;
nodes.push_back(node); nodes.push_back(node);
return node; return node;
@ -241,6 +245,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
{ {
assert(!finalized); assert(!finalized);
assert(from && to); assert(from && to);
simplified = false;
if(to->link) { if(to->link) {
fprintf(stderr, "Cycles shader graph connect: input already connected.\n"); fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
@ -273,6 +278,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
void ShaderGraph::disconnect(ShaderOutput *from) void ShaderGraph::disconnect(ShaderOutput *from)
{ {
assert(!finalized); assert(!finalized);
simplified = false;
foreach(ShaderInput *sock, from->links) { foreach(ShaderInput *sock, from->links) {
sock->link = NULL; sock->link = NULL;
@ -285,6 +291,7 @@ void ShaderGraph::disconnect(ShaderInput *to)
{ {
assert(!finalized); assert(!finalized);
assert(to->link); assert(to->link);
simplified = false;
ShaderOutput *from = to->link; ShaderOutput *from = to->link;
@ -294,6 +301,8 @@ void ShaderGraph::disconnect(ShaderInput *to)
void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
{ {
simplified = false;
/* Copy because disconnect modifies this list */ /* Copy because disconnect modifies this list */
vector<ShaderInput*> outputs = from->links; vector<ShaderInput*> outputs = from->links;
@ -310,9 +319,19 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
} }
} }
void ShaderGraph::simplify(Scene *scene)
{
if(!simplified) {
default_inputs(scene->shader_manager->use_osl());
clean(scene);
refine_bump_nodes();
simplified = true;
}
}
void ShaderGraph::finalize(Scene *scene, void ShaderGraph::finalize(Scene *scene,
bool do_bump, bool do_bump,
bool do_osl,
bool do_simplify, bool do_simplify,
bool bump_in_object_space) bool bump_in_object_space)
{ {
@ -322,9 +341,7 @@ void ShaderGraph::finalize(Scene *scene,
* modified afterwards. */ * modified afterwards. */
if(!finalized) { if(!finalized) {
default_inputs(do_osl); simplify(scene);
clean(scene);
refine_bump_nodes();
if(do_bump) if(do_bump)
bump_from_displacement(bump_in_object_space); bump_from_displacement(bump_in_object_space);

@ -240,6 +240,7 @@ public:
list<ShaderNode*> nodes; list<ShaderNode*> nodes;
size_t num_node_ids; size_t num_node_ids;
bool finalized; bool finalized;
bool simplified;
ShaderGraph(); ShaderGraph();
~ShaderGraph(); ~ShaderGraph();
@ -255,9 +256,9 @@ public:
void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to); void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
void remove_proxy_nodes(); void remove_proxy_nodes();
void simplify(Scene *scene);
void finalize(Scene *scene, void finalize(Scene *scene,
bool do_bump = false, bool do_bump = false,
bool do_osl = false,
bool do_simplify = false, bool do_simplify = false,
bool bump_in_object_space = false); bool bump_in_object_space = false);

@ -1096,11 +1096,9 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
/* finalize */ /* finalize */
shader->graph->finalize(scene, shader->graph->finalize(scene,
false, false,
true,
shader->has_integrator_dependency); shader->has_integrator_dependency);
if(shader->graph_bump) { if(shader->graph_bump) {
shader->graph_bump->finalize(scene, shader->graph_bump->finalize(scene,
true,
true, true,
shader->has_integrator_dependency, shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH); shader->displacement_method == DISPLACE_BOTH);

@ -812,7 +812,6 @@ void SVMCompiler::compile(Scene *scene,
{ {
scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL); scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
shader->graph->finalize(scene, shader->graph->finalize(scene,
false,
false, false,
shader->has_integrator_dependency); shader->has_integrator_dependency);
} }
@ -821,7 +820,6 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL); scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
shader->graph_bump->finalize(scene, shader->graph_bump->finalize(scene,
true, true,
false,
shader->has_integrator_dependency, shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH); shader->displacement_method == DISPLACE_BOTH);
} }