Metal: Ensure explicit return after discard to eliminate differences in behaviour between GPUs.

Discard is not always treated as an explicit return and flow control can continue for required derivative calculations. This behaviour is different in Metal vs OpenGL. Adding return after discards ensures consistency in expectation as behaviour is well-defined.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D17199
This commit is contained in:
Jason Fielder 2023-02-07 00:57:54 +01:00 committed by Clément Foucault
parent f152159101
commit 8703db393b
15 changed files with 26 additions and 3 deletions

@ -41,6 +41,7 @@ void main(void)
/* Outside of bokeh shape. Try to avoid overloading ROPs. */
if (max_v4(shapes) == 0.0) {
discard;
return;
}
if (!no_scatter_occlusion) {

@ -226,6 +226,7 @@ void main()
if (depth == 1.0) {
discard;
return;
}
ivec2 texel = ivec2(gl_FragCoord.xy);
@ -235,6 +236,7 @@ void main()
if (max_v3(brdf) <= 0.0) {
discard;
return;
}
FragDepth = depth;

@ -9,6 +9,7 @@ void main()
/* Discard outside the circle. */
if (dist_sqr > 1.0) {
discard;
return;
}
vec3 view_nor = vec3(quadCoord, sqrt(max(0.0, 1.0 - dist_sqr)));

@ -8,6 +8,7 @@ void main()
/* Discard outside the circle. */
if (dist_sqr > 1.0) {
discard;
return;
}
vec3 view_nor = vec3(quadCoord, sqrt(max(0.0, 1.0 - dist_sqr)));

@ -37,6 +37,7 @@ void main()
/* Outside of bokeh shape. Try to avoid overloading ROPs. */
if (max_v4(shapes) == 0.0) {
discard;
return;
}
if (!no_scatter_occlusion) {

@ -80,6 +80,7 @@ void main()
float transparency = avg(g_transmittance);
if (transparency > random_threshold) {
discard;
return;
}
#endif

@ -10,6 +10,7 @@ void main()
/* Discard if there is no edge. */
if (dot(out_edges, float2(1.0, 1.0)) == 0.0) {
discard;
return;
}
#elif SMAA_STAGE == 1

@ -104,6 +104,7 @@ void main()
if (fragColor.a < 0.001) {
discard;
return;
}
}
@ -114,6 +115,7 @@ void main()
float scene_depth = texture(gpSceneDepthTexture, uvs).r;
if (gl_FragCoord.z > scene_depth) {
discard;
return;
}
/* FIXME(fclem): Grrr. This is bad for performance but it's the easiest way to not get
@ -121,6 +123,7 @@ void main()
float mask = texture(gpMaskTexture, uvs).r;
if (mask < 0.001) {
discard;
return;
}
/* We override the fragment depth using the fragment shader to ensure a constant value.

@ -15,6 +15,7 @@ void main()
float depth = texelFetch(depth_texture, uvs_clamped, 0).r;
if (depth == 1.0) {
discard;
return;
}
vec4 tex_color = texelFetch(imageTexture, uvs_clamped - offset, 0);

@ -18,6 +18,7 @@ void main()
gp_interp.thickness.x,
gp_interp.hardness) < 0.001) {
discard;
return;
}
if (!gpStrokeOrder3d) {

@ -8,6 +8,7 @@ void main()
if (dist > 0.5) {
discard;
return;
}
/* Nice sphere falloff. */
float intensity = sqrt(1.0 - dist * 2.0) * 0.5 + 0.5;

@ -8,6 +8,7 @@ void main()
/* Round point with jaggy edges. */
if (dist_squared > rad_squared) {
discard;
return;
}
#if defined(VERT)

@ -7,6 +7,7 @@ void main()
* If we could get rid of it would be nice because of performance drain of discard. */
if (edgeStart.r == -1.0) {
discard;
return;
}
#ifndef SELECT_EDGES

@ -9,6 +9,7 @@ void main()
/* Discard if there is no edge. */
if (dot(out_edges, float2(1.0, 1.0)) == 0.0) {
discard;
return;
}
#elif SMAA_STAGE == 1

@ -777,8 +777,10 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
# ifndef SMAA_NO_DISCARD
# ifdef GPU_FRAGMENT_SHADER
// Then discard if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0)
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
discard;
return float2(0.0, 0.0);
}
# endif
# endif
@ -847,8 +849,10 @@ float2 SMAAColorEdgeDetectionPS(float2 texcoord,
# ifndef SMAA_NO_DISCARD
# ifdef GPU_FRAGMENT_SHADER
// Then discard if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0)
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
discard;
return float2(0.0, 0.0);
}
# endif
# endif
@ -895,8 +899,10 @@ float2 SMAADepthEdgeDetectionPS(float2 texcoord, float4 offset[3], SMAATexture2D
float2 edges = step(SMAA_DEPTH_THRESHOLD, delta);
# ifdef GPU_FRAGMENT_SHADER
if (dot(edges, float2(1.0, 1.0)) == 0.0)
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
discard;
return float2(0.0, 0.0);
}
# endif
return edges;