From 167ff7b9529e690c291b158b9ea6f4232ddcb738 Mon Sep 17 00:00:00 2001 From: Jamie Nicol Date: Mon, 9 Jun 2025 16:14:02 +0100 Subject: [PATCH] [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. --- wgpu-core/src/device/resource.rs | 4 ++++ wgpu-hal/src/metal/adapter.rs | 3 ++- wgpu-hal/src/metal/device.rs | 37 ++++++++++++++++++++++++++++++-- wgpu-types/src/features.rs | 1 + 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index ba894a977..7d5898ecc 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -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())?; diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index 02dfc0fe6..44e2c3010 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -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( diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 6af8ad306..d034be31f 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -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; + } } } } diff --git a/wgpu-types/src/features.rs b/wgpu-types/src/features.rs index 8f7418b01..2c4bd7245 100644 --- a/wgpu-types/src/features.rs +++ b/wgpu-types/src/features.rs @@ -985,6 +985,7 @@ bitflags_array! { /// /// Supported platforms: /// - DX12 + /// - Metal const EXTERNAL_TEXTURE = 1 << 31; // Shader: