[metal] Implement support for external textures

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.
This commit is contained in:
Jamie Nicol 2025-06-09 16:14:02 +01:00 committed by Jamie Nicol
parent 2c6f06a82b
commit 167ff7b952
4 changed files with 42 additions and 3 deletions

View File

@ -163,6 +163,8 @@ pub struct ExternalTextureParams {
/// plane and an interleaved CbCr plane. 3 indicates separate Y, Cb, and Cr
/// planes.
pub num_planes: u32,
// Ensure the size of this struct matches the type generated by Naga.
pub _padding: [u8; 4],
}
impl ExternalTextureParams {
@ -191,6 +193,7 @@ impl ExternalTextureParams {
sample_transform: desc.sample_transform,
load_transform: desc.load_transform,
num_planes: desc.num_planes() as u32,
_padding: Default::default(),
}
}
}
@ -512,6 +515,7 @@ impl Device {
0.0, 0.0
],
num_planes: 1,
_padding: Default::default(),
};
let mut staging_buffer =
StagingBuffer::new(self, wgt::BufferSize::new(size_of_val(&data) as _).unwrap())?;

View File

@ -927,7 +927,8 @@ impl super::PrivateCapabilities {
| F::SHADER_F16
| F::DEPTH32FLOAT_STENCIL8
| F::BGRA8UNORM_STORAGE
| F::EXPERIMENTAL_PASSTHROUGH_SHADERS;
| F::EXPERIMENTAL_PASSTHROUGH_SHADERS
| F::EXTERNAL_TEXTURE;
features.set(F::FLOAT32_FILTERABLE, self.supports_float_filtering);
features.set(

View File

@ -747,7 +747,19 @@ impl crate::Device for super::Device {
};
}
wgt::BindingType::AccelerationStructure { .. } => unimplemented!(),
wgt::BindingType::ExternalTexture => unimplemented!(),
wgt::BindingType::ExternalTexture => {
target.external_texture =
Some(naga::back::msl::BindExternalTextureTarget {
planes: [
info.counters.textures as _,
(info.counters.textures + 1) as _,
(info.counters.textures + 2) as _,
],
params: info.counters.buffers as _,
});
info.counters.textures += 3;
info.counters.buffers += 1;
}
}
}
@ -980,7 +992,28 @@ impl crate::Device for super::Device {
counter.textures += 1;
}
wgt::BindingType::AccelerationStructure { .. } => unimplemented!(),
wgt::BindingType::ExternalTexture => unimplemented!(),
wgt::BindingType::ExternalTexture => {
// We don't yet support binding arrays of external textures.
// https://github.com/gfx-rs/wgpu/issues/8027
assert_eq!(entry.count, 1);
let external_texture =
&desc.external_textures[entry.resource_index as usize];
bg.textures.extend(
external_texture
.planes
.iter()
.map(|plane| plane.view.as_raw()),
);
bg.buffers.push(super::BufferResource {
ptr: external_texture.params.buffer.as_raw(),
offset: external_texture.params.offset,
dynamic_index: None,
binding_size: None,
binding_location: layout.binding,
});
counter.textures += 3;
counter.buffers += 1;
}
}
}
}

View File

@ -985,6 +985,7 @@ bitflags_array! {
///
/// Supported platforms:
/// - DX12
/// - Metal
const EXTERNAL_TEXTURE = 1 << 31;
// Shader: