Metal: Improve AMD EEVEE Performance #104743

Closed
Jason Fielder wants to merge 3 commits from Jason-Fielder/blender:MetalAMDPerformanceEEVEE_2 into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
2 changed files with 60 additions and 2 deletions

View File

@ -102,7 +102,7 @@ Closure closure_eval(ClosureTranslucent translucent)
} }
CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy) 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. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_1(Glossy); CLOSURE_VARS_DECLARE_1(Glossy);
@ -113,12 +113,22 @@ Closure closure_eval(ClosureReflection reflection)
CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy); CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy);
Closure closure = CLOSURE_DEFAULT; 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; closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
} }

Change closure_eval_always to be an overload of closure_eval with an optional const bool parameter for ssr output: closure_eval(ClosureReflection reflection, const bool do_ssr_output)

Change `closure_eval_always` to be an overload of `closure_eval` with an optional const bool parameter for ssr output: `closure_eval(ClosureReflection reflection, const bool do_ssr_output)`
return closure; return closure;
} }
Closure closure_eval(ClosureReflection reflection)
{
return closure_eval(reflection, true);
}
CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction) CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction)
Closure closure_eval(ClosureRefraction refraction) Closure closure_eval(ClosureRefraction refraction)
{ {
@ -155,6 +165,13 @@ Closure closure_eval(ClosureTransparency transparency)
CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction) CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction)
Closure closure_eval(ClosureReflection reflection, ClosureRefraction 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. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_2(Glossy, Refraction); CLOSURE_VARS_DECLARE_2(Glossy, Refraction);
@ -172,12 +189,19 @@ Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Dielectric BSDF */ /* Dielectric BSDF */
CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy) CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy)
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection) 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. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_2(Diffuse, Glossy); CLOSURE_VARS_DECLARE_2(Diffuse, Glossy);
@ -198,6 +222,7 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Specular BSDF */ /* Specular BSDF */
@ -206,6 +231,13 @@ Closure closure_eval(ClosureDiffuse diffuse,
ClosureReflection reflection, ClosureReflection reflection,
ClosureReflection clearcoat) ClosureReflection clearcoat)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(diffuse);
Closure closure_reflection = closure_eval(reflection);
Closure closure_clearcoat = closure_eval(clearcoat, false);
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance;
return closure;
#else
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy); CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy);
@ -229,6 +261,7 @@ Closure closure_eval(ClosureDiffuse diffuse,
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Principled BSDF */ /* Principled BSDF */
@ -238,6 +271,15 @@ Closure closure_eval(ClosureDiffuse diffuse,
ClosureReflection clearcoat, ClosureReflection clearcoat,
ClosureRefraction refraction) ClosureRefraction refraction)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(diffuse);
Closure closure_reflection = closure_eval(reflection);
Closure closure_clearcoat = closure_eval(clearcoat, false);
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. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction); CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
@ -263,11 +305,18 @@ Closure closure_eval(ClosureDiffuse diffuse,
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy) CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy)
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat) 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. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_2(Glossy, Glossy); CLOSURE_VARS_DECLARE_2(Glossy, Glossy);
@ -284,6 +333,7 @@ Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Not supported for surface shaders. */ /* Not supported for surface shaders. */

View File

@ -16,6 +16,14 @@ typedef struct CommonUniformBlock CommonUniformBlock;
# endif # endif
#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 { struct CommonUniformBlock {
mat4 pastViewProjectionMatrix; mat4 pastViewProjectionMatrix;
vec4 hizUvScale; /* To correct mip level texel misalignment */ vec4 hizUvScale; /* To correct mip level texel misalignment */