-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Primitive clipping at the rasterization stage is inconsistent between APIs #3638
Comments
That's a case I didn't think to test :(. It's surprising to me that the fragment output could affect clipping. I suppose reading the Vulkan spec defined my mental model of how z clipping works - it specifies it as a primitive geometry clip, afaik never a depth test / fragment discard. It's likely I misinterpreted some test results as clips when really I was seeing discards. In Metal it sounds like it is a clip if you don't write frag_depth, but a discard if you do, which is reasonable since writing frag_depth has special consequences already due to the early depth test. That said, I do wonder if this Metal behavior is different between Apple GPUs and Intel/AMD/NVIDIA GPUs (since they implement D3D12). |
I wrote the issue in a bit of a confused way but fragment output doesn't affect clipping. It is that we need to clamp it to the viewport on Metal like we do on Vulkan. The way the investigation suggested to do that was to use |
Hm. I thought there must be some difference because the depth_clip_clamp tests I wrote passed on Metal but not on Vulkan. I don't remember whether I used the Intel or Apple GPU for that result. They're not passing for me now, on an Apple GPU, with Chrome Canary. OK, I think I understand the problem now. To restate, we thought MTLDepthClipModeClip kept clamping on (like D3D), but now you're seeing results that it doesn't (like unextended Vulkan, or OpenGL; this makes sense since Metal usually copies OpenGL semantics, and also because the naming of MTLDepthClipModeClip/Clamp strongly implies it). In your test case, MTLDepthClipModeClip doesn't work because we need clamping, and MTLDepthClipModeClamp doesn't work because we need clipping. I wonder if there was a driver bug when I was testing Metal's behavior. In any case, D3D still doesn't let us disable clamping, so I don't think we can change our API, unless we can think of a way to emulate it? (Immediate thought is to use ~infinite viewport z bounds, but I am pretty sure this messes up too many other things, if it's even possible.) |
Just checked: the existing depth_clip_clamp tests pass on Metal on both Intel and AMD GPUs. They fail on M1. |
Sigh, but thanks for doing that investigation! Clears things up a lot. |
Closing, since we agreed in the group that we'd just require clamping of frag_depth in Metal the same way we do for Vulkan. |
Looking to enable tests around depth clipping and clamping in Dawn, there seems to be yet another inconsistency between APIs.
Because the frag_depth should always be clamped to the viewport, then
@builtin(frag_depth)
implies thatMTLDepthClipMode.clamp
is used. @kainino0x previously made this great table, but experimental results show that Metal withMTLDepthClipMode.clamp
doesn't do clipping of the fragment at the rasterization stage if@builtin(frag_depth)
is used.More precisely, the following WGSL code with
MTLDepthClipMode.Clamp
(and trivially the pipeline from it) draws a point on Metal which prevents implementingunclippedDepth = false
withfrag_depth
like on the other APIs:The way to fix this inconsistency is to pass the viewport bounds to the shader and either:
MTLDepthClipMode.clamp
and discard at the start of the FS if the position is outside of the viewport.MTLDepthClipMode.clip
and clamp the resulting frag_depth. (what we opted to do for Vulkan).However since this changes what's in the investigation table, maybe we need to revisit the exact depth clipping behavior?
The text was updated successfully, but these errors were encountered: