Conversation
|
I'm excited to see this and plan on checking out the code. Thanks a ton for working on it! |
Vecvec
left a comment
There was a problem hiding this comment.
A couple of things from a read through.
There was a problem hiding this comment.
Ok so lots of thoughts here, mostly questions. Overall looks good. More comments would be great.
Big thing though is snapshot tests. I can't really review this change until I know what it generates and know that what it generates is correct. There might even be existing tests that you can just add METAL as a target to.
Thanks for putting in the work. I look forward to using this myself, and I'd like to get this landed soon!
|
|
||
| - Use autogenerated `objc2` bindings internally, which should resolve a lot of leaks and unsoundness. By @madsmtm in [#5641](https://github.com/gfx-rs/wgpu/pull/5641). | ||
| - Implements ray-tracing acceleration structures for metal backend. By @lichtso in [#8071](https://github.com/gfx-rs/wgpu/pull/8071). | ||
| - Added support for bindless storage buffers (buffer binding arrays) on Metal. By @mate-h in [#9081](https://github.com/gfx-rs/wgpu/pull/9081). |
There was a problem hiding this comment.
Tiny nit but maybe put this under "new features" rather than "changes"?
| crate::TypeInner::Struct { .. } => { | ||
| write!( | ||
| out, | ||
| "device {ARGUMENT_BUFFER_WRAPPER_STRUCT}<device {base_tyname}*>*" |
There was a problem hiding this comment.
Can you add a comment explaining this special case
| crate::Expression::FunctionArgument(_) => return None, | ||
| // There are no other expressions that produce pointer values. | ||
| _ => unreachable!(), | ||
| _ => return None, |
| { | ||
| Some(device.hasUnifiedMemory()) | ||
| // On Xcode frame capture this call causes a crash, fall back to feature table. | ||
| if Self::is_capture_mtl_device(device) { |
There was a problem hiding this comment.
Technically this might belong in another PR but its fine here IMO. Anyway, why Apple6 specifically? And tbh, it'd be fine to just report None here if we don't know for sure
| ); | ||
| features.set( | ||
| F::BUFFER_BINDING_ARRAY, | ||
| self.msl_version >= MTLLanguageVersion::Version3_0 |
There was a problem hiding this comment.
I can't find any reason why this shouldn't be 2.0? Though I guess you copied the above so that should also be changed.
Also, I believe this might impact Features::PARTIALLY_BOUND_BINDING_ARRAY?
| wgt::BufferBindingType::Uniform => MTLResourceUsage::Read, | ||
| wgt::BufferBindingType::Storage { read_only } => { | ||
| if *read_only { | ||
| MTLResourceUsage::Read | ||
| } else { | ||
| MTLResourceUsage::Read | MTLResourceUsage::Write | ||
| } | ||
| } |
There was a problem hiding this comment.
| wgt::BufferBindingType::Uniform => MTLResourceUsage::Read, | |
| wgt::BufferBindingType::Storage { read_only } => { | |
| if *read_only { | |
| MTLResourceUsage::Read | |
| } else { | |
| MTLResourceUsage::Read | MTLResourceUsage::Write | |
| } | |
| } | |
| wgt::BufferBindingType::Uniform | wgt::BufferBindingType::Storage { read_only: true }=> MTLResourceUsage::Read, | |
| wgt::BufferBindingType::Storage { read_only: false }=> MTLResourceUsage::Write, |
| wgt::BufferBindingType::Uniform => MTLBindingAccess::ReadOnly, | ||
| wgt::BufferBindingType::Storage { read_only } => { | ||
| if *read_only { | ||
| MTLBindingAccess::ReadOnly | ||
| } else { | ||
| MTLBindingAccess::ReadWrite | ||
| } | ||
| } |
There was a problem hiding this comment.
| wgt::BufferBindingType::Uniform => MTLBindingAccess::ReadOnly, | |
| wgt::BufferBindingType::Storage { read_only } => { | |
| if *read_only { | |
| MTLBindingAccess::ReadOnly | |
| } else { | |
| MTLBindingAccess::ReadWrite | |
| } | |
| } | |
| wgt::BufferBindingType::Uniform | wgt::BufferBindingType::Storage { read_only: true } => MTLBindingAccess::ReadOnly, | |
| wgt::BufferBindingType::Storage { read_only: false } => MTLBindingAccess::ReadWrite, |
There was a problem hiding this comment.
We will definitely need some snapshot tests here. You can read through naga/tests/in/wgsl to get a good idea of how to create these.
| let buffers = &desc.buffers[entry.resource_index as usize..] | ||
| [..count as usize]; |
There was a problem hiding this comment.
| let buffers = &desc.buffers[entry.resource_index as usize..] | |
| [..count as usize]; | |
| let buffers = &desc.buffers[entry.resource_index as usize..(entry.resource_index + count) as usize]; |
| let argument_desc = conv::pointer_array_argument_descriptor( | ||
| count, | ||
| conv::map_binding_access(&ty), | ||
| ); | ||
|
|
||
| let encoder = device | ||
| .newArgumentEncoderWithArguments(&NSArray::from_retained_slice( | ||
| &[argument_desc], | ||
| )) | ||
| .unwrap(); | ||
| let aligned_length = wgt::math::align_to( | ||
| encoder.encodedLength(), | ||
| encoder.alignment(), | ||
| ); | ||
| argument_buffer = device | ||
| .newBufferWithLength_options( | ||
| aligned_length, | ||
| MTLResourceOptions::HazardTrackingModeUntracked | ||
| | MTLResourceOptions::StorageModeShared, | ||
| ) | ||
| .unwrap(); |
There was a problem hiding this comment.
This entire section of code (and everything aroudn it) needs more comments. I don't fully understand why we're creating buffers, not putting them anywhere, etc.
Connections
Resolves #6741
Description
Problem: Metal on macOS did not support bindless storage buffers.
In
wgpu-hal, encode buffer binding arrays usingMTLArgumentEncoder. Metal expects encoded pointers, not raw resource IDs. Creates an argument buffer from an encoder, encode each buffer, and register it inresources_to_use.In naga MSL writer, emit
device T*for buffer binding array elements (which are pointers to device memory) instead of the constant layout used for textures and samplers. For struct members behind binding arrays, emit->instead of.because the elements are pointers.In the adapter, expose the
BUFFER_BINDING_ARRAYfeature and raisemax_buffers_per_stageon supporting devices, with special handling forMTLCaptureDevice. This is a separate fix for Xcode frame capture, when some functions fail to invoke, in these cases fallback to feature table based limits. I referenced the metal feature table PDF.Testing
Tested with Bevy Solari on metal / macOS which makes use of bindless storage buffers and raytracing acceleration structures.
Squash
Checklist
cargo fmt.taplo format.cargo clippy --tests. If applicable, add:--target wasm32-unknown-unknowncargo xtask testto run tests.CHANGELOG.mdentry.