Metal: re-enable fastmath (#8911)
This commit is contained in:
@@ -113,13 +113,7 @@ bool MetalShaderCompiler::isParallelShaderCompileSupported() const noexcept {
|
||||
case ShaderLanguage::MSL: {
|
||||
// By default, Metal uses the most recent language version.
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
|
||||
// Disable Fast Math optimizations.
|
||||
// This ensures that operations adhere to IEEE standards for floating-point
|
||||
// arithmetic, which is crucial for half precision floats in scenarios where fast
|
||||
// math optimizations lead to inaccuracies, such as in handling special values like
|
||||
// NaN or Infinity.
|
||||
options.fastMathEnabled = NO;
|
||||
options.fastMathEnabled = YES;
|
||||
|
||||
assert_invariant(source[source.size() - 1] == '\0');
|
||||
// the shader string is null terminated and the length includes the null character
|
||||
|
||||
@@ -3,22 +3,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @public-api */
|
||||
#define PI 3.14159265359
|
||||
#define PI 3.14159265359
|
||||
/** @public-api */
|
||||
#define HALF_PI 1.570796327
|
||||
#define HALF_PI 1.570796327
|
||||
|
||||
#define MEDIUMP_FLT_MAX 65504.0
|
||||
#define MEDIUMP_FLT_MIN 0.00006103515625
|
||||
#define MEDIUMP_FLT_MAX 65504.0
|
||||
#define MEDIUMP_FLT_MIN 0.00006103515625
|
||||
|
||||
#ifdef TARGET_MOBILE
|
||||
#define FLT_EPS MEDIUMP_FLT_MIN
|
||||
#define saturateMediump(x) min(x, MEDIUMP_FLT_MAX)
|
||||
#define FLT_EPS MEDIUMP_FLT_MIN
|
||||
#else
|
||||
#define FLT_EPS 1e-5
|
||||
#define saturateMediump(x) x
|
||||
#define FLT_EPS 1e-5
|
||||
#endif
|
||||
|
||||
#define saturate(x) clamp(x, 0.0, 1.0)
|
||||
#define saturate(x) clamp(x, 0.0, 1.0)
|
||||
|
||||
#ifdef TARGET_MOBILE
|
||||
#define PREVENT_DIV0(n, d, magic) ((n) / max(d, magic))
|
||||
#else
|
||||
#define PREVENT_DIV0(n, d, magic) ((n) / (d))
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Scalar operations
|
||||
|
||||
@@ -73,9 +73,9 @@ float D_GGX(float roughness, float NoH, const vec3 h) {
|
||||
#endif
|
||||
|
||||
float a = NoH * roughness;
|
||||
float k = roughness / (oneMinusNoHSquared + a * a);
|
||||
float d = k * k * (1.0 / PI);
|
||||
return saturateMediump(d);
|
||||
float k = min(roughness / (oneMinusNoHSquared + a * a), 453.5); // 453.5 prevents fp16 overflow
|
||||
float d = k * (k * (1.0 / PI));
|
||||
return d;
|
||||
}
|
||||
|
||||
float D_GGX_Anisotropic(float at, float ab, float ToH, float BoH, float NoH) {
|
||||
@@ -105,17 +105,18 @@ float V_SmithGGXCorrelated(float roughness, float NoV, float NoL) {
|
||||
// TODO: lambdaV can be pre-computed for all the lights, it should be moved out of this function
|
||||
float lambdaV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);
|
||||
float lambdaL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);
|
||||
float v = 0.5 / (lambdaV + lambdaL);
|
||||
// 0.0000077 = nextafter(0.5 / MEDIUMP_FLT_MAX, 1.0) in fp16, so we don't overflow
|
||||
float v = PREVENT_DIV0(0.5, lambdaV + lambdaL, 0.0000077);
|
||||
// a2=0 => v = 1 / 4*NoL*NoV => min=1/4, max=+inf
|
||||
// a2=1 => v = 1 / 2*(NoL+NoV) => min=1/4, max=+inf
|
||||
// clamp to the maximum value representable in mediump
|
||||
return saturateMediump(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
float V_SmithGGXCorrelated_Fast(float roughness, float NoV, float NoL) {
|
||||
// Hammon 2017, "PBR Diffuse Lighting for GGX+Smith Microsurfaces"
|
||||
float v = 0.5 / mix(2.0 * NoL * NoV, NoL + NoV, roughness);
|
||||
return saturateMediump(v);
|
||||
// 0.0000077 = nextafter(0.5 / MEDIUMP_FLT_MAX, 1.0) in fp16, so we don't overflow
|
||||
float v = PREVENT_DIV0(0.5, mix(2.0 * NoL * NoV, NoL + NoV, roughness), 0.0000077);
|
||||
return v;
|
||||
}
|
||||
|
||||
float V_SmithGGXCorrelated_Anisotropic(float at, float ab, float ToV, float BoV,
|
||||
@@ -124,18 +125,21 @@ float V_SmithGGXCorrelated_Anisotropic(float at, float ab, float ToV, float BoV,
|
||||
// TODO: lambdaV can be pre-computed for all the lights, it should be moved out of this function
|
||||
float lambdaV = NoL * length(vec3(at * ToV, ab * BoV, NoV));
|
||||
float lambdaL = NoV * length(vec3(at * ToL, ab * BoL, NoL));
|
||||
float v = 0.5 / (lambdaV + lambdaL);
|
||||
return saturateMediump(v);
|
||||
// 0.0000077 = nextafter(0.5 / MEDIUMP_FLT_MAX, 1.0) in fp16, so we don't overflow
|
||||
float v = PREVENT_DIV0(0.5, lambdaV + lambdaL, 0.0000077);
|
||||
return v;
|
||||
}
|
||||
|
||||
float V_Kelemen(float LoH) {
|
||||
// Kelemen 2001, "A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling"
|
||||
return saturateMediump(0.25 / (LoH * LoH));
|
||||
// 0.0000039 = nextafter(0.25 / MEDIUMP_FLT_MAX, 1.0) in fp16, so we don't overflow
|
||||
return PREVENT_DIV0(0.25, LoH * LoH, 0.0000039);
|
||||
}
|
||||
|
||||
float V_Neubelt(float NoV, float NoL) {
|
||||
// Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
|
||||
return saturateMediump(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));
|
||||
// 0.00001532 = nextafter(1.0 / MEDIUMP_FLT_MAX, 1.0) in fp16, so we don't overflow
|
||||
return PREVENT_DIV0(1.0, 4.0 * (NoL + NoV - NoL * NoV), 0.00001532);
|
||||
}
|
||||
|
||||
vec3 F_Schlick(const vec3 f0, float f90, float VoH) {
|
||||
|
||||
Reference in New Issue
Block a user