From 8077384e3a2fd3d90ef64f3e4e9f568fad979da8 Mon Sep 17 00:00:00 2001 From: Michael Jones Date: Fri, 18 Jul 2025 11:18:43 +0200 Subject: [PATCH] Cycles: Improve Metal kernel specialisation This improves the existing scene specialisation mechanism by replacing "kernel_data.kernel_features" with a function constant. It doesn't cause any additional compilation requests, but allows the backend compiler to eliminate more dead code. An additional compiler hint is provided for dead-stripping "volume_stack_enter_exit" which results in slightly faster rendering of non-volumetric scenes. Pull Request: https://projects.blender.org/blender/blender/pulls/142235 --- intern/cycles/device/metal/device_impl.mm | 4 ++++ intern/cycles/device/metal/kernel.mm | 4 ++++ intern/cycles/kernel/device/metal/function_constants.h | 4 ++++ intern/cycles/kernel/integrator/volume_stack.h | 9 +++++++++ 4 files changed, 21 insertions(+) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 218183a0af4..e7f9151d952 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -309,6 +309,10 @@ string MetalDevice::preprocess_source(MetalPipelineType pso_type, # undef KERNEL_STRUCT_MEMBER_DONT_SPECIALIZE # undef KERNEL_STRUCT_BEGIN + /* Replace "kernel_data.kernel_features" memory fetches with a function constant. */ + string_replace_same_length( + *source, "kernel_data.kernel_features", "kernel_data_kernel_features"); + metal_printf("KernelData patching took %.1f ms", (time_dt() - starttime) * 1000.0); } diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm index 79e90526a27..64ddf316d6a 100644 --- a/intern/cycles/device/metal/kernel.mm +++ b/intern/cycles/device/metal/kernel.mm @@ -461,6 +461,10 @@ static MTLFunctionConstantValues *GetConstantValues(const KernelData *data = nul # include "kernel/data_template.h" + [constant_values setConstantValue:&data->kernel_features + type:MTLDataTypeInt + atIndex:KernelData_kernel_features]; + return constant_values; } diff --git a/intern/cycles/kernel/device/metal/function_constants.h b/intern/cycles/kernel/device/metal/function_constants.h index 17fb034300d..4fed68bd199 100644 --- a/intern/cycles/kernel/device/metal/function_constants.h +++ b/intern/cycles/kernel/device/metal/function_constants.h @@ -6,6 +6,8 @@ enum { Kernel_DummyConstant, #define KERNEL_STRUCT_MEMBER(parent, type, name) KernelData_##parent##_##name, #include "kernel/data_template.h" + + KernelData_kernel_features }; #ifdef __KERNEL_METAL__ @@ -13,4 +15,6 @@ enum { constant type kernel_data_##parent##_##name \ [[function_constant(KernelData_##parent##_##name)]]; # include "kernel/data_template.h" + +constant int kernel_data_kernel_features [[function_constant(KernelData_kernel_features)]]; #endif diff --git a/intern/cycles/kernel/integrator/volume_stack.h b/intern/cycles/kernel/integrator/volume_stack.h index 95f84be385f..094a38caaea 100644 --- a/intern/cycles/kernel/integrator/volume_stack.h +++ b/intern/cycles/kernel/integrator/volume_stack.h @@ -27,6 +27,15 @@ ccl_device void volume_stack_enter_exit(KernelGlobals kg, StackReadOp stack_read, StackWriteOp stack_write) { +# ifdef __KERNEL_USE_DATA_CONSTANTS__ + /* If we're using data constants, this fetch disappears. + * On Apple GPUs, scenes without volumetric features can render 1 or 2% faster by dead-stripping + * this function. */ + if (!(kernel_data.kernel_features & KERNEL_FEATURE_VOLUME)) { + return; + } +# endif + /* todo: we should have some way for objects to indicate if they want the * world shader to work inside them. excluding it by default is problematic * because non-volume objects can't be assumed to be closed manifolds */