Perform sampling before branching to discard

This two fragment shaders that exhibit undefined behavior. In GLSL,
it is undefined to use implicit or explicit derivatives in
non-uniform control flow [1]. The SPIR-V produced by glslang contained
similar undefined behavior, which results in incorrect codegen
with the amdvlk's LLPC shader compiler, and produces visually
incorrect image.

This PR fixes this issue by hoisting the sampling so that it's
executed before discarding. It's a simple fix and may not be
the optimial way to resolve this issue.

[1]
https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
p. 137.
This commit is contained in:
Jakub Kuderski 2020-02-13 00:58:44 -05:00 committed by Jakub Kuderski
parent 3977935d94
commit 8982f8f2ec
4 changed files with 11 additions and 3 deletions

View file

@ -123,17 +123,21 @@ void main(void)
break;
}
// Perform sampling before (potentially) discarding.
// This is to avoid implicit derivatives in non-uniform control flow.
vec3 normalHeightMapLod = textureLod(sNormalHeightMap, uv, 0.0).rgb;
vec3 color = texture(sColorMap, uv).rgb;
// Discard fragments at texture border
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
discard;
}
vec3 N = normalize(textureLod(sNormalHeightMap, uv, 0.0).rgb * 2.0 - 1.0);
vec3 N = normalize(normalHeightMapLod * 2.0 - 1.0);
vec3 L = normalize(inTangentLightPos - inTangentFragPos);
vec3 R = reflect(-L, N);
vec3 H = normalize(L + V);
vec3 color = texture(sColorMap, uv).rgb;
vec3 ambient = 0.2 * color;
vec3 diffuse = max(dot(L, N), 0.0) * color;
vec3 specular = vec3(0.15) * pow(max(dot(N, H), 0.0), 32.0);

View file

@ -21,10 +21,14 @@ void main ()
{
// Sample depth from deferred depth buffer and discard if obscured
float depth = subpassLoad(samplerPositionDepth).a;
// Save the sampled texture color before discarding.
// This is to avoid implicit derivatives in non-uniform control flow.
vec4 sampledColor = texture(samplerTexture, inUV);
if ((depth != 0.0) && (linearDepth(gl_FragCoord.z) > depth))
{
discard;
};
outColor = texture(samplerTexture, inUV);
outColor = sampledColor;
}