From e23751513f6e73a5358dba2e5c518bbede8eb0c9 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Sun, 2 Nov 2025 12:23:00 +0100 Subject: [PATCH 1/6] Support STORAGE_RESOURCE_BINDING_ARRAY on Metal --- Cargo.lock | 3 +-- Cargo.toml | 2 +- naga/src/back/msl/writer.rs | 8 +++++--- wgpu-hal/src/metal/adapter.rs | 7 +++++++ wgpu-hal/src/metal/conv.rs | 10 ++++++++++ wgpu-hal/src/metal/device.rs | 19 +++++++++++++++++++ 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0bd25b79ff3..eb81afe33a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2412,8 +2412,7 @@ dependencies = [ [[package]] name = "metal" version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" +source = "git+https://github.com/msvbg/metal-rs?branch=gpu_resource_id_for_buffer#a4866ca7659e53d252d5a3909dffb2bffdbb1f90" dependencies = [ "bitflags 2.10.0", "block", diff --git a/Cargo.toml b/Cargo.toml index 335dddaa601..572c344dcd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -200,7 +200,7 @@ which = "8" xshell = "0.2.2" # Metal dependencies -metal = "0.32" +metal = { git = "https://github.com/msvbg/metal-rs", branch = "gpu_resource_id_for_buffer" } block = "0.1.6" core-graphics-types = "0.2" objc = "0.2.5" diff --git a/naga/src/back/msl/writer.rs b/naga/src/back/msl/writer.rs index 484142630d2..50f5c86503e 100644 --- a/naga/src/back/msl/writer.rs +++ b/naga/src/back/msl/writer.rs @@ -7099,9 +7099,11 @@ template } } crate::ImageClass::Storage { .. } => { - return Err(Error::UnsupportedArrayOf( - "read-write textures".to_string(), - )); + if options.lang_version < (3, 0) { + return Err(Error::UnsupportedArrayOf( + "read-write textures".to_string(), + )); + } } crate::ImageClass::External => { return Err(Error::UnsupportedArrayOf( diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index fa3d2fa8d41..bc0f8ead251 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -985,6 +985,13 @@ impl super::PrivateCapabilities { && self.supports_arrays_of_textures && self.argument_buffers as u64 >= MTLArgumentBuffersTier::Tier2 as u64, ); + features.set( + F::STORAGE_RESOURCE_BINDING_ARRAY, + self.msl_version >= MTLLanguageVersion::V3_0 + && self.supports_arrays_of_textures + && self.supports_arrays_of_textures_write + && self.argument_buffers as u64 >= MTLArgumentBuffersTier::Tier2 as u64, + ); features.set( F::SHADER_INT64, self.int64 && self.msl_version >= MTLLanguageVersion::V2_3, diff --git a/wgpu-hal/src/metal/conv.rs b/wgpu-hal/src/metal/conv.rs index 260b6c15a32..8a761f538a1 100644 --- a/wgpu-hal/src/metal/conv.rs +++ b/wgpu-hal/src/metal/conv.rs @@ -349,6 +349,16 @@ pub fn map_resource_usage(ty: &wgt::BindingType) -> MTLResourceUsage { MTLResourceUsage::Read | MTLResourceUsage::Write } }, + wgt::BindingType::Buffer { ty, .. } => match ty { + wgt::BufferBindingType::Uniform => MTLResourceUsage::Read, + wgt::BufferBindingType::Storage { read_only } => { + if *read_only { + MTLResourceUsage::Read + } else { + MTLResourceUsage::Read | MTLResourceUsage::Write + } + } + }, wgt::BindingType::Sampler(..) => MTLResourceUsage::empty(), _ => unreachable!(), } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 91533453569..c992f786ced 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -905,6 +905,25 @@ impl crate::Device for super::Device { }; match layout.ty { + wgt::BindingType::Buffer { .. } => { + let start = entry.resource_index as usize; + let end = start + count as usize; + let buffers = &desc.buffers[start..end]; + let compute_visible = + layout.visibility.contains(wgt::ShaderStages::COMPUTE); + + for (idx, buffer_binding) in buffers.iter().enumerate() { + contents[idx] = buffer_binding.buffer.raw.gpu_resource_id(); + + let use_info = bg + .resources_to_use + .entry(buffer_binding.buffer.as_raw().cast()) + .or_default(); + use_info.stages |= stages; + use_info.uses |= uses; + use_info.visible_in_compute |= compute_visible; + } + } wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => { let start = entry.resource_index as usize; From 9d371f35975610692f6db6107482c6ecadb51408 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Sun, 2 Nov 2025 12:52:19 +0100 Subject: [PATCH 2/6] Add CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5678c5760df..68af5117d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -109,6 +109,7 @@ By @SupaMaggie70Incorporated in [#8206](https://github.com/gfx-rs/wgpu/pull/8206 - Added support for transient textures on Vulkan and Metal. By @opstic in [#8247](https://github.com/gfx-rs/wgpu/pull/8247) - Implement shader triangle barycentric coordinate builtins. By @atlv24 in [#8320](https://github.com/gfx-rs/wgpu/pull/8320). +- Added support for binding arrays of storage buffers and storage textures on Metal. By @msvbg in [#8464](https://github.com/gfx-rs/wgpu/pull/8464) ### Changes From 8325f2dcb9f7cfad0856c305ae5547e293103811 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Mon, 17 Nov 2025 16:54:56 +0100 Subject: [PATCH 3/6] Remove changes to buffers --- wgpu-hal/src/metal/conv.rs | 10 ---------- wgpu-hal/src/metal/device.rs | 19 ------------------- 2 files changed, 29 deletions(-) diff --git a/wgpu-hal/src/metal/conv.rs b/wgpu-hal/src/metal/conv.rs index 8a761f538a1..260b6c15a32 100644 --- a/wgpu-hal/src/metal/conv.rs +++ b/wgpu-hal/src/metal/conv.rs @@ -349,16 +349,6 @@ pub fn map_resource_usage(ty: &wgt::BindingType) -> MTLResourceUsage { MTLResourceUsage::Read | MTLResourceUsage::Write } }, - wgt::BindingType::Buffer { ty, .. } => match ty { - wgt::BufferBindingType::Uniform => MTLResourceUsage::Read, - wgt::BufferBindingType::Storage { read_only } => { - if *read_only { - MTLResourceUsage::Read - } else { - MTLResourceUsage::Read | MTLResourceUsage::Write - } - } - }, wgt::BindingType::Sampler(..) => MTLResourceUsage::empty(), _ => unreachable!(), } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index c992f786ced..91533453569 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -905,25 +905,6 @@ impl crate::Device for super::Device { }; match layout.ty { - wgt::BindingType::Buffer { .. } => { - let start = entry.resource_index as usize; - let end = start + count as usize; - let buffers = &desc.buffers[start..end]; - let compute_visible = - layout.visibility.contains(wgt::ShaderStages::COMPUTE); - - for (idx, buffer_binding) in buffers.iter().enumerate() { - contents[idx] = buffer_binding.buffer.raw.gpu_resource_id(); - - let use_info = bg - .resources_to_use - .entry(buffer_binding.buffer.as_raw().cast()) - .or_default(); - use_info.stages |= stages; - use_info.uses |= uses; - use_info.visible_in_compute |= compute_visible; - } - } wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => { let start = entry.resource_index as usize; From 83e28de7a04cb999d3189fef5765e359d8a9c557 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Mon, 17 Nov 2025 16:55:58 +0100 Subject: [PATCH 4/6] Tweak wording in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68af5117d6d..f7dc3ba79c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -109,7 +109,7 @@ By @SupaMaggie70Incorporated in [#8206](https://github.com/gfx-rs/wgpu/pull/8206 - Added support for transient textures on Vulkan and Metal. By @opstic in [#8247](https://github.com/gfx-rs/wgpu/pull/8247) - Implement shader triangle barycentric coordinate builtins. By @atlv24 in [#8320](https://github.com/gfx-rs/wgpu/pull/8320). -- Added support for binding arrays of storage buffers and storage textures on Metal. By @msvbg in [#8464](https://github.com/gfx-rs/wgpu/pull/8464) +- Added support for binding arrays of storage textures on Metal. By @msvbg in [#8464](https://github.com/gfx-rs/wgpu/pull/8464) ### Changes From 1b8aca4163e1b15a95e5b52406c85d2650d5ef85 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Mon, 17 Nov 2025 16:56:49 +0100 Subject: [PATCH 5/6] Revert Cargo.toml/lock changes --- Cargo.lock | 3 ++- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eb81afe33a2..0bd25b79ff3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2412,7 +2412,8 @@ dependencies = [ [[package]] name = "metal" version = "0.32.0" -source = "git+https://github.com/msvbg/metal-rs?branch=gpu_resource_id_for_buffer#a4866ca7659e53d252d5a3909dffb2bffdbb1f90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ "bitflags 2.10.0", "block", diff --git a/Cargo.toml b/Cargo.toml index 572c344dcd8..335dddaa601 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -200,7 +200,7 @@ which = "8" xshell = "0.2.2" # Metal dependencies -metal = { git = "https://github.com/msvbg/metal-rs", branch = "gpu_resource_id_for_buffer" } +metal = "0.32" block = "0.1.6" core-graphics-types = "0.2" objc = "0.2.5" From de93dbb5d9f51de44e9ae986d076e97f30c1629a Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Wed, 26 Nov 2025 21:43:51 +0100 Subject: [PATCH 6/6] Make storage tests pass on Metal --- tests/tests/wgpu-gpu/binding_array/storage_textures.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/tests/wgpu-gpu/binding_array/storage_textures.rs b/tests/tests/wgpu-gpu/binding_array/storage_textures.rs index 69cec788c4f..e27b9dc2a34 100644 --- a/tests/tests/wgpu-gpu/binding_array/storage_textures.rs +++ b/tests/tests/wgpu-gpu/binding_array/storage_textures.rs @@ -2,8 +2,8 @@ use std::num::NonZeroU32; use wgpu::*; use wgpu_test::{ - gpu_test, image::ReadbackBuffers, FailureCase, GpuTestConfiguration, GpuTestInitializer, - TestParameters, TestingContext, + gpu_test, image::ReadbackBuffers, GpuTestConfiguration, GpuTestInitializer, TestParameters, + TestingContext, }; pub fn all_tests(tests: &mut Vec) { @@ -26,8 +26,7 @@ static BINDING_ARRAY_STORAGE_TEXTURES: GpuTestConfiguration = GpuTestConfigurati .limits(Limits { max_binding_array_elements_per_shader_stage: 17, ..Limits::default() - }) - .expect_fail(FailureCase::backend(Backends::METAL)), + }), ) .run_async(|ctx| async move { binding_array_storage_textures(ctx, false).await }); @@ -45,8 +44,7 @@ static PARTIAL_BINDING_ARRAY_STORAGE_TEXTURES: GpuTestConfiguration = GpuTestCon .limits(Limits { max_binding_array_elements_per_shader_stage: 33, ..Limits::default() - }) - .expect_fail(FailureCase::backend(Backends::METAL)), + }), ) .run_async(|ctx| async move { binding_array_storage_textures(ctx, true).await });