这是indexloc提供的服务,不要输入任何密码
Skip to content

2nd, 3rd, and 4th components of sampled depth/stencil textures are undefined in Metal #1198

@austinEng

Description

@austinEng

In WGSL, performing a textureSample or textureLoad operation on a texture_sampled_2d<type> yields a vec4<type>. This is true even for textures that have fewer than 4 components ex.) r8uint, r16float, rg8unorm. It is possible to bind a texture with n components to texture_sampled_2d<type> as long as the texture's component type matches the type in the shader. You can bind a texture of type depth32float to texture_sampled_2d<float>.

Sampling the "unspecified" components yields default values. i.e. accessing the b component of an rg texture yields some default value.

According to the Metal Shading Language Specification (EDIT:) 2.3 section 6.10 / 2.4 section 6.12:

For unspecified color components in a pixel format, the default values are:
• zero, for components other than alpha.
• one, for the alpha component.
...
...
For a texture with depth or stencil pixel format
(such as MTLPixelFormatDepth24Unorm_Stencil8 or MTLPixelFormatStencil8), the
default value for an unspecified component is undefined

On the contrary, in all of the other APIs (Vulkan, D3D12, OpenGL too), when sampling a depth texture (it has 1 component), accessing the "unspecified" components .g, .b, and .a yield 0, 0, and 1, respectively.

In recent versions of MacOS (10.15+) and iOS (13.0+), MTLTextureSwizzleChannels can be set on texture view creation to force the unspecified components to some component index, or 0, or 1. Unfortunately, on older Apple platforms, mitigating the undefined values in Metal would involve binding extra data to the shader to indicate whether at draw-time a texture is a depth/stencil texture in order to emulate correct values for the unspecified components. We could also recompile pipelines and pass the data as MTLFunctionConstants, but that may be a worse solution.

If we want to avoid binding extra data per-sampled-texture or recompiling pipelines, an alternative solution could be to add even more binding types and WGSL types: sampled-depth-texture and sampled-stencil-texture. This way, a WGSL compiler knows at compile-time if a texture is a depth/stencil texture and can insert shader code to emulate the unspecified components.

Note: When I say "sampling a depth texture" I mean sampling the values out of a depth texture bound to texture_sampled_2d<f32>. This is not the same as using texture_depth_2d which is for comparison sampling.

Metadata

Metadata

Assignees

Labels

wgslWebGPU Shading Language Issues

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions