Question Regarding SVM Add Node Parameters

Hi,
I’m trying to understand some of the blender source code. Something I’ve noticed when looking at node definitions in nodes.cpp is that some nodes will pass both a stack offset for a parameter, as well as the value directly when adding a node for SVM compilation.

An example is the wave texture node

void WaveTextureNode::compile(SVMCompiler &compiler)
{
ShaderInput *scale_in = input(“Scale”);
ShaderInput *distortion_in = input(“Distortion”);
ShaderInput *dscale_in = input(“Detail Scale”);
ShaderInput *detail_in = input(“Detail”);
ShaderInput *vector_in = input(“Vector”);
ShaderOutput *fac_out = output(“Fac”);
ShaderOutput *color_out = output(“Color”);
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);

compiler.add_node(NODE_TEX_WAVE,
compiler.encode_uchar4(type,
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out),
compiler.stack_assign_if_linked(dscale_in)),
compiler.encode_uchar4(vector_offset,
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(detail_in),
compiler.stack_assign_if_linked(distortion_in)),
profile);
compiler.add_node(__float_as_int(scale),
__float_as_int(detail),
__float_as_int(distortion),
__float_as_int(detail_scale));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}

The values are passed directly with additional add_node calls. I’m not sure where this data ends up as it doesn’t seem to be referenced in the shader?

ccl_device void svm_node_tex_wave(
KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
uint4 node2 = read_node(kg, offset);
uint type;
uint co_offset, scale_offset, detail_offset, dscale_offset, distortion_offset, color_offset,
fac_offset;
svm_unpack_node_uchar4(node.y, &type, &color_offset, &fac_offset, &dscale_offset);
svm_unpack_node_uchar4(node.z, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
float3 co = stack_load_float3(stack, co_offset);
float scale = stack_load_float_default(stack, scale_offset, node2.x);
float detail = stack_load_float_default(stack, detail_offset, node2.y);
float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
float dscale = stack_load_float_default(stack, dscale_offset, node2.w);

float f = svm_wave(
(NodeWaveType)type, (NodeWaveProfile)node.w, co * scale, detail, distortion, dscale);
if (stack_valid(fac_offset))
stack_store_float(stack, fac_offset, f);
if (stack_valid(color_offset))
stack_store_float3(stack, color_offset, make_float3(f, f, f));
}

If anyone could take the time to explain, or point me towards a resource or part of the code which explains what is happening here I would really appreciate it.

1 Like

Including the values directly is an optimization, if not another SVM instruction has to be generated which writes the value to the stack.

stack_load_float_default is the function that will either read from the stack at a specified offset or use the value passed to it as the last argument.

Is there a reason there is not an equivalent stack_load_float3_default?

No particular reason, there was no need for it yet I think. It can be added.