From 184345e885fb0cf3dcd2938d713d6cd26eae23d9 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Mon, 13 Feb 2023 15:47:21 +0000 Subject: [PATCH 1/3] Metal: Improve AMD EEVEE Performance Complex EEVEE nodegraphs, particularly those combining multiple principledBSDF shader nodes have a tendancy to require a large number of simultaneous live registers due to function call depth. In some instances, this causes substantial performance drop and corruption if the stack gets too large. To mitigate this, splitting calls to closure_eval such that only a single individual closure is evaluated in each call reduces the number of live registers required. This is preferred over using compound closure evaluation functions which require a large amount of in-flight data. Note that this is generally not more optimal, if the stack does not spill, as there is an increased instruction count. The specific trade-off depends on the exact architecture in question. Hence, this is limited to AMD GPUs. Authored by Apple: Michael Parkin-White Ref T96261 --- .../shaders/closure_eval_surface_lib.glsl | 56 +++++++++++++++++++ .../shaders/closure_eval_volume_lib.glsl | 4 ++ .../eevee/shaders/closure_type_lib.glsl | 1 + .../infos/engine_eevee_legacy_shared.h | 8 +++ .../shaders/eevee_nodetree_lib.glsl | 6 ++ 5 files changed, 75 insertions(+) diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl index ffca97b6b8f..4b3889ecc4f 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl @@ -119,6 +119,22 @@ Closure closure_eval(ClosureReflection reflection) return closure; } +CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDFAlways, Glossy) +Closure closure_eval_always(ClosureReflection reflection) +{ + /* Glue with the old system. */ + CLOSURE_VARS_DECLARE_1(Glossy); + + in_Glossy_0.N = reflection.N; + in_Glossy_0.roughness = reflection.roughness; + + CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy); + + Closure closure = CLOSURE_DEFAULT; + closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; + return closure; +} + CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction) Closure closure_eval(ClosureRefraction refraction) { @@ -155,6 +171,13 @@ Closure closure_eval(ClosureTransparency transparency) CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction) Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction) { + +#if defined(DO_SPLIT_CLOSURE_EVAL) + Closure closure = closure_eval(refraction); + Closure closure_reflection = closure_eval(reflection); + closure.radiance += closure_reflection.radiance; + return closure; +#else /* Glue with the old system. */ CLOSURE_VARS_DECLARE_2(Glossy, Refraction); @@ -172,12 +195,19 @@ Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction) closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; } return closure; +#endif } /* Dielectric BSDF */ CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy) Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection) { +#if defined(DO_SPLIT_CLOSURE_EVAL) + Closure closure = closure_eval(diffuse); + Closure closure_reflection = closure_eval(reflection); + closure.radiance += closure_reflection.radiance; + return closure; +#else /* Glue with the old system. */ CLOSURE_VARS_DECLARE_2(Diffuse, Glossy); @@ -198,6 +228,7 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection) closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; } return closure; +#endif } /* Specular BSDF */ @@ -206,6 +237,13 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection, ClosureReflection clearcoat) { +#if defined(DO_SPLIT_CLOSURE_EVAL) + Closure closure = closure_eval(diffuse); + Closure closure_reflection = closure_eval(reflection); + Closure closure_clearcoat = closure_eval_always(clearcoat); + closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance; + return closure; +#else /* Glue with the old system. */ CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy); @@ -229,6 +267,7 @@ Closure closure_eval(ClosureDiffuse diffuse, closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; } return closure; +#endif } /* Principled BSDF */ @@ -238,6 +277,15 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection clearcoat, ClosureRefraction refraction) { +#if defined(DO_SPLIT_CLOSURE_EVAL) + Closure closure = closure_eval(diffuse); + Closure closure_reflection = closure_eval(reflection); + Closure closure_clearcoat = closure_eval_always(clearcoat); + Closure closure_refraction = closure_eval(refraction); + closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance + + closure_refraction.radiance; + return closure; +#else /* Glue with the old system. */ CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction); @@ -263,11 +311,18 @@ Closure closure_eval(ClosureDiffuse diffuse, closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; } return closure; +#endif } CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy) Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat) { +#if defined(DO_SPLIT_CLOSURE_EVAL) + Closure closure = closure_eval(clearcoat); + Closure closure_reflection = closure_eval(reflection); + closure.radiance += closure_reflection.radiance; + return closure; +#else /* Glue with the old system. */ CLOSURE_VARS_DECLARE_2(Glossy, Glossy); @@ -284,6 +339,7 @@ Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat) closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; } return closure; +#endif } /* Not supported for surface shaders. */ diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl index 5e34d654cfd..0e9af344104 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl @@ -17,6 +17,10 @@ Closure closure_eval(ClosureReflection reflection) { return CLOSURE_DEFAULT; } +Closure closure_eval_always(ClosureReflection reflection) +{ + return CLOSURE_DEFAULT; +} Closure closure_eval(ClosureRefraction refraction) { return CLOSURE_DEFAULT; diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl index ceef35886ff..ca65a8d6985 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl @@ -53,6 +53,7 @@ vec3 coordinate_incoming(vec3 P); Closure closure_eval(ClosureDiffuse diffuse); Closure closure_eval(ClosureTranslucent translucent); Closure closure_eval(ClosureReflection reflection); +Closure closure_eval_always(ClosureReflection reflection); Closure closure_eval(ClosureRefraction refraction); Closure closure_eval(ClosureEmission emission); Closure closure_eval(ClosureTransparency transparency); diff --git a/source/blender/draw/engines/eevee/shaders/infos/engine_eevee_legacy_shared.h b/source/blender/draw/engines/eevee/shaders/infos/engine_eevee_legacy_shared.h index 1170078d9a5..cb06ee74ec7 100644 --- a/source/blender/draw/engines/eevee/shaders/infos/engine_eevee_legacy_shared.h +++ b/source/blender/draw/engines/eevee/shaders/infos/engine_eevee_legacy_shared.h @@ -16,6 +16,14 @@ typedef struct CommonUniformBlock CommonUniformBlock; # endif #endif +/* NOTE: AMD-based macOS platforms experience performance and correctness issues with EEVEE + * material closure evaluation. Using singular closure evaluation, rather than the compound + * function calls reduces register overflow, by limiting the simultaneous number of live + * registers used by the virtual GPU function stack. */ +#if (defined(GPU_METAL) && defined(GPU_ATI)) +# define DO_SPLIT_CLOSURE_EVAL 1 +#endif + struct CommonUniformBlock { mat4 pastViewProjectionMatrix; vec4 hizUvScale; /* To correct mip level texel misalignment */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index 965780d9bcf..83729859c42 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -92,6 +92,12 @@ Closure closure_eval(ClosureReflection reflection) return Closure(0); } +Closure closure_eval_always(ClosureReflection reflection) +{ + SELECT_CLOSURE(g_reflection_data, g_reflection_rand, reflection); + return Closure(0); +} + Closure closure_eval(ClosureRefraction refraction) { SELECT_CLOSURE(g_refraction_data, g_refraction_rand, refraction); -- 2.30.2 From dc42ce02737494a34b1dfc738dae994e4520041e Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Wed, 15 Feb 2023 17:10:46 +0000 Subject: [PATCH 2/3] Refactor closure_eval to allow skipping SSR. --- .../shaders/closure_eval_surface_lib.glsl | 28 ++++++++----------- .../shaders/closure_eval_volume_lib.glsl | 4 --- .../eevee/shaders/closure_type_lib.glsl | 2 +- .../shaders/eevee_nodetree_lib.glsl | 6 ---- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl index 4b3889ecc4f..19958505f95 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl @@ -102,7 +102,7 @@ Closure closure_eval(ClosureTranslucent translucent) } CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy) -Closure closure_eval(ClosureReflection reflection) +Closure closure_eval(ClosureReflection reflection, const bool do_output_ssr) { /* Glue with the old system. */ CLOSURE_VARS_DECLARE_1(Glossy); @@ -113,26 +113,20 @@ Closure closure_eval(ClosureReflection reflection) CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy); Closure closure = CLOSURE_DEFAULT; - if (!output_ssr(reflection)) { + + bool output_radiance = true; + if(do_output_ssr){ + output_radiance = !output_ssr(reflection); + } + if (output_radiance) { closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; } return closure; } -CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDFAlways, Glossy) -Closure closure_eval_always(ClosureReflection reflection) +Closure closure_eval(ClosureReflection reflection) { - /* Glue with the old system. */ - CLOSURE_VARS_DECLARE_1(Glossy); - - in_Glossy_0.N = reflection.N; - in_Glossy_0.roughness = reflection.roughness; - - CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy); - - Closure closure = CLOSURE_DEFAULT; - closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; - return closure; + return closure_eval(reflection, true); } CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction) @@ -240,7 +234,7 @@ Closure closure_eval(ClosureDiffuse diffuse, #if defined(DO_SPLIT_CLOSURE_EVAL) Closure closure = closure_eval(diffuse); Closure closure_reflection = closure_eval(reflection); - Closure closure_clearcoat = closure_eval_always(clearcoat); + Closure closure_clearcoat = closure_eval(clearcoat, false); closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance; return closure; #else @@ -280,7 +274,7 @@ Closure closure_eval(ClosureDiffuse diffuse, #if defined(DO_SPLIT_CLOSURE_EVAL) Closure closure = closure_eval(diffuse); Closure closure_reflection = closure_eval(reflection); - Closure closure_clearcoat = closure_eval_always(clearcoat); + Closure closure_clearcoat = closure_eval(clearcoat, false); Closure closure_refraction = closure_eval(refraction); closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance + closure_refraction.radiance; diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl index 0e9af344104..5e34d654cfd 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl @@ -17,10 +17,6 @@ Closure closure_eval(ClosureReflection reflection) { return CLOSURE_DEFAULT; } -Closure closure_eval_always(ClosureReflection reflection) -{ - return CLOSURE_DEFAULT; -} Closure closure_eval(ClosureRefraction refraction) { return CLOSURE_DEFAULT; diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl index ca65a8d6985..91c6f3e4fdf 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl @@ -53,7 +53,7 @@ vec3 coordinate_incoming(vec3 P); Closure closure_eval(ClosureDiffuse diffuse); Closure closure_eval(ClosureTranslucent translucent); Closure closure_eval(ClosureReflection reflection); -Closure closure_eval_always(ClosureReflection reflection); +Closure closure_eval(ClosureReflection reflection, const bool do_output_ssr); Closure closure_eval(ClosureRefraction refraction); Closure closure_eval(ClosureEmission emission); Closure closure_eval(ClosureTransparency transparency); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index 83729859c42..965780d9bcf 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -92,12 +92,6 @@ Closure closure_eval(ClosureReflection reflection) return Closure(0); } -Closure closure_eval_always(ClosureReflection reflection) -{ - SELECT_CLOSURE(g_reflection_data, g_reflection_rand, reflection); - return Closure(0); -} - Closure closure_eval(ClosureRefraction refraction) { SELECT_CLOSURE(g_refraction_data, g_refraction_rand, refraction); -- 2.30.2 From 17bb51b413f68e46947405690e14c49bffd01bc9 Mon Sep 17 00:00:00 2001 From: Michael Parkin-White Date: Thu, 16 Feb 2023 10:41:46 +0000 Subject: [PATCH 3/3] Remove prototype function and ensure formatting. --- .../draw/engines/eevee/shaders/closure_eval_surface_lib.glsl | 2 +- source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl index 19958505f95..8bfc231f947 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl @@ -115,7 +115,7 @@ Closure closure_eval(ClosureReflection reflection, const bool do_output_ssr) Closure closure = CLOSURE_DEFAULT; bool output_radiance = true; - if(do_output_ssr){ + if (do_output_ssr) { output_radiance = !output_ssr(reflection); } if (output_radiance) { diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl index 91c6f3e4fdf..ceef35886ff 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl @@ -53,7 +53,6 @@ vec3 coordinate_incoming(vec3 P); Closure closure_eval(ClosureDiffuse diffuse); Closure closure_eval(ClosureTranslucent translucent); Closure closure_eval(ClosureReflection reflection); -Closure closure_eval(ClosureReflection reflection, const bool do_output_ssr); Closure closure_eval(ClosureRefraction refraction); Closure closure_eval(ClosureEmission emission); Closure closure_eval(ClosureTransparency transparency); -- 2.30.2