Cycles Volume Render: optimization to avoid exporting surface attributes when

only a volume shader is used.
This commit is contained in:
Brecht Van Lommel
2013-12-31 17:30:34 +01:00
parent 9939ec06dd
commit 6b03f92aa7
7 changed files with 88 additions and 63 deletions

View File

@@ -116,7 +116,7 @@ ShaderOutput *ShaderNode::add_output(const char *name, ShaderSocketType type)
return output; return output;
} }
void ShaderNode::attributes(AttributeRequestSet *attributes) void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
foreach(ShaderInput *input, inputs) { foreach(ShaderInput *input, inputs) {
if(!input->link) { if(!input->link) {
@@ -151,9 +151,9 @@ ShaderNode *ShaderGraph::add(ShaderNode *node)
return node; return node;
} }
ShaderNode *ShaderGraph::output() OutputNode *ShaderGraph::output()
{ {
return nodes.front(); return (OutputNode*)nodes.front();
} }
ShaderGraph *ShaderGraph::copy() ShaderGraph *ShaderGraph::copy()

View File

@@ -29,12 +29,14 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
class AttributeRequestSet; class AttributeRequestSet;
class Shader;
class ShaderInput; class ShaderInput;
class ShaderOutput; class ShaderOutput;
class ShaderNode; class ShaderNode;
class ShaderGraph; class ShaderGraph;
class SVMCompiler; class SVMCompiler;
class OSLCompiler; class OSLCompiler;
class OutputNode;
/* Socket Type /* Socket Type
* *
@@ -182,7 +184,7 @@ public:
ShaderOutput *add_output(const char *name, ShaderSocketType type); ShaderOutput *add_output(const char *name, ShaderSocketType type);
virtual ShaderNode *clone() const = 0; virtual ShaderNode *clone() const = 0;
virtual void attributes(AttributeRequestSet *attributes); virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
virtual void compile(SVMCompiler& compiler) = 0; virtual void compile(SVMCompiler& compiler) = 0;
virtual void compile(OSLCompiler& compiler) = 0; virtual void compile(OSLCompiler& compiler) = 0;
@@ -238,7 +240,7 @@ public:
ShaderGraph *copy(); ShaderGraph *copy();
ShaderNode *add(ShaderNode *node); ShaderNode *add(ShaderNode *node);
ShaderNode *output(); OutputNode *output();
void connect(ShaderOutput *from, ShaderInput *to); void connect(ShaderOutput *from, ShaderInput *to);
void disconnect(ShaderInput *to); void disconnect(ShaderInput *to);

View File

@@ -217,19 +217,19 @@ ShaderNode *ImageTextureNode::clone() const
return node; return node;
} }
void ImageTextureNode::attributes(AttributeRequestSet *attributes) void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
#ifdef WITH_PTEX #ifdef WITH_PTEX
/* todo: avoid loading other texture coordinates when using ptex, /* todo: avoid loading other texture coordinates when using ptex,
* and hide texture coordinate socket in the UI */ * and hide texture coordinate socket in the UI */
if (string_endswith(filename, ".ptx")) { if (shader->has_surface && string_endswith(filename, ".ptx")) {
/* ptex */ /* ptex */
attributes->add(ATTR_STD_PTEX_FACE_ID); attributes->add(ATTR_STD_PTEX_FACE_ID);
attributes->add(ATTR_STD_PTEX_UV); attributes->add(ATTR_STD_PTEX_UV);
} }
#endif #endif
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void ImageTextureNode::compile(SVMCompiler& compiler) void ImageTextureNode::compile(SVMCompiler& compiler)
@@ -367,17 +367,17 @@ ShaderNode *EnvironmentTextureNode::clone() const
return node; return node;
} }
void EnvironmentTextureNode::attributes(AttributeRequestSet *attributes) void EnvironmentTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
#ifdef WITH_PTEX #ifdef WITH_PTEX
if (string_endswith(filename, ".ptx")) { if (shader->has_surface && string_endswith(filename, ".ptx")) {
/* ptex */ /* ptex */
attributes->add(ATTR_STD_PTEX_FACE_ID); attributes->add(ATTR_STD_PTEX_FACE_ID);
attributes->add(ATTR_STD_PTEX_UV); attributes->add(ATTR_STD_PTEX_UV);
} }
#endif #endif
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void EnvironmentTextureNode::compile(SVMCompiler& compiler) void EnvironmentTextureNode::compile(SVMCompiler& compiler)
@@ -1533,14 +1533,16 @@ WardBsdfNode::WardBsdfNode()
add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f); add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f);
} }
void WardBsdfNode::attributes(AttributeRequestSet *attributes) void WardBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
ShaderInput *tangent_in = input("Tangent"); if(shader->has_surface) {
ShaderInput *tangent_in = input("Tangent");
if(!tangent_in->link) if(!tangent_in->link)
attributes->add(ATTR_STD_GENERATED); attributes->add(ATTR_STD_GENERATED);
}
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void WardBsdfNode::compile(SVMCompiler& compiler) void WardBsdfNode::compile(SVMCompiler& compiler)
@@ -2088,12 +2090,14 @@ GeometryNode::GeometryNode()
add_output("Backfacing", SHADER_SOCKET_FLOAT); add_output("Backfacing", SHADER_SOCKET_FLOAT);
} }
void GeometryNode::attributes(AttributeRequestSet *attributes) void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if(!output("Tangent")->links.empty()) if(shader->has_surface) {
attributes->add(ATTR_STD_GENERATED); if(!output("Tangent")->links.empty())
attributes->add(ATTR_STD_GENERATED);
}
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void GeometryNode::compile(SVMCompiler& compiler) void GeometryNode::compile(SVMCompiler& compiler)
@@ -2178,16 +2182,18 @@ TextureCoordinateNode::TextureCoordinateNode()
from_dupli = false; from_dupli = false;
} }
void TextureCoordinateNode::attributes(AttributeRequestSet *attributes) void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if(!from_dupli) { if(shader->has_surface) {
if(!output("Generated")->links.empty()) if(!from_dupli) {
attributes->add(ATTR_STD_GENERATED); if(!output("Generated")->links.empty())
if(!output("UV")->links.empty()) attributes->add(ATTR_STD_GENERATED);
attributes->add(ATTR_STD_UV); if(!output("UV")->links.empty())
attributes->add(ATTR_STD_UV);
}
} }
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void TextureCoordinateNode::compile(SVMCompiler& compiler) void TextureCoordinateNode::compile(SVMCompiler& compiler)
@@ -2490,7 +2496,7 @@ ParticleInfoNode::ParticleInfoNode()
add_output("Angular Velocity", SHADER_SOCKET_VECTOR); add_output("Angular Velocity", SHADER_SOCKET_VECTOR);
} }
void ParticleInfoNode::attributes(AttributeRequestSet *attributes) void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if(!output("Index")->links.empty()) if(!output("Index")->links.empty())
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
@@ -2511,7 +2517,7 @@ void ParticleInfoNode::attributes(AttributeRequestSet *attributes)
if(!output("Angular Velocity")->links.empty()) if(!output("Angular Velocity")->links.empty())
attributes->add(ATTR_STD_PARTICLE); attributes->add(ATTR_STD_PARTICLE);
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void ParticleInfoNode::compile(SVMCompiler& compiler) void ParticleInfoNode::compile(SVMCompiler& compiler)
@@ -2588,14 +2594,16 @@ HairInfoNode::HairInfoNode()
/*add_output("Fade", SHADER_SOCKET_FLOAT);*/ /*add_output("Fade", SHADER_SOCKET_FLOAT);*/
} }
void HairInfoNode::attributes(AttributeRequestSet *attributes) void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
ShaderOutput *intercept_out = output("Intercept"); if(shader->has_surface) {
ShaderOutput *intercept_out = output("Intercept");
if(!intercept_out->links.empty()) if(!intercept_out->links.empty())
attributes->add(ATTR_STD_CURVE_INTERCEPT); attributes->add(ATTR_STD_CURVE_INTERCEPT);
}
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void HairInfoNode::compile(SVMCompiler& compiler) void HairInfoNode::compile(SVMCompiler& compiler)
@@ -3106,16 +3114,18 @@ AttributeNode::AttributeNode()
add_output("Fac", SHADER_SOCKET_FLOAT); add_output("Fac", SHADER_SOCKET_FLOAT);
} }
void AttributeNode::attributes(AttributeRequestSet *attributes) void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
ShaderOutput *color_out = output("Color"); if(shader->has_surface) {
ShaderOutput *vector_out = output("Vector"); ShaderOutput *color_out = output("Color");
ShaderOutput *fac_out = output("Fac"); ShaderOutput *vector_out = output("Vector");
ShaderOutput *fac_out = output("Fac");
if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty())
attributes->add(attribute); attributes->add(attribute);
}
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void AttributeNode::compile(SVMCompiler& compiler) void AttributeNode::compile(SVMCompiler& compiler)
@@ -3831,9 +3841,9 @@ NormalMapNode::NormalMapNode()
add_output("Normal", SHADER_SOCKET_NORMAL); add_output("Normal", SHADER_SOCKET_NORMAL);
} }
void NormalMapNode::attributes(AttributeRequestSet *attributes) void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if(space == ustring("Tangent")) { if(shader->has_surface && space == ustring("Tangent")) {
if(attribute == ustring("")) { if(attribute == ustring("")) {
attributes->add(ATTR_STD_UV_TANGENT); attributes->add(ATTR_STD_UV_TANGENT);
attributes->add(ATTR_STD_UV_TANGENT_SIGN); attributes->add(ATTR_STD_UV_TANGENT_SIGN);
@@ -3846,7 +3856,7 @@ void NormalMapNode::attributes(AttributeRequestSet *attributes)
attributes->add(ATTR_STD_VERTEX_NORMAL); attributes->add(ATTR_STD_VERTEX_NORMAL);
} }
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void NormalMapNode::compile(SVMCompiler& compiler) void NormalMapNode::compile(SVMCompiler& compiler)
@@ -3935,18 +3945,20 @@ TangentNode::TangentNode()
add_output("Tangent", SHADER_SOCKET_NORMAL); add_output("Tangent", SHADER_SOCKET_NORMAL);
} }
void TangentNode::attributes(AttributeRequestSet *attributes) void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{ {
if(direction_type == ustring("UV Map")) { if(shader->has_surface) {
if(attribute == ustring("")) if(direction_type == ustring("UV Map")) {
attributes->add(ATTR_STD_UV_TANGENT); if(attribute == ustring(""))
attributes->add(ATTR_STD_UV_TANGENT);
else
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
}
else else
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); attributes->add(ATTR_STD_GENERATED);
} }
else
attributes->add(ATTR_STD_GENERATED);
ShaderNode::attributes(attributes); ShaderNode::attributes(shader, attributes);
} }
void TangentNode::compile(SVMCompiler& compiler) void TangentNode::compile(SVMCompiler& compiler)

View File

@@ -66,7 +66,7 @@ public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode) SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
~ImageTextureNode(); ~ImageTextureNode();
ShaderNode *clone() const; ShaderNode *clone() const;
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
ImageManager *image_manager; ImageManager *image_manager;
int slot; int slot;
@@ -88,7 +88,7 @@ public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode) SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
~EnvironmentTextureNode(); ~EnvironmentTextureNode();
ShaderNode *clone() const; ShaderNode *clone() const;
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
ImageManager *image_manager; ImageManager *image_manager;
int slot; int slot;
@@ -217,7 +217,7 @@ public:
class WardBsdfNode : public BsdfNode { class WardBsdfNode : public BsdfNode {
public: public:
SHADER_NODE_CLASS(WardBsdfNode) SHADER_NODE_CLASS(WardBsdfNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
}; };
class DiffuseBsdfNode : public BsdfNode { class DiffuseBsdfNode : public BsdfNode {
@@ -338,13 +338,13 @@ public:
class GeometryNode : public ShaderNode { class GeometryNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(GeometryNode) SHADER_NODE_CLASS(GeometryNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
}; };
class TextureCoordinateNode : public ShaderNode { class TextureCoordinateNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(TextureCoordinateNode) SHADER_NODE_CLASS(TextureCoordinateNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
bool from_dupli; bool from_dupli;
}; };
@@ -367,14 +367,14 @@ public:
class ParticleInfoNode : public ShaderNode { class ParticleInfoNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(ParticleInfoNode) SHADER_NODE_CLASS(ParticleInfoNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
}; };
class HairInfoNode : public ShaderNode { class HairInfoNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(HairInfoNode) SHADER_NODE_CLASS(HairInfoNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
}; };
class ValueNode : public ShaderNode { class ValueNode : public ShaderNode {
@@ -459,7 +459,7 @@ public:
class AttributeNode : public ShaderNode { class AttributeNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(AttributeNode) SHADER_NODE_CLASS(AttributeNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
ustring attribute; ustring attribute;
}; };
@@ -580,7 +580,7 @@ public:
class NormalMapNode : public ShaderNode { class NormalMapNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(NormalMapNode) SHADER_NODE_CLASS(NormalMapNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
ustring space; ustring space;
static ShaderEnum space_enum; static ShaderEnum space_enum;
@@ -591,7 +591,7 @@ public:
class TangentNode : public ShaderNode { class TangentNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(TangentNode) SHADER_NODE_CLASS(TangentNode)
void attributes(AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
ustring direction_type; ustring direction_type;
static ShaderEnum direction_type_enum; static ShaderEnum direction_type_enum;

View File

@@ -21,6 +21,7 @@
#include "osl.h" #include "osl.h"
#include "scene.h" #include "scene.h"
#include "shader.h" #include "shader.h"
#include "nodes.h"
#ifdef WITH_OSL #ifdef WITH_OSL

View File

@@ -93,15 +93,24 @@ void Shader::tag_update(Scene *scene)
if(use_mis && has_surface_emission) if(use_mis && has_surface_emission)
scene->light_manager->need_update = true; scene->light_manager->need_update = true;
/* quick detection of which kind of shaders we have to avoid loading
* e.g. surface attributes when there is only a volume shader. this could
* be more fine grained but it's better than nothing */
OutputNode *output = graph->output();
has_surface = has_surface || output->input("Surface")->link;
has_volume = has_volume || output->input("Volume")->link;
has_displacement = has_displacement || output->input("Displacement")->link;
/* get requested attributes. this could be optimized by pruning unused /* get requested attributes. this could be optimized by pruning unused
* nodes here already, but that's the job of the shader manager currently, * nodes here already, but that's the job of the shader manager currently,
* and may not be so great for interactive rendering where you temporarily * and may not be so great for interactive rendering where you temporarily
* disconnect a node */ * disconnect a node */
AttributeRequestSet prev_attributes = attributes; AttributeRequestSet prev_attributes = attributes;
attributes.clear(); attributes.clear();
foreach(ShaderNode *node, graph->nodes) foreach(ShaderNode *node, graph->nodes)
node->attributes(&attributes); node->attributes(this, &attributes);
/* compare if the attributes changed, mesh manager will check /* compare if the attributes changed, mesh manager will check
* need_update_attributes, update the relevant meshes and clear it. */ * need_update_attributes, update the relevant meshes and clear it. */

View File

@@ -18,6 +18,7 @@
#include "graph.h" #include "graph.h"
#include "light.h" #include "light.h"
#include "mesh.h" #include "mesh.h"
#include "nodes.h"
#include "scene.h" #include "scene.h"
#include "shader.h" #include "shader.h"
#include "svm.h" #include "svm.h"