diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bceb0e7ec..367acb563a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ Bottom level categories: - Fix order of arguments to glPolygonOffset by @komadori in [#3783](https://github.com/gfx-rs/wgpu/pull/3783). - Fix OpenGL/EGL backend not respecting non-sRGB texture formats in `SurfaceConfiguration`. by @liquidev in [#3817](https://github.com/gfx-rs/wgpu/pull/3817) +- Make write- and read-only marked buffers match non-readonly layouts. by @fornwall in [#3893](https://github.com/gfx-rs/wgpu/pull/3893) #### Metal diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index 83cb90530a..771adba731 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -409,7 +409,7 @@ impl Resource { ) } }; - if self.class != class { + if !address_space_matches(self.class, class) { return Err(BindingError::WrongAddressSpace { binding: class, shader: self.class, @@ -1237,3 +1237,72 @@ impl Interface { Ok(outputs) } } + +fn address_space_matches(shader: naga::AddressSpace, binding: naga::AddressSpace) -> bool { + match (shader, binding) { + ( + naga::AddressSpace::Storage { + access: access_shader, + }, + naga::AddressSpace::Storage { + access: access_pipeline, + }, + ) => { + // Allow read- and write-only usages to match read-write layouts: + (access_shader & access_pipeline) == access_shader + } + (a, b) => a == b, + } +} + +#[cfg(test)] +mod test { + use super::address_space_matches; + + #[test] + fn address_space_matches_correctly() { + assert!(address_space_matches( + naga::AddressSpace::Uniform, + naga::AddressSpace::Uniform + )); + + assert!(!address_space_matches( + naga::AddressSpace::Uniform, + naga::AddressSpace::Storage { + access: naga::StorageAccess::LOAD + } + )); + + let test_cases = [ + (naga::StorageAccess::LOAD, naga::StorageAccess::LOAD, true), + (naga::StorageAccess::STORE, naga::StorageAccess::LOAD, false), + (naga::StorageAccess::LOAD, naga::StorageAccess::STORE, false), + (naga::StorageAccess::STORE, naga::StorageAccess::STORE, true), + ( + naga::StorageAccess::LOAD | naga::StorageAccess::STORE, + naga::StorageAccess::LOAD | naga::StorageAccess::STORE, + true, + ), + ( + naga::StorageAccess::STORE, + naga::StorageAccess::LOAD | naga::StorageAccess::STORE, + true, + ), + ( + naga::StorageAccess::LOAD, + naga::StorageAccess::LOAD | naga::StorageAccess::STORE, + true, + ), + ]; + + for (shader, binding, expect_match) in test_cases { + assert_eq!( + expect_match, + address_space_matches( + naga::AddressSpace::Storage { access: shader }, + naga::AddressSpace::Storage { access: binding } + ) + ); + } + } +}