-
Notifications
You must be signed in to change notification settings - Fork 329
Description
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.