Cycles: Implement selective nodes compilation

This commits finishes initial selective nodes compilation into kernel, which
helps a lot performance-wise for AMD OpenCL kernels.

Split by node groups is based on statistics from simple scenes like BMW and
more complex scenes like mango and gooseberry production files. Further
tweaks are always possible, but it should be a good starting point.

TODO: Still need to ignore unused nodes when calculating requested shader
features.
This commit is contained in:
Sergey Sharybin 2015-06-01 17:48:45 +05:00
parent c0235da53c
commit ecd4ee75af
3 changed files with 215 additions and 137 deletions

@ -212,17 +212,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_CLOSURE_BACKGROUND: case NODE_CLOSURE_BACKGROUND:
svm_node_closure_background(sd, stack, node); svm_node_closure_background(sd, stack, node);
break; break;
case NODE_CLOSURE_HOLDOUT:
svm_node_closure_holdout(sd, stack, node);
break;
case NODE_CLOSURE_AMBIENT_OCCLUSION:
svm_node_closure_ambient_occlusion(sd, stack, node);
break;
#if NODES_FEATURE(NODE_FEATURE_VOLUME)
case NODE_CLOSURE_VOLUME:
svm_node_closure_volume(kg, sd, stack, node, path_flag);
break;
#endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
case NODE_CLOSURE_SET_WEIGHT: case NODE_CLOSURE_SET_WEIGHT:
svm_node_closure_set_weight(sd, node.y, node.z, node.w); svm_node_closure_set_weight(sd, node.y, node.z, node.w);
break; break;
@ -235,7 +224,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_MIX_CLOSURE: case NODE_MIX_CLOSURE:
svm_node_mix_closure(sd, stack, node); svm_node_mix_closure(sd, stack, node);
break; break;
#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
case NODE_JUMP_IF_ZERO: case NODE_JUMP_IF_ZERO:
if(stack_load_float(stack, node.z) == 0.0f) if(stack_load_float(stack, node.z) == 0.0f)
offset += node.y; offset += node.y;
@ -244,13 +232,137 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
if(stack_load_float(stack, node.z) == 1.0f) if(stack_load_float(stack, node.z) == 1.0f)
offset += node.y; offset += node.y;
break; break;
#ifdef __TEXTURES__ case NODE_GEOMETRY:
svm_node_geometry(kg, sd, stack, node.y, node.z);
break;
case NODE_CONVERT:
svm_node_convert(sd, stack, node.y, node.z, node.w);
break;
case NODE_TEX_COORD:
svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
break;
case NODE_VALUE_F:
svm_node_value_f(kg, sd, stack, node.y, node.z);
break;
case NODE_VALUE_V:
svm_node_value_v(kg, sd, stack, node.y, &offset);
break;
case NODE_ATTR:
svm_node_attr(kg, sd, stack, node);
break;
# if NODES_FEATURE(NODE_FEATURE_BUMP)
case NODE_GEOMETRY_BUMP_DX:
svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
break;
case NODE_GEOMETRY_BUMP_DY:
svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
break;
case NODE_SET_DISPLACEMENT:
svm_node_set_displacement(sd, stack, node.y);
break;
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
# ifdef __TEXTURES__
case NODE_TEX_IMAGE: case NODE_TEX_IMAGE:
svm_node_tex_image(kg, sd, stack, node); svm_node_tex_image(kg, sd, stack, node);
break; break;
case NODE_TEX_IMAGE_BOX: case NODE_TEX_IMAGE_BOX:
svm_node_tex_image_box(kg, sd, stack, node); svm_node_tex_image_box(kg, sd, stack, node);
break; break;
case NODE_TEX_NOISE:
svm_node_tex_noise(kg, sd, stack, node, &offset);
break;
# endif /* __TEXTURES__ */
# ifdef __EXTRA_NODES__
# if NODES_FEATURE(NODE_FEATURE_BUMP)
case NODE_SET_BUMP:
svm_node_set_bump(kg, sd, stack, node);
break;
case NODE_ATTR_BUMP_DX:
svm_node_attr_bump_dx(kg, sd, stack, node);
break;
case NODE_ATTR_BUMP_DY:
svm_node_attr_bump_dy(kg, sd, stack, node);
break;
case NODE_TEX_COORD_BUMP_DX:
svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
break;
case NODE_TEX_COORD_BUMP_DY:
svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
break;
case NODE_CLOSURE_SET_NORMAL:
svm_node_set_normal(kg, sd, stack, node.y, node.z);
break;
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
case NODE_HSV:
svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
# endif /* __EXTRA_NODES__ */
#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
#if NODES_GROUP(NODE_GROUP_LEVEL_1)
case NODE_CLOSURE_HOLDOUT:
svm_node_closure_holdout(sd, stack, node);
break;
case NODE_CLOSURE_AMBIENT_OCCLUSION:
svm_node_closure_ambient_occlusion(sd, stack, node);
break;
case NODE_FRESNEL:
svm_node_fresnel(sd, stack, node.y, node.z, node.w);
break;
case NODE_LAYER_WEIGHT:
svm_node_layer_weight(sd, stack, node);
break;
# if NODES_FEATURE(NODE_FEATURE_VOLUME)
case NODE_CLOSURE_VOLUME:
svm_node_closure_volume(kg, sd, stack, node, path_flag);
break;
# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
# ifdef __EXTRA_NODES__
case NODE_MATH:
svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_VECTOR_MATH:
svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_RGB_RAMP:
svm_node_rgb_ramp(kg, sd, stack, node, &offset);
break;
case NODE_GAMMA:
svm_node_gamma(sd, stack, node.y, node.z, node.w);
break;
case NODE_BRIGHTCONTRAST:
svm_node_brightness(sd, stack, node.y, node.z, node.w);
break;
case NODE_LIGHT_PATH:
svm_node_light_path(sd, stack, node.y, node.z, path_flag);
break;
case NODE_OBJECT_INFO:
svm_node_object_info(kg, sd, stack, node.y, node.z);
break;
case NODE_PARTICLE_INFO:
svm_node_particle_info(kg, sd, stack, node.y, node.z);
break;
# ifdef __HAIR__
# if NODES_FEATURE(NODE_FEATURE_HAIR)
case NODE_HAIR_INFO:
svm_node_hair_info(kg, sd, stack, node.y, node.z);
break;
# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
# endif /* __HAIR__ */
# endif /* __EXTRA_NODES__ */
#endif /* NODES_GROUP(NODE_GROUP_LEVEL_1) */
#if NODES_GROUP(NODE_GROUP_LEVEL_2)
case NODE_MAPPING:
svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
break;
case NODE_MIN_MAX:
svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
break;
case NODE_CAMERA:
svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
break;
# ifdef __TEXTURES__
case NODE_TEX_ENVIRONMENT: case NODE_TEX_ENVIRONMENT:
svm_node_tex_environment(kg, sd, stack, node); svm_node_tex_environment(kg, sd, stack, node);
break; break;
@ -260,9 +372,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_GRADIENT: case NODE_TEX_GRADIENT:
svm_node_tex_gradient(sd, stack, node); svm_node_tex_gradient(sd, stack, node);
break; break;
case NODE_TEX_NOISE:
svm_node_tex_noise(kg, sd, stack, node, &offset);
break;
case NODE_TEX_VORONOI: case NODE_TEX_VORONOI:
svm_node_tex_voronoi(kg, sd, stack, node, &offset); svm_node_tex_voronoi(kg, sd, stack, node, &offset);
break; break;
@ -281,57 +390,34 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_TEX_BRICK: case NODE_TEX_BRICK:
svm_node_tex_brick(kg, sd, stack, node, &offset); svm_node_tex_brick(kg, sd, stack, node, &offset);
break; break;
#endif /* __TEXTURES__ */ # endif /* __TEXTURES__ */
case NODE_CAMERA: # ifdef __EXTRA_NODES__
svm_node_camera(kg, sd, stack, node.y, node.z, node.w); case NODE_NORMAL:
svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
break; break;
case NODE_GEOMETRY: case NODE_LIGHT_FALLOFF:
svm_node_geometry(kg, sd, stack, node.y, node.z); svm_node_light_falloff(sd, stack, node);
break; break;
#ifdef __EXTRA_NODES__ # endif /* __EXTRA_NODES__ */
case NODE_GEOMETRY_BUMP_DX: #endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
break;
case NODE_GEOMETRY_BUMP_DY:
svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
break;
case NODE_LIGHT_PATH:
svm_node_light_path(sd, stack, node.y, node.z, path_flag);
break;
case NODE_OBJECT_INFO:
svm_node_object_info(kg, sd, stack, node.y, node.z);
break;
case NODE_PARTICLE_INFO:
svm_node_particle_info(kg, sd, stack, node.y, node.z);
break;
#ifdef __HAIR__
# if NODES_FEATURE(NODE_FEATURE_HAIR)
case NODE_HAIR_INFO:
svm_node_hair_info(kg, sd, stack, node.y, node.z);
break;
# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
#endif /* __HAIR__ */
#endif /* __EXTRA_NODES__ */ #if NODES_GROUP(NODE_GROUP_LEVEL_3)
case NODE_CONVERT: case NODE_RGB_CURVES:
svm_node_convert(sd, stack, node.y, node.z, node.w); svm_node_rgb_curves(kg, sd, stack, node, &offset);
break; break;
case NODE_VALUE_F: case NODE_VECTOR_CURVES:
svm_node_value_f(kg, sd, stack, node.y, node.z); svm_node_vector_curves(kg, sd, stack, node, &offset);
break; break;
case NODE_VALUE_V: case NODE_TANGENT:
svm_node_value_v(kg, sd, stack, node.y, &offset); svm_node_tangent(kg, sd, stack, node);
break; break;
#ifdef __EXTRA_NODES__ case NODE_NORMAL_MAP:
svm_node_normal_map(kg, sd, stack, node);
break;
# ifdef __EXTRA_NODES__
case NODE_INVERT: case NODE_INVERT:
svm_node_invert(sd, stack, node.y, node.z, node.w); svm_node_invert(sd, stack, node.y, node.z, node.w);
break; break;
case NODE_GAMMA:
svm_node_gamma(sd, stack, node.y, node.z, node.w);
break;
case NODE_BRIGHTCONTRAST:
svm_node_brightness(sd, stack, node.y, node.z, node.w);
break;
case NODE_MIX: case NODE_MIX:
svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset); svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset);
break; break;
@ -347,28 +433,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_COMBINE_HSV: case NODE_COMBINE_HSV:
svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset); svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
break; break;
case NODE_HSV: case NODE_VECTOR_TRANSFORM:
svm_node_hsv(kg, sd, stack, node.y, node.z, node.w, &offset); svm_node_vector_transform(kg, sd, stack, node);
break; break;
#endif /* __EXTRA_NODES__ */
case NODE_ATTR:
svm_node_attr(kg, sd, stack, node);
break;
#ifdef __EXTRA_NODES__
case NODE_ATTR_BUMP_DX:
svm_node_attr_bump_dx(kg, sd, stack, node);
break;
case NODE_ATTR_BUMP_DY:
svm_node_attr_bump_dy(kg, sd, stack, node);
break;
#endif /* __EXTRA_NODES__ */
case NODE_FRESNEL:
svm_node_fresnel(sd, stack, node.y, node.z, node.w);
break;
case NODE_LAYER_WEIGHT:
svm_node_layer_weight(sd, stack, node);
break;
#ifdef __EXTRA_NODES__
case NODE_WIREFRAME: case NODE_WIREFRAME:
svm_node_wireframe(kg, sd, stack, node); svm_node_wireframe(kg, sd, stack, node);
break; break;
@ -378,63 +445,8 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
case NODE_BLACKBODY: case NODE_BLACKBODY:
svm_node_blackbody(kg, sd, stack, node.y, node.z); svm_node_blackbody(kg, sd, stack, node.y, node.z);
break; break;
case NODE_SET_DISPLACEMENT: # endif /* __EXTRA_NODES__ */
svm_node_set_displacement(sd, stack, node.y); #endif /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
break;
case NODE_SET_BUMP:
svm_node_set_bump(kg, sd, stack, node);
break;
case NODE_MATH:
svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_VECTOR_MATH:
svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_VECTOR_TRANSFORM:
svm_node_vector_transform(kg, sd, stack, node);
break;
case NODE_NORMAL:
svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
#endif /* __EXTRA_NODES__ */
case NODE_MAPPING:
svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
break;
case NODE_MIN_MAX:
svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
break;
case NODE_TEX_COORD:
svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
break;
#ifdef __EXTRA_NODES__
case NODE_TEX_COORD_BUMP_DX:
svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
break;
case NODE_TEX_COORD_BUMP_DY:
svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
break;
case NODE_CLOSURE_SET_NORMAL:
svm_node_set_normal(kg, sd, stack, node.y, node.z );
break;
case NODE_RGB_RAMP:
svm_node_rgb_ramp(kg, sd, stack, node, &offset);
break;
case NODE_RGB_CURVES:
svm_node_rgb_curves(kg, sd, stack, node, &offset);
break;
case NODE_VECTOR_CURVES:
svm_node_vector_curves(kg, sd, stack, node, &offset);
break;
case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node);
break;
#endif /* __EXTRA_NODES__ */
case NODE_TANGENT:
svm_node_tangent(kg, sd, stack, node);
break;
case NODE_NORMAL_MAP:
svm_node_normal_map(kg, sd, stack, node);
break;
case NODE_END: case NODE_END:
default: default:
return; return;

@ -39,7 +39,8 @@ CCL_NAMESPACE_BEGIN
#define NODE_GROUP_LEVEL_0 0 #define NODE_GROUP_LEVEL_0 0
#define NODE_GROUP_LEVEL_1 1 #define NODE_GROUP_LEVEL_1 1
#define NODE_GROUP_LEVEL_2 2 #define NODE_GROUP_LEVEL_2 2
#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_2 #define NODE_GROUP_LEVEL_3 3
#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_3
#define NODE_FEATURE_VOLUME (1 << 0) #define NODE_FEATURE_VOLUME (1 << 0)
#define NODE_FEATURE_HAIR (1 << 1) #define NODE_FEATURE_HAIR (1 << 1)

@ -105,6 +105,7 @@ public:
~EnvironmentTextureNode(); ~EnvironmentTextureNode();
ShaderNode *clone() const; ShaderNode *clone() const;
void attributes(Shader *shader, AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ImageManager *image_manager; ImageManager *image_manager;
int is_float; int is_float;
@ -124,6 +125,8 @@ class SkyTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(SkyTextureNode) SHADER_NODE_CLASS(SkyTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
float3 sun_direction; float3 sun_direction;
float turbidity; float turbidity;
float ground_albedo; float ground_albedo;
@ -141,6 +144,8 @@ class GradientTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(GradientTextureNode) SHADER_NODE_CLASS(GradientTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ustring type; ustring type;
static ShaderEnum type_enum; static ShaderEnum type_enum;
}; };
@ -154,6 +159,8 @@ class VoronoiTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(VoronoiTextureNode) SHADER_NODE_CLASS(VoronoiTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ustring coloring; ustring coloring;
static ShaderEnum coloring_enum; static ShaderEnum coloring_enum;
@ -163,6 +170,8 @@ class MusgraveTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(MusgraveTextureNode) SHADER_NODE_CLASS(MusgraveTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ustring type; ustring type;
static ShaderEnum type_enum; static ShaderEnum type_enum;
@ -172,6 +181,8 @@ class WaveTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(WaveTextureNode) SHADER_NODE_CLASS(WaveTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
ustring type; ustring type;
static ShaderEnum type_enum; static ShaderEnum type_enum;
}; };
@ -180,12 +191,16 @@ class MagicTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(MagicTextureNode) SHADER_NODE_CLASS(MagicTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
int depth; int depth;
}; };
class CheckerTextureNode : public TextureNode { class CheckerTextureNode : public TextureNode {
public: public:
SHADER_NODE_CLASS(CheckerTextureNode) SHADER_NODE_CLASS(CheckerTextureNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
}; };
class BrickTextureNode : public TextureNode { class BrickTextureNode : public TextureNode {
@ -194,11 +209,14 @@ public:
float offset, squash; float offset, squash;
int offset_frequency, squash_frequency; int offset_frequency, squash_frequency;
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
}; };
class MappingNode : public ShaderNode { class MappingNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(MappingNode) SHADER_NODE_CLASS(MappingNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
TextureMapping tex_mapping; TextureMapping tex_mapping;
}; };
@ -321,6 +339,7 @@ public:
class HoldoutNode : public ShaderNode { class HoldoutNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(HoldoutNode) SHADER_NODE_CLASS(HoldoutNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class AmbientOcclusionNode : public ShaderNode { class AmbientOcclusionNode : public ShaderNode {
@ -328,6 +347,7 @@ public:
SHADER_NODE_CLASS(AmbientOcclusionNode) SHADER_NODE_CLASS(AmbientOcclusionNode)
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class VolumeNode : public ShaderNode { class VolumeNode : public ShaderNode {
@ -335,6 +355,7 @@ public:
SHADER_NODE_CLASS(VolumeNode) SHADER_NODE_CLASS(VolumeNode)
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2); void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ClosureType closure; ClosureType closure;
}; };
@ -382,6 +403,7 @@ public:
SHADER_NODE_CLASS(UVMapNode) SHADER_NODE_CLASS(UVMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring attribute; ustring attribute;
bool from_dupli; bool from_dupli;
@ -390,6 +412,7 @@ public:
class LightPathNode : public ShaderNode { class LightPathNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(LightPathNode) SHADER_NODE_CLASS(LightPathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class LightFalloffNode : public ShaderNode { class LightFalloffNode : public ShaderNode {
@ -401,12 +424,14 @@ public:
class ObjectInfoNode : public ShaderNode { class ObjectInfoNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(ObjectInfoNode) SHADER_NODE_CLASS(ObjectInfoNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class ParticleInfoNode : public ShaderNode { class ParticleInfoNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(ParticleInfoNode) SHADER_NODE_CLASS(ParticleInfoNode)
void attributes(Shader *shader, AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class HairInfoNode : public ShaderNode { class HairInfoNode : public ShaderNode {
@ -415,6 +440,7 @@ public:
void attributes(Shader *shader, AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
virtual int get_feature() { virtual int get_feature() {
return ShaderNode::get_feature() | NODE_FEATURE_HAIR; return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
} }
@ -452,12 +478,16 @@ public:
class InvertNode : public ShaderNode { class InvertNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(InvertNode) SHADER_NODE_CLASS(InvertNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class MixNode : public ShaderNode { class MixNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(MixNode) SHADER_NODE_CLASS(MixNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
bool use_clamp; bool use_clamp;
ustring type; ustring type;
@ -467,41 +497,55 @@ public:
class CombineRGBNode : public ShaderNode { class CombineRGBNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(CombineRGBNode) SHADER_NODE_CLASS(CombineRGBNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class CombineHSVNode : public ShaderNode { class CombineHSVNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(CombineHSVNode) SHADER_NODE_CLASS(CombineHSVNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class CombineXYZNode : public ShaderNode { class CombineXYZNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(CombineXYZNode) SHADER_NODE_CLASS(CombineXYZNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class GammaNode : public ShaderNode { class GammaNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(GammaNode) SHADER_NODE_CLASS(GammaNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class BrightContrastNode : public ShaderNode { class BrightContrastNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(BrightContrastNode) SHADER_NODE_CLASS(BrightContrastNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class SeparateRGBNode : public ShaderNode { class SeparateRGBNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(SeparateRGBNode) SHADER_NODE_CLASS(SeparateRGBNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class SeparateHSVNode : public ShaderNode { class SeparateHSVNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(SeparateHSVNode) SHADER_NODE_CLASS(SeparateHSVNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class SeparateXYZNode : public ShaderNode { class SeparateXYZNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(SeparateXYZNode) SHADER_NODE_CLASS(SeparateXYZNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class HSVNode : public ShaderNode { class HSVNode : public ShaderNode {
@ -528,18 +572,21 @@ class FresnelNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(FresnelNode) SHADER_NODE_CLASS(FresnelNode)
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class LayerWeightNode : public ShaderNode { class LayerWeightNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(LayerWeightNode) SHADER_NODE_CLASS(LayerWeightNode)
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class WireframeNode : public ShaderNode { class WireframeNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(WireframeNode) SHADER_NODE_CLASS(WireframeNode)
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
bool use_pixel_size; bool use_pixel_size;
}; };
@ -547,16 +594,21 @@ public:
class WavelengthNode : public ShaderNode { class WavelengthNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(WavelengthNode) SHADER_NODE_CLASS(WavelengthNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class BlackbodyNode : public ShaderNode { class BlackbodyNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(BlackbodyNode) SHADER_NODE_CLASS(BlackbodyNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
}; };
class MathNode : public ShaderNode { class MathNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(MathNode) SHADER_NODE_CLASS(MathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
bool use_clamp; bool use_clamp;
@ -567,6 +619,7 @@ public:
class NormalNode : public ShaderNode { class NormalNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(NormalNode) SHADER_NODE_CLASS(NormalNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
float3 direction; float3 direction;
}; };
@ -574,6 +627,7 @@ public:
class VectorMathNode : public ShaderNode { class VectorMathNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(VectorMathNode) SHADER_NODE_CLASS(VectorMathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
ustring type; ustring type;
static ShaderEnum type_enum; static ShaderEnum type_enum;
@ -583,6 +637,8 @@ class VectorTransformNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(VectorTransformNode) SHADER_NODE_CLASS(VectorTransformNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring type; ustring type;
ustring convert_from; ustring convert_from;
ustring convert_to; ustring convert_to;
@ -602,12 +658,18 @@ public:
class RGBCurvesNode : public ShaderNode { class RGBCurvesNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(RGBCurvesNode) SHADER_NODE_CLASS(RGBCurvesNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float4 curves[RAMP_TABLE_SIZE]; float4 curves[RAMP_TABLE_SIZE];
}; };
class VectorCurvesNode : public ShaderNode { class VectorCurvesNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(VectorCurvesNode) SHADER_NODE_CLASS(VectorCurvesNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
float4 curves[RAMP_TABLE_SIZE]; float4 curves[RAMP_TABLE_SIZE];
}; };
@ -616,6 +678,7 @@ public:
SHADER_NODE_CLASS(RGBRampNode) SHADER_NODE_CLASS(RGBRampNode)
float4 ramp[RAMP_TABLE_SIZE]; float4 ramp[RAMP_TABLE_SIZE];
bool interpolate; bool interpolate;
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
}; };
class SetNormalNode : public ShaderNode { class SetNormalNode : public ShaderNode {
@ -644,6 +707,7 @@ public:
SHADER_NODE_CLASS(NormalMapNode) SHADER_NODE_CLASS(NormalMapNode)
void attributes(Shader *shader, AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring space; ustring space;
static ShaderEnum space_enum; static ShaderEnum space_enum;
@ -656,6 +720,7 @@ public:
SHADER_NODE_CLASS(TangentNode) SHADER_NODE_CLASS(TangentNode)
void attributes(Shader *shader, AttributeRequestSet *attributes); void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; } bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
ustring direction_type; ustring direction_type;
static ShaderEnum direction_type_enum; static ShaderEnum direction_type_enum;