Although the operation of these functions is defined in terms of f16
semantics, the input/output types are not f16, and they are generally
available even when native `f16` support is not. But in at least one
case, they are only available with `f16` support, so add a new downlevel
flag that is cleared when these functions are not available.
Add some infrastructure to simplify testing of missing
capabilities/extensions, and add tests for a few more kinds of f16
usage.
Co-authored-by: Erich Gubler <erichdongubler@gmail.com>
This contains the Metal HAL changes required to support external
textures. When creating a bind group we create resource bindings for
each of the 3 textures and parameters buffer that the external texture
has been lowered to. When creating the pipeline layout we fill the
`BindTarget` accordingly, so that the Naga MSL backend can bind each
of the global variables to which the the external texture has been
lowered to each of these resources.
We must also ensure the size of the buffer bound to the parameters
global matches the size of the MSL type, else metal validation
complains. We do this by adding a padding field to the rust-side
ExternalTextureParams struct, the size of which is used as the size of
the buffer to allocate.
Lastly we enable `Features::EXTERNAL_TEXTURE` on the Metal backend.
P010 is a 4:2:0 chroma subsampled planar format, similar to NV12. Each
component uses 16 bits of storage, of which only the high 10 bits are
used. On DX12 this maps to DXGI_FORMAT_P010, and on Vulkan this maps to
G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16.
The existing "nv12" gpu test module has been renamed to
"planar_texture", and a new test P010_TEXTURE_CREATION_SAMPLING has
been added similar to the existing NV12_TEXTURE_CREATION_SAMPLING. The
remaining tests in this module have been converted to validation tests,
and now test both NV12 and P010 formats.
This implements the DX12 HAL part of external texture support, which is
the final piece of the puzzle for external textures on DirectX 12.
When creating a pipeline layout, HAL is responsible for mapping a
single BindingType::ExternalTexture bind group entry to multiple
descriptor ranges in the root signature it creates: 3 SRVs (one for
each texture plane) and a CBV for the parameters buffer. Additionally
we must expose the additional bindings to the Naga backend via the
`external_texture_binding_map`. Lastly, when creating a bind group we
write the descriptors for each of these bindings to the heap.
And with that, we can finally enable the `EXTERNAL_TEXTURE` feature
for the dx12 backend.
This adds several fields to `ExternalTextureDescriptor`, specifying
how to handle color space conversion for an external texture. These
fields consist of transfer functions for the source and destination
color spaces, and a matrix for converting between gamuts. This allows
`ImageSample` and `ImageLoad` operations on external textures to
return values in a desired destination color space rather than the
source color space of the underlying planes.
These fields are plumbed through to the `ExternalTextureParams`
uniform buffer from which they are exposed to the shader. Following
conversion from YUV to RGB after sampling/loading from the external
texture planes, the shader uses them to gamma decode to linear RGB in
the source color space, convert from source to destination gamut, then
finally gamma encode to non-linear RGB in the destination color space.
This adds HLSL backend support for `ImageClass::External` (ie WGSL's
`external_texture` texture type).
For each external texture global variable in the IR, we declare 3
`Texture2D` globals as well as a `cbuffer` for the params. The
additional bindings required by these are found in the newly added
`external_texture_binding_map`. Unique names for each can be obtained
using `NameKey::ExternalTextureGlobalVariable`.
For functions that contain ImageQuery::Size, ImageLoad, or ImageSample
expressions for external textures, ensure we have generated wrapper
functions for those expressions. When emitting code for the
expressions themselves, simply insert a call to the wrapper function.
For size queries, we return the value provided in the params
struct. If that value is [0, 0] then we query the size of the plane 0
texture and return that.
For load and sample, we sample the textures based on the number of
planes specified in the params struct. If there is more than one plane
we additionally perform YUV to RGB conversion using the provided
matrix.
Unfortunately HLSL does not allow structs to contain textures, meaning
we are unable to wrap the 3 textures and params struct variables in a
single variable that can be passed around.
For our wrapper functions we therefore ensure they take the three
textures and the params as consecutive arguments. Likewise, when
declaring user-defined functions with external texture arguments, we
expand the single external texture argument into 4 consecutive
arguments. (Using NameKey::ExternalTextureFunctionArgument to ensure
unique names for each.)
Thankfully external textures can only be used as either global
variables or function arguments. This means we only have to handle the
`Expression::GlobalVariable` and `Expression::FunctionArgument` cases
of `write_expr()`. Since in both cases we know the external texture
can only be an argument to either a user-defined function or one of
our wrapper functions, we can simply emit the names of the variables
for each three textures and the params struct in a comma-separated
list.
* Additional validation of buffer-texture copies
Fixes#7936, but leaves a TODO for #7947
* Skip tests failing on dx12
* Update comments and change unwrap_or to expect
`ExternalTexture` will form the basis of wgpu's implementation of
WebGPU's `GPUExternalTexture`. [1]
The application will be responsible for creating `Texture`(s) and
`TextureView`(s) from the external texture source and managing their
lifecycle. It may have a single RGBA texture, or it may have multiple
textures for separate Y and Cb/Cr planes. It can then create an external
texture by calling `create_external_texture()`, providing the texture
views and a descriptor. The descriptor provides the following required
information:
* Whether the texture data is RGBA, or multiplanar or interleaved
YCbCr.
* The purpoted size of the external texture, which may not match the
actual size of the underlying textures.
* A matrix for converting from YCbCr to RGBA, if required.
* A transform to apply to texture sample coordinates, allowing for
rotation and crop rects.
The external texture stores a reference to the provided texture views,
and additionally owns a `Buffer`. This buffer holds data of the type
`ExternalTextureParams`, and will be provided as a uniform buffer to
shaders containing external textures. This contains information that
will be required by the shaders to handle external textures correctly.
Note that attempting to create an external texture will fail unless the
`Feature::EXTERNAL_TEXTURE` feature is enabled, which as of yet is not
supported by any HAL backends.
Additionally add the relevant API to wgpu, implemented for the
wgpu-core backend. The web and custom backends are unimplemented.
[1] https://www.w3.org/TR/webgpu/#gpuexternaltexture
Adds a new feature flag, `EXTERNAL_TEXTURE`, indicating device support
for our implementation of WebGPU's `GPUExternalTexture` [1] which will
land in upcoming patches. Conceptually this would make more sense as a
downlevel flag, as it is a core part of the WebGPU spec which we do not
yet support. We do not want, however, to cause applications to reject
adapters because we have not finished implementing this, so for now we
are making it an opt-in feature.
As an initial step towards supporting this feature, this patch adds a
new `BindingType` corresponding to WebGPU's
`GPUExternalTextureBindingLayout` [2]. This binding type dictates that
when creating a bind group the corresponding entry must be either an
external texture or a texture view with certain additional requirements
[3].
As of yet wgpu has no concept of an external texture (that will follow
in later patches) but for now this patch ensures that texture views
corresponding to an external texture binding type are validated
correctly. Note that as the feature flag is not yet supported on any
real backends, bind group layout creation will fail before getting the
chance to attempt to create a bind group. But in the added tests using
the noop backend we can see this validation taking place.
[1] https://www.w3.org/TR/webgpu/#gpuexternaltexture
[1] https://www.w3.org/TR/webgpu/#dictdef-gpuexternaltexturebindinglayout
[2] https://gpuweb.github.io/gpuweb/#bind-group-creation