Skip to content

Commit 092bf67

Browse files
committed
[naga msl-out] Implement support for external textures
This adds MSL backend support for `ImageClass::External`. (ie WGSL's `external_texture` texture type). This is implemented very similarily to the HLSL implementation in #7826. Each external texture global variable is lowered to 3 `texture2d`s and a buffer of type NagaExternalTextureParams. As usual in Naga's MSL backend, these are passed as arguments to the entry point. The bindings for each of these arguments are provided via the usual binding map, using a new `BindExternalTextureTarget` variant of `BindTarget`. Unlike HLSL, MSL allows textures to be used as fields in structs. We therefore immediately wrap these variables in a `NagaExternalTextureWrapper` struct. This wrapper can then conveniently be passed to either user-defined functions or builtin implementations that accept an external texture. The WGSL builtins `textureDimensions()`, `textureLoad()`, and `textureSampleBaseClampToEdge()` are implemented using wrapper functions using the regular `write_wrapped_functions()` machinery.
1 parent a288e86 commit 092bf67

File tree

6 files changed

+748
-34
lines changed

6 files changed

+748
-34
lines changed

naga-cli/src/bin/naga.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ fn run() -> anyhow::Result<()> {
538538
use naga::valid::Capabilities as C;
539539
let missing = match Path::new(path).extension().and_then(|ex| ex.to_str()) {
540540
Some("wgsl") => C::CLIP_DISTANCE | C::CULL_DISTANCE,
541-
Some("metal") => C::CULL_DISTANCE | C::TEXTURE_EXTERNAL,
541+
Some("metal") => C::CULL_DISTANCE,
542542
Some("hlsl") => C::empty(),
543543
_ => C::TEXTURE_EXTERNAL,
544544
};

naga/src/back/msl/keywords.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,11 @@ pub const RESERVED: &[&str] = &[
353353
super::writer::F2U32_FUNCTION,
354354
super::writer::F2I64_FUNCTION,
355355
super::writer::F2U64_FUNCTION,
356+
super::writer::IMAGE_LOAD_EXTERNAL_FUNCTION,
356357
super::writer::IMAGE_SAMPLE_BASE_CLAMP_TO_EDGE_FUNCTION,
358+
super::writer::IMAGE_SIZE_EXTERNAL_FUNCTION,
357359
super::writer::ARGUMENT_BUFFER_WRAPPER_STRUCT,
360+
super::writer::EXTERNAL_TEXTURE_WRAPPER_STRUCT,
358361
];
359362

360363
/// The above set of reserved keywords, turned into a cached HashSet. This saves

naga/src/back/msl/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,29 @@ additional effort and the difference is unlikely to matter.)
4343
4444
[`BoundsCheckPolicy`]: crate::proc::BoundsCheckPolicy
4545
46+
## External textures
47+
48+
Support for [`crate::ImageClass::External`] textures is implemented by lowering
49+
each external texture global variable to 3 `texture2d<float, sample>`s, and a
50+
constant buffer of type `NagaExternalTextureParams`. This provides up to 3
51+
planes of texture data (for example single planar RGBA, or separate Y, Cb, and
52+
Cr planes), and the parameters buffer containing information describing how to
53+
handle these correctly. The bind target to use for each of these globals is
54+
specified via the [`BindTarget::external_texture`] field of the relevant
55+
entries in [`EntryPointResources::resources`].
56+
57+
External textures are supported by WGSL's `textureDimensions()`,
58+
`textureLoad()`, and `textureSampleBaseClampToEdge()` built-in functions. These
59+
are implemented using helper functions. See the following functions for how
60+
these are generated:
61+
* `Writer::write_wrapped_image_query`
62+
* `Writer::write_wrapped_image_load`
63+
* `Writer::write_wrapped_image_sample`
64+
65+
The lowered global variables for each external texture global are passed to the
66+
entry point as separate arguments (see "Entry points" above). However, they are
67+
then wrapped in a struct to allow them to be conveniently passed to user
68+
defined and helper functions. See [`writer::EXTERNAL_TEXTURE_WRAPPER_STRUCT`].
4669
*/
4770

4871
use alloc::{
@@ -71,6 +94,19 @@ pub enum BindSamplerTarget {
7194
Inline(InlineSamplerIndex),
7295
}
7396

97+
/// Binding information for a Naga [`External`] image global variable.
98+
///
99+
/// See the module documentation's section on external textures for details.
100+
///
101+
/// [`External`]: crate::ir::ImageClass::External
102+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
103+
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
104+
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
105+
pub struct BindExternalTextureTarget {
106+
pub planes: [Slot; 3],
107+
pub params: Slot,
108+
}
109+
74110
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
75111
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
76112
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
@@ -79,6 +115,7 @@ pub struct BindTarget {
79115
pub buffer: Option<Slot>,
80116
pub texture: Option<Slot>,
81117
pub sampler: Option<BindSamplerTarget>,
118+
pub external_texture: Option<BindExternalTextureTarget>,
82119
pub mutable: bool,
83120
}
84121

0 commit comments

Comments
 (0)