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
This commit is contained in:
Clément Foucault
2025-09-16 16:44:01 +02:00
committed by Clément Foucault
parent 3995359236
commit ecc495ac39
4 changed files with 45 additions and 0 deletions

View File

@@ -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;

View File

@@ -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()
/** \} */

View File

@@ -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);
}

View File

@@ -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);