Skip to content

Primitive clipping at the rasterization stage is inconsistent between APIs #3638

Closed
@Kangz

Description

@Kangz

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 that MTLDepthClipMode.clamp is used. @kainino0x previously made this great table, but experimental results show that Metal with MTLDepthClipMode.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 implementing unclippedDepth = false with frag_depth like on the other APIs:

        @vertex fn vs() -> @builtin(position) vec4<f32> {
            return vec4<f32>(0.0, 0.0, 5.0, 1.0);
        }

        @fragment fn fs() -> @builtin(frag_depth) f32 {
            return 0.5;
        }

The way to fix this inconsistency is to pass the viewport bounds to the shader and either:

  • Use MTLDepthClipMode.clamp and discard at the start of the FS if the position is outside of the viewport.
  • Use 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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions