From ecc495ac39b9fbfdfeaf1a438d4e6f6c88dcf166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 16 Sep 2025 16:44:01 +0200 Subject: [PATCH] EEVEE: Optimize Principled BSDF compilation time This removes unused closure branches in the principled BSDF code using the Material flags. On top of this, use constants for weights to use compiler dead code eliminitation for unused branches when there is different variants of the principled BSDF node used. Finally, remove Gbuffer packing cases that are not present inside the nodetree. Testing with the same setup as #145347: | | main (ms) | PR (ms) | Delta (ms) | | -------- | ----------- | ------------ |------------ | | Nvidia | 174 | 132 (1.31x) | 42 | | Mesa AMD | 191 | 170 (1.12x) | 21 | Barbershop compilation time is almost equal because it is not using the principled BSDF. Rel #145347 Pull Request: https://projects.blender.org/blender/blender/pulls/146324 --- .../eevee/shaders/eevee_gbuffer_write_lib.glsl | 15 +++++++++++++++ .../eevee/shaders/infos/eevee_common_info.hh | 4 ++++ .../material/gpu_shader_material_principled.glsl | 10 ++++++++++ .../shader/nodes/node_shader_bsdf_principled.cc | 16 ++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_write_lib.glsl b/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_write_lib.glsl index 38764557316..f542876158e 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_write_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_write_lib.glsl @@ -24,6 +24,21 @@ #include "eevee_gbuffer_lib.glsl" +/* Allows to reduce shader complexity and compilation time. + * Prefer removing the defines to let the loading lib have all cases by default. */ +#ifndef MAT_REFLECTION +# undef GBUFFER_HAS_REFLECTION +#endif +#ifndef MAT_REFRACTION +# undef GBUFFER_HAS_REFRACTION +#endif +#ifndef MAT_SUBSURFACE +# undef GBUFFER_HAS_SUBSURFACE +#endif +#ifndef MAT_TRANSLUCENT +# undef GBUFFER_HAS_TRANSLUCENT +#endif + namespace gbuffer { using ClosurePacking = gbuffer::ClosurePacking; diff --git a/source/blender/draw/engines/eevee/shaders/infos/eevee_common_info.hh b/source/blender/draw/engines/eevee/shaders/infos/eevee_common_info.hh index 26ee433804f..c67e83fd39c 100644 --- a/source/blender/draw/engines/eevee/shaders/infos/eevee_common_info.hh +++ b/source/blender/draw/engines/eevee/shaders/infos/eevee_common_info.hh @@ -164,6 +164,10 @@ GPU_SHADER_CREATE_END() GPU_SHADER_CREATE_INFO(eevee_tests_data) TYPEDEF_SOURCE("eevee_defines.hh") +DEFINE("MAT_REFLECTION") +DEFINE("MAT_REFRACTION") +DEFINE("MAT_SUBSURFACE") +DEFINE("MAT_TRANSLUCENT") GPU_SHADER_CREATE_END() /** \} */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 76d15591c3f..e96b326b84c 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -114,6 +114,7 @@ void node_bsdf_principled(float4 base_color, weight *= max((1.0f - math_reduce_max(sheen_color)), 0.0f); } +#ifdef MAT_CLEARCOAT /* Second layer: Coat */ if (coat_weight > 0.0f) { float coat_NV = dot(CN, V); @@ -140,6 +141,9 @@ void node_bsdf_principled(float4 base_color, else { coat_tint.rgb = float3(1.0f); } +#else + coat_tint.rgb = float3(1.0f); +#endif /* Emission component. * Attenuated by sheen and coat. @@ -164,6 +168,7 @@ void node_bsdf_principled(float4 base_color, weight *= max((1.0f - metallic), 0.0f); } +#ifdef MAT_REFRACTION /* Transmission component */ if (transmission_weight > 0.0f) { float3 F0 = float3(F0_from_ior(ior)) * reflection_tint; @@ -192,6 +197,7 @@ void node_bsdf_principled(float4 base_color, /* Attenuate lower layers */ weight *= max((1.0f - transmission_weight), 0.0f); } +#endif /* Specular component */ if (true) { @@ -224,6 +230,7 @@ void node_bsdf_principled(float4 base_color, weight *= max((1.0f - math_reduce_max(reflectance)), 0.0f); } +#ifdef MAT_SUBSURFACE /* Subsurface component */ if (subsurface_weight > 0.0f) { ClosureSubsurface sss_data; @@ -241,7 +248,9 @@ void node_bsdf_principled(float4 base_color, /* Attenuate lower layers */ weight *= max((1.0f - subsurface_weight), 0.0f); } +#endif +#ifdef MAT_DIFFUSE /* Diffuse component */ if (true) { ClosureDiffuse diffuse_data; @@ -253,6 +262,7 @@ void node_bsdf_principled(float4 base_color, diffuse_data.weight = 1.0f; closure_eval(diffuse_data); } +#endif result = Closure(0); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index 0037beec44d..f061ae8ce2e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -351,6 +351,22 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, flag |= GPU_MATFLAG_COAT; } + /* Make constant link for the cases we optimize. This allows the driver to constant fold. + * Note that doing so specialize the final tree topology, and thus the shader becomes less + * reusable. So to be used with care. + * Also note that we do note override existing links. This is because it would leak the current + * nodes otherwise. */ + const float zero = 0.0f; + if (!use_coat && in[SOCK_COAT_WEIGHT_ID].link == nullptr) { + in[SOCK_COAT_WEIGHT_ID].link = GPU_constant(&zero); + } + if (!use_subsurf && in[SOCK_SUBSURFACE_WEIGHT_ID].link == nullptr) { + in[SOCK_SUBSURFACE_WEIGHT_ID].link = GPU_constant(&zero); + } + if (!use_refract && in[SOCK_TRANSMISSION_WEIGHT_ID].link == nullptr) { + in[SOCK_TRANSMISSION_WEIGHT_ID].link = GPU_constant(&zero); + } + float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; GPU_material_flag_set(mat, flag);