mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-01-10 12:48:46 -05:00
[naga hlsl-out] Implement external texture support
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.
This commit is contained in:
@@ -6285,6 +6285,20 @@ pub enum ExternalTextureFormat {
|
||||
|
||||
/// Describes an [`ExternalTexture`](../wgpu/struct.ExternalTexture.html).
|
||||
///
|
||||
/// Note that [`width`] and [`height`] are the values that should be returned by
|
||||
/// size queries in shader code; they do not necessarily match the dimensions of
|
||||
/// the underlying plane texture(s). As a special case, if `(width, height)` is
|
||||
/// `(0, 0)`, the actual size of the first underlying plane should be used instead.
|
||||
///
|
||||
/// The size given by [`width`] and [`height`] must be consistent with
|
||||
/// [`sample_transform`]: they should be the size in texels of the rectangle
|
||||
/// covered by the square (0,0)..(1,1) after [`sample_transform`] has been applied
|
||||
/// to it.
|
||||
///
|
||||
/// [`width`]: Self::width
|
||||
/// [`height`]: Self::height
|
||||
/// [`sample_transform`]: Self::sample_transform
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUExternalTextureDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuexternaltexturedescriptor).
|
||||
#[repr(C)]
|
||||
@@ -6294,23 +6308,51 @@ pub struct ExternalTextureDescriptor<L> {
|
||||
/// Debug label of the external texture. This will show up in graphics
|
||||
/// debuggers for easy identification.
|
||||
pub label: L,
|
||||
/// Width of the external texture. Note that both this and `height` may
|
||||
/// not match the dimensions of the underlying texture(s). This could be
|
||||
/// due to a crop rect or rotation.
|
||||
|
||||
/// Width of the external texture.
|
||||
pub width: u32,
|
||||
|
||||
/// Height of the external texture.
|
||||
pub height: u32,
|
||||
|
||||
/// Format of the external texture.
|
||||
pub format: ExternalTextureFormat,
|
||||
|
||||
/// 4x4 column-major matrix with which to convert sampled YCbCr values
|
||||
/// to RGBA.
|
||||
/// This is ignored when `format` is [`ExternalTextureFormat::Rgba`].
|
||||
pub yuv_conversion_matrix: [f32; 16],
|
||||
/// 3x2 column-major matrix with which to multiply normalized texture
|
||||
/// coordinates prior to sampling from the external texture.
|
||||
|
||||
/// Transform to apply to [`ImageSample`] coordinates.
|
||||
///
|
||||
/// This is a 3x2 column-major matrix representing an affine transform from
|
||||
/// normalized texture coordinates to the normalized coordinates that should
|
||||
/// be sampled from the external texture's underlying plane(s).
|
||||
///
|
||||
/// This transform may scale, translate, flip, and rotate in 90-degree
|
||||
/// increments, but the result of transforming the rectangle (0,0)..(1,1)
|
||||
/// must be an axis-aligned rectangle that falls within the bounds of
|
||||
/// (0,0)..(1,1).
|
||||
///
|
||||
/// [`ImageSample`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageSample
|
||||
pub sample_transform: [f32; 6],
|
||||
/// 3x2 column-major matrix with which to multiply unnormalized texture
|
||||
/// coordinates prior to loading from the external texture.
|
||||
|
||||
/// Transform to apply to [`ImageLoad`] coordinates.
|
||||
///
|
||||
/// This is a 3x2 column-major matrix representing an affine transform from
|
||||
/// non-normalized texel coordinates to the non-normalized coordinates of
|
||||
/// the texel that should be loaded from the external texture's underlying
|
||||
/// plane 0. For planes 1 and 2, if present, plane 0's coordinates are
|
||||
/// scaled according to the textures' relative sizes.
|
||||
///
|
||||
/// This transform may scale, translate, flip, and rotate in 90-degree
|
||||
/// increments, but the result of transforming the rectangle (0,0)..([`width`],
|
||||
/// [`height`]) must be an axis-aligned rectangle that falls within the bounds
|
||||
/// of (0,0)..([`width`], [`height`]).
|
||||
///
|
||||
/// [`ImageLoad`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageLoad
|
||||
/// [`width`]: Self::width
|
||||
/// [`height`]: Self::height
|
||||
pub load_transform: [f32; 6],
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user