From 3107d1f962a3ffc8d0c74cd9da7448d900c1e4cb Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Mon, 4 Aug 2025 15:19:40 +0200 Subject: [PATCH] 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 --- intern/cycles/kernel/svm/closure.h | 28 ++++++------ intern/cycles/scene/shader_nodes.cpp | 68 +++++++++++++++------------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index f2c62dcaf8d..9656005b182 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -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; } diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index 516e5ff6338..87c6e57a74c 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -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);