You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Cannot reliably specify depth biases with depth24plus #6350
Let bias be (float)state.depthBias * 2^(exp(max depth in primitive) - r) + state.depthBiasSlopeScale * maxDepthSlope.
Since it is unclear whether depth24plus is a unorm format or a float format, it is impossible to reliably specify depth biases that work. It is also not possible to query whether depth24plus is backed by a unorm format or a float format, as far as I'm aware.
TBH I don't understand depth bias super well, but my understanding is that depthBias (Vulkan depthBiasConstantFactor ) is basically supposed to be in units of "ULPs" (units in last place) for both float and unorm, and thus the same value should work approximately the same regardless of the format.
That 2^(exp(max depth in primitive) - r) seems wrong in several ways, but I think it intends essentially 1 ULP at (max depth in primitive). Vulkan computes this as follows as follows:
Otherwise for floating-point depth attachment, there is no single minimum resolvable difference. In this case, the minimum resolvable difference for a given polygon is dependent on the maximum exponent, e, in the range of z values spanned by the primitive. If n is the number of bits in the floating-point mantissa, the minimum resolvable difference, r, for the given primitive is defined as
r = 2e−n
(Note our algorithm for unorm seems wrong as well: it assumes Vulkan's depthBiasExact is true.)
Anyway I assume since you filed this issue you ran into some trouble with the assumption that this would work for both formats. Would love to know more.
The D3D11 specification has something similar. I imagine this is where the WebGPU spec text originated from:
When UNORM Depth Buffer is at Output Merger (or no Depth Buffer):
Bias = (float)DepthBias * r + SlopeScaledDepthBias
Where r is the minimum representable value > 0 in the depth buffer
format, converted to float32.
When Floating Point Depth Buffer at Output Merger:
Bias = (float)DepthBias * 2^(exponent(max abs(z) in primitive) - r) +
SlopeScaledDepthBias
Where r is the # of mantissa bits in the floating point representation
(excluding the hidden bit), e.g. 23 for float32.
Anyway I assume since you filed this issue you ran into some trouble with the assumption that this would work for both formats. Would love to know more.
I don't have any data on this in WebGPU itself (all my test devices have 24-bit support), but I have past experience with this on different engines, and found that I needed to drastically change my depth bias constants when changing depth buffer precision. Even if it's 1ULP, that amount would change between pretty drastically between a 24-bit unorm format and an imagined 32-bit unorm format.
KN: Did research on this, Jasper says that there’s … <missed this>
Easiest solution would be to adjust what depth24plus is, make format explicit
Could also make depth24unorm optional and force developers to choose between that and depth32float.
CW: What are the possible formats?
KN: 16unorm, 24plus, 32float
CW: depth24unormstencil8 is optional
JB: Sounds like we don’t know what people are seeing in the field? Would it change our decision if we knew what they were seeing?
KN: As long as we trust that that’s true, no.
CW: Is there a world where we can say there’s multiple extensions and depth24unorm comes with the stencil8 version? Similar to compression we guarantee that at least one is exposed. Then once it’s in all stable channels developers can rely on at least one. Can’t guarantee because Vulkan doesn’t mandate.
KN: It makes sense, is consistent with everything else. But in what situation would you use depth24unorm?
CW: It’s a smaller format. Depth32float tends to have 4 bytes for stencil
KN: We have depth24plus for people worried about memory usage
JB: Unless we tell people what they’re getting they can’t get reliable biasing behavior.
CW: Even if this is only useful for depth bias, it would be good to have explicit formats rather than inferring. Nice part is that if they don’t use extensions they are required to use portable formats (depth24plus) even if depth bias is unpredictable.
KN: I think so. Are we convinced that this is enough of an issue to make a change?
MW: Share Kai’s concern that we may not need to do anything here. Not clear what format supports these formats. 24 bit depth buffers are deprecated in Metal.
CW: Is our suggestion to tell people to rely on Depth32_ to have consistent behavior?
KN: Wouldn’t hurt to expose which one it is. (depth24plus internal format)
CW: We have a number of options here. Let’s consult with Jasper about how big of a deal this is.
3 options:
Do nothing
Expose depth24plus internal format in adapter info
Activity
magcius commentedon Aug 11, 2026
jimblandy commentedon Aug 11, 2026
kainino0x commentedon Aug 11, 2026
TBH I don't understand depth bias super well, but my understanding is that
depthBias(VulkandepthBiasConstantFactor) is basically supposed to be in units of "ULPs" (units in last place) for both float and unorm, and thus the same value should work approximately the same regardless of the format.That
2^(exp(max depth in primitive) - r)seems wrong in several ways, but I think it intends essentially1 ULP at (max depth in primitive). Vulkan computes this as follows as follows:(Note our algorithm for unorm seems wrong as well: it assumes Vulkan's
depthBiasExactis true.)Anyway I assume since you filed this issue you ran into some trouble with the assumption that this would work for both formats. Would love to know more.
magcius commentedon Aug 12, 2026
The D3D11 specification has something similar. I imagine this is where the WebGPU spec text originated from:
I don't have any data on this in WebGPU itself (all my test devices have 24-bit support), but I have past experience with this on different engines, and found that I needed to drastically change my depth bias constants when changing depth buffer precision. Even if it's 1ULP, that amount would change between pretty drastically between a 24-bit unorm format and an imagined 32-bit unorm format.
Kangz commentedon Aug 18, 2026
GPU Web WG 2026-08-12 Atlantic-time
magcius commentedon Aug 19, 2026
Exposing depth24plus format information is fine by me. I agree this is not a major issue, just brought it up as a potential compat hazard.