Cycles: Improve parameter packing for BSDFs and emission

This replaces `stack_assign` with `stack_assign_if_linked`, which should save a few SVM nodes for constant parameters.

Running benchmarks (all scenes in the benchmark repo, 3 runs, median value for each) shows 1.0% improvement on CPU and 1.5% on OptiX. Not huge, but fairly (all between -0.2% and 3.0%).

Pull Request: https://projects.blender.org/blender/blender/pulls/143404
This commit is contained in:
Lukas Stockner
2025-08-04 15:19:40 +02:00
parent 2da5969fdc
commit 3107d1f962
2 changed files with 51 additions and 45 deletions

View File

@@ -531,31 +531,31 @@ ccl_device
uint rotation_offset;
uint tangent_offset;
svm_unpack_node_uchar4(
node.z, &base_ior_offset, &edge_tint_k_offset, &rotation_offset, &tangent_offset);
data_node.y, &base_ior_offset, &edge_tint_k_offset, &rotation_offset, &tangent_offset);
const float3 valid_reflection_N = maybe_ensure_valid_specular_reflection(sd, N);
float3 T = stack_load_float3(stack, tangent_offset);
const float anisotropy = saturatef(param2);
const float roughness = saturatef(param1);
float alpha_x = sqr(roughness);
float alpha_y = sqr(roughness);
if (anisotropy > 0.0f) {
bsdf->alpha_x = sqr(roughness);
bsdf->alpha_y = sqr(roughness);
if (anisotropy > 0.0f && tangent_offset != SVM_STACK_INVALID) {
bsdf->T = stack_load_float3(stack, tangent_offset);
const float aspect = sqrtf(1.0f - anisotropy * 0.9f);
alpha_x /= aspect;
alpha_y *= aspect;
bsdf->alpha_x /= aspect;
bsdf->alpha_y *= aspect;
const float anisotropic_rotation = stack_load_float(stack, rotation_offset);
if (anisotropic_rotation != 0.0f) {
T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
bsdf->T = rotate_around_axis(bsdf->T, N, anisotropic_rotation * M_2PI_F);
}
}
else {
bsdf->T = zero_float3();
}
bsdf->N = valid_reflection_N;
bsdf->ior = 1.0f;
bsdf->T = T;
bsdf->alpha_x = alpha_x;
bsdf->alpha_y = alpha_y;
const ClosureType distribution = (ClosureType)node.w;
const ClosureType distribution = (ClosureType)data_node.z;
/* Setup BSDF */
if (distribution == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) {
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
@@ -1458,7 +1458,9 @@ ccl_device_noinline void svm_node_emission_weight(ccl_private float *stack,
const uint color_offset = node.y;
const uint strength_offset = node.z;
const float strength = stack_load_float(stack, strength_offset);
const float strength = (stack_valid(strength_offset)) ?
stack_load_float(stack, strength_offset) :
__uint_as_float(node.w);
*closure_weight = rgb_to_spectrum(stack_load_float3(stack, color_offset)) * strength;
}

View File

@@ -2089,14 +2089,14 @@ void BsdfNode::compile(SVMCompiler &compiler,
const int data_z_offset = (data_z) ? compiler.stack_assign(data_z) : SVM_STACK_INVALID;
const int data_w_offset = (data_w) ? compiler.stack_assign(data_w) : SVM_STACK_INVALID;
compiler.add_node(
NODE_CLOSURE_BSDF,
compiler.encode_uchar4(closure,
(bsdf_y) ? compiler.stack_assign(bsdf_y) : SVM_STACK_INVALID,
(bsdf_z) ? compiler.stack_assign(bsdf_z) : SVM_STACK_INVALID,
compiler.closure_mix_weight_offset()),
__float_as_int((bsdf_y) ? get_float(bsdf_y->socket_type) : 0.0f),
__float_as_int((bsdf_z) ? get_float(bsdf_z->socket_type) : 0.0f));
compiler.add_node(NODE_CLOSURE_BSDF,
compiler.encode_uchar4(
closure,
(bsdf_y) ? compiler.stack_assign_if_linked(bsdf_y) : SVM_STACK_INVALID,
(bsdf_z) ? compiler.stack_assign_if_linked(bsdf_z) : SVM_STACK_INVALID,
compiler.closure_mix_weight_offset()),
__float_as_int((bsdf_y) ? get_float(bsdf_y->socket_type) : 0.0f),
__float_as_int((bsdf_z) ? get_float(bsdf_z->socket_type) : 0.0f));
compiler.add_node(normal_offset, data_y_offset, data_z_offset, data_w_offset);
}
@@ -2187,36 +2187,32 @@ void MetallicBsdfNode::compile(SVMCompiler &compiler)
{
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, one_float3());
ShaderInput *base_color_in = input("Base Color");
ShaderInput *edge_tint_in = input("Edge Tint");
ShaderInput *ior_in = input("IOR");
ShaderInput *k_in = input("Extinction");
const int base_color_ior_offset = fresnel_type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR ?
compiler.stack_assign(ior_in) :
compiler.stack_assign(base_color_in);
compiler.stack_assign(input("IOR")) :
compiler.stack_assign(input("Base Color"));
const int edge_tint_k_offset = fresnel_type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR ?
compiler.stack_assign(k_in) :
compiler.stack_assign(edge_tint_in);
compiler.stack_assign(input("Extinction")) :
compiler.stack_assign(input("Edge Tint"));
ShaderInput *anisotropy_in = input("Anisotropy");
ShaderInput *rotation_in = input("Rotation");
ShaderInput *roughness_in = input("Roughness");
ShaderInput *tangent_in = input("Tangent");
ShaderInput *anisotropy_in = input("Anisotropy");
const int normal_offset = compiler.stack_assign_if_linked(input("Normal"));
const int tangent_offset = compiler.stack_assign_if_linked(input("Tangent"));
const int rotation_offset = compiler.stack_assign(input("Rotation"));
compiler.add_node(NODE_CLOSURE_BSDF,
compiler.encode_uchar4(fresnel_type,
compiler.stack_assign(roughness_in),
compiler.stack_assign(anisotropy_in),
compiler.stack_assign_if_linked(roughness_in),
compiler.stack_assign_if_linked(anisotropy_in),
compiler.closure_mix_weight_offset()),
compiler.encode_uchar4(base_color_ior_offset,
edge_tint_k_offset,
compiler.stack_assign(rotation_in),
compiler.stack_assign(tangent_in)),
distribution);
compiler.add_node(normal_offset);
__float_as_int(get_float(roughness_in->socket_type)),
__float_as_int(get_float(anisotropy_in->socket_type)));
compiler.add_node(
normal_offset,
compiler.encode_uchar4(
base_color_ior_offset, edge_tint_k_offset, rotation_offset, tangent_offset),
distribution);
}
void MetallicBsdfNode::compile(OSLCompiler &compiler)
@@ -2914,9 +2910,13 @@ void EmissionNode::compile(SVMCompiler &compiler)
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
const int strength_offset = compiler.stack_assign_if_linked(strength_in);
if (color_in->link || strength_in->link) {
compiler.add_node(
NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
compiler.add_node(NODE_EMISSION_WEIGHT,
compiler.stack_assign(color_in),
strength_offset,
__float_as_int(get_float(strength_in->socket_type)));
}
else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
@@ -2962,9 +2962,13 @@ void BackgroundNode::compile(SVMCompiler &compiler)
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
const int strength_offset = compiler.stack_assign_if_linked(strength_in);
if (color_in->link || strength_in->link) {
compiler.add_node(
NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
compiler.add_node(NODE_EMISSION_WEIGHT,
compiler.stack_assign(color_in),
strength_offset,
__float_as_int(get_float(strength_in->socket_type)));
}
else {
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);