Repository navigation
feat(dx12, hlsl-out) Support for SHADER_EARLY_DEPTH_TEST on DX12 (only non-MSAA framebuffers) - #10624
Open
DouglasDwyer wants to merge 2 commits into
Open
DouglasDwyer wants to merge 2 commits into
DouglasDwyer wants to merge 2 commits into
Conversation
7 of 8 tasks
DouglasDwyer
force-pushed
the
conservative-depth-dx12
branch
2 times, most recently
from
October 15, 2026 00:04
b42231f to
57b880e
Compare
DouglasDwyer
force-pushed
the
conservative-depth-dx12
branch
3 times, most recently
from
October 15, 2026 00:47
9f81cac to
c19cefd
Compare
Naga's HLSL backend now implements `EarlyDepthTest`: - `@early_depth_test(force)` emits the `[earlydepthstencil]` attribute on the fragment entry point. - `@early_depth_test(greater_equal/less_equal)` changes the semantic of the `frag_depth` output from `SV_Depth` to `SV_DepthGreaterEqual` or `SV_DepthLessEqual`, but only for pipelines that are not multisampled. DXC only accepts these semantics when the `SV_Position` input is `noperspective centroid`, which is equivalent to the default pixel-center position only when there is one sample per pixel. Multisampled pipelines use an unrestricted `SV_Depth` and leave the position input alone. - HLSL has no equivalent of `unchanged`. A depth output with that setting would be a no-op, so it is discarded instead of being written to `SV_Depth`, which would disable early depth tests. Entry points that return only the depth return `void`, and a result struct that also has other outputs is returned through a wrapper struct without the depth member. Callers tell the backend whether the pipeline is multisampled with the new `hlsl::PipelineOptions::multisampled`, which defaults to `false`. wgpu-hal sets it from the sample count of the render pipeline. The semantic is part of a struct's definition, so when several fragment entry points share an output struct, the conservative semantic is only used if they all agree on the setting. Otherwise `SV_Depth` is used, which is always correct. The HLSL backend now advertises `Capabilities::EARLY_DEPTH_TEST`, and the DX12 adapter advertises the wgpu feature.
Add HLSL snapshots for `@early_depth_test`, including `force`, `greater_equal`, `less_equal` and `unchanged`, and depth written through an output struct that is shared by several entry points (both when they agree and when they do not). Cover discarding the depth for `unchanged` when the result is only the depth, a struct of only the depth, and a struct with other outputs.
DouglasDwyer
force-pushed
the
conservative-depth-dx12
branch
from
October 15, 2026 00:52
c19cefd to
db78b68
Compare
DouglasDwyer
marked this pull request as ready for review
October 15, 2026 01:02
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Connections
#3961 - Support for conservative depth
#10625 - feat(metal, msl-out) Support for SHADER_EARLY_DEPTH_TEST on Metal
gpuweb/gpuweb#5349 - [WGSL fragment depth] (less, greater, any) portability
Description
Right now, the
early_depth_testintrinsic is supported on Vulkan, but not DX12 or Metal. WGSL code like this fails to compile:DX12 is capable of supporting conservative depth. In HLSL, instead of writing to
SV_Depth, you can write toSV_DepthGreaterEqualorSV_DepthLessEqual. There is no equivalent for@early_depth_test(unchanged).This PR makes Naga emit
SV_DepthGreaterEqual/SV_DepthLessEqualin the appropriate cases. For@early_depth_test(unchanged), Naga makes sure that its output never actually modifies the realSV_Depth- instead, all depth writes are redirected to a private variable.This PR does not support MSAA render pipelines yet
When conservative depth testing is enabled, DXC requires that the
SV_Positionfragment input be interpolated as either:Notably, pixel center is not allowed as an option. This is troublesome because the WebGPU spec always defines
@builtin(position)to be at the pixel center, at least according to my reading. So choosing either of these options, for an MSAA framebuffer, would be incorrect.As such, this PR will only emit conservative depth attributes when compiling for a 1-sample framebuffer. In other cases, it falls back to
SV_Depth. But I'm open to reconsidering this approach if centroid/per-sample interpolation turn out to be allowed within the spec.Testing
I have tested this in my game engine and it worked - there was a measurable improvement in frame times with
@early_depth_test(less_equal)in one of my shaders.Additionally, the following unit tests are added:
naga/tests/in/wgsl/early-depth-test-*) that cover every@early_depth_testsetting for HLSL:force,greater_equal,less_equal, andunchangedon a barefrag_depthresult.unchangedwith a color-plus-depth struct, a depth-only struct, and an unrestricted entry point sharing the struct.Squash or Rebase?
Squash
LLM Use?
Yes - I used Claude to implement and test these changes.
Checklist
CHANGELOG.mdentries for the user-facing effects of this change are present.wgpumay be affected behaviorally.