From 4831789bbb15ce22fbdffd6c319098f389f2e5ee Mon Sep 17 00:00:00 2001 From: Hannes Vernooij <70136549+hannes-vernooij@users.noreply.github.com> Date: Tue, 26 Oct 2021 09:15:50 +0200 Subject: [PATCH] added memory barrier intrinsics to spirv-std (#769) * added memory barrier intrinsics to spirv-std * added function-level docs * added unit-tests constants could not be validated in tests because of the limited output * clippy fixes * improved documentation * Added missing features to device_memory and all_memory barrier intrinsics. --- crates/spirv-std/src/arch/barrier.rs | 111 ++++++++++++++++++ tests/ui/arch/all_memory_barrier.rs | 16 +++ tests/ui/arch/all_memory_barrier.stderr | 7 ++ .../all_memory_barrier_with_group_sync.rs | 16 +++ .../all_memory_barrier_with_group_sync.stderr | 7 ++ tests/ui/arch/device_memory_barrier.rs | 16 +++ tests/ui/arch/device_memory_barrier.stderr | 7 ++ .../device_memory_barrier_with_group_sync.rs | 16 +++ ...vice_memory_barrier_with_group_sync.stderr | 7 ++ tests/ui/arch/workgroup_memory_barrier.rs | 15 +++ tests/ui/arch/workgroup_memory_barrier.stderr | 7 ++ ...orkgroup_memory_barrier_with_group_sync.rs | 15 +++ ...roup_memory_barrier_with_group_sync.stderr | 7 ++ 13 files changed, 247 insertions(+) create mode 100644 tests/ui/arch/all_memory_barrier.rs create mode 100644 tests/ui/arch/all_memory_barrier.stderr create mode 100644 tests/ui/arch/all_memory_barrier_with_group_sync.rs create mode 100644 tests/ui/arch/all_memory_barrier_with_group_sync.stderr create mode 100644 tests/ui/arch/device_memory_barrier.rs create mode 100644 tests/ui/arch/device_memory_barrier.stderr create mode 100644 tests/ui/arch/device_memory_barrier_with_group_sync.rs create mode 100644 tests/ui/arch/device_memory_barrier_with_group_sync.stderr create mode 100644 tests/ui/arch/workgroup_memory_barrier.rs create mode 100644 tests/ui/arch/workgroup_memory_barrier.stderr create mode 100644 tests/ui/arch/workgroup_memory_barrier_with_group_sync.rs create mode 100644 tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr diff --git a/crates/spirv-std/src/arch/barrier.rs b/crates/spirv-std/src/arch/barrier.rs index 6420dc80f0..19b8fc1bf8 100644 --- a/crates/spirv-std/src/arch/barrier.rs +++ b/crates/spirv-std/src/arch/barrier.rs @@ -78,3 +78,114 @@ pub unsafe fn memory_barrier< semantics = const SEMANTICS, } } + +/// Blocks execution of all threads in a group until all group shared accesses have been completed. +/// +/// This is an exact implementation of `GroupMemoryBarrier()`. +/// +/// From +#[spirv_std_macros::gpu_only] +#[inline] +pub unsafe fn workgroup_memory_barrier() { + memory_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); +} + +/// Blocks execution of all threads in a group until all group shared accesses have been completed and all threads in the group have reached this call. +/// +/// This is an exact implementation of `GroupMemoryBarrierWithGroupSync()`. +/// +/// From +#[spirv_std_macros::gpu_only] +#[inline] +pub unsafe fn workgroup_memory_barrier_with_group_sync() { + control_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { crate::memory::Scope::Workgroup as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); +} + +/// Blocks execution of all threads in a group until all device memory accesses have been completed. +/// +/// This is an exact implementation of `DeviceMemoryBarrier()`. +/// +/// From +#[spirv_std_macros::gpu_only] +#[inline] +pub unsafe fn device_memory_barrier() { + memory_barrier::< + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); +} + +/// Blocks execution of all threads in a group until all device memory accesses have been completed and all threads in the group have reached this call. +/// +/// This is an exact implementation of `DeviceMemoryBarrierWithGroupSync()`. +/// +/// From +#[spirv_std_macros::gpu_only] +#[inline] +pub unsafe fn device_memory_barrier_with_group_sync() { + control_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); +} + +/// Blocks execution of all threads in a group until all memory accesses have been completed. +/// +/// This is an exact implementation of `AllMemoryBarrier()`. +/// +/// From +#[spirv_std_macros::gpu_only] +#[inline] +pub unsafe fn all_memory_barrier() { + memory_barrier::< + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); +} + +/// Blocks execution of all threads in a group until all memory accesses have been completed and all threads in the group have reached this call. +/// +/// This is an exact implementation of `AllMemoryBarrierWithGroupSync()`. +/// +/// From +#[spirv_std_macros::gpu_only] +#[inline] +pub unsafe fn all_memory_barrier_with_group_sync() { + control_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); +} diff --git a/tests/ui/arch/all_memory_barrier.rs b/tests/ui/arch/all_memory_barrier.rs new file mode 100644 index 0000000000..95f00ed306 --- /dev/null +++ b/tests/ui/arch/all_memory_barrier.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C target-feature=+VulkanMemoryModelDeviceScopeKHR,+ext:SPV_KHR_vulkan_memory_model +// compile-flags: -C llvm-args=--disassemble-fn=all_memory_barrier::all_memory_barrier + +use spirv_std as _; + +unsafe fn all_memory_barrier() { + spirv_std::arch::all_memory_barrier(); +} + +#[spirv(compute(threads(1, 1, 1)))] +pub fn main() { + unsafe { + all_memory_barrier(); + } +} diff --git a/tests/ui/arch/all_memory_barrier.stderr b/tests/ui/arch/all_memory_barrier.stderr new file mode 100644 index 0000000000..6c47c8a8ff --- /dev/null +++ b/tests/ui/arch/all_memory_barrier.stderr @@ -0,0 +1,7 @@ +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 72 4 +OpMemoryBarrier %6 %7 +OpLine %8 9 1 +OpReturn +OpFunctionEnd diff --git a/tests/ui/arch/all_memory_barrier_with_group_sync.rs b/tests/ui/arch/all_memory_barrier_with_group_sync.rs new file mode 100644 index 0000000000..ba05ad8ee6 --- /dev/null +++ b/tests/ui/arch/all_memory_barrier_with_group_sync.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C target-feature=+VulkanMemoryModelDeviceScopeKHR,+ext:SPV_KHR_vulkan_memory_model +// compile-flags: -C llvm-args=--disassemble-fn=all_memory_barrier_with_group_sync::all_memory_barrier_with_group_sync + +use spirv_std as _; + +unsafe fn all_memory_barrier_with_group_sync() { + spirv_std::arch::all_memory_barrier_with_group_sync(); +} + +#[spirv(compute(threads(1, 1, 1)))] +pub fn main() { + unsafe { + all_memory_barrier_with_group_sync(); + } +} diff --git a/tests/ui/arch/all_memory_barrier_with_group_sync.stderr b/tests/ui/arch/all_memory_barrier_with_group_sync.stderr new file mode 100644 index 0000000000..5661430745 --- /dev/null +++ b/tests/ui/arch/all_memory_barrier_with_group_sync.stderr @@ -0,0 +1,7 @@ +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 38 4 +OpControlBarrier %6 %7 %8 +OpLine %9 9 1 +OpReturn +OpFunctionEnd diff --git a/tests/ui/arch/device_memory_barrier.rs b/tests/ui/arch/device_memory_barrier.rs new file mode 100644 index 0000000000..0ffe4cfb29 --- /dev/null +++ b/tests/ui/arch/device_memory_barrier.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C target-feature=+VulkanMemoryModelDeviceScopeKHR,+ext:SPV_KHR_vulkan_memory_model +// compile-flags: -C llvm-args=--disassemble-fn=device_memory_barrier::device_memory_barrier + +use spirv_std as _; + +unsafe fn device_memory_barrier() { + spirv_std::arch::device_memory_barrier(); +} + +#[spirv(compute(threads(1, 1, 1)))] +pub fn main() { + unsafe { + device_memory_barrier(); + } +} diff --git a/tests/ui/arch/device_memory_barrier.stderr b/tests/ui/arch/device_memory_barrier.stderr new file mode 100644 index 0000000000..6c47c8a8ff --- /dev/null +++ b/tests/ui/arch/device_memory_barrier.stderr @@ -0,0 +1,7 @@ +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 72 4 +OpMemoryBarrier %6 %7 +OpLine %8 9 1 +OpReturn +OpFunctionEnd diff --git a/tests/ui/arch/device_memory_barrier_with_group_sync.rs b/tests/ui/arch/device_memory_barrier_with_group_sync.rs new file mode 100644 index 0000000000..cc17b78937 --- /dev/null +++ b/tests/ui/arch/device_memory_barrier_with_group_sync.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C target-feature=+VulkanMemoryModelDeviceScopeKHR,+ext:SPV_KHR_vulkan_memory_model +// compile-flags: -C llvm-args=--disassemble-fn=device_memory_barrier_with_group_sync::device_memory_barrier_with_group_sync + +use spirv_std as _; + +unsafe fn device_memory_barrier_with_group_sync() { + spirv_std::arch::device_memory_barrier_with_group_sync(); +} + +#[spirv(compute(threads(1, 1, 1)))] +pub fn main() { + unsafe { + device_memory_barrier_with_group_sync(); + } +} diff --git a/tests/ui/arch/device_memory_barrier_with_group_sync.stderr b/tests/ui/arch/device_memory_barrier_with_group_sync.stderr new file mode 100644 index 0000000000..5661430745 --- /dev/null +++ b/tests/ui/arch/device_memory_barrier_with_group_sync.stderr @@ -0,0 +1,7 @@ +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 38 4 +OpControlBarrier %6 %7 %8 +OpLine %9 9 1 +OpReturn +OpFunctionEnd diff --git a/tests/ui/arch/workgroup_memory_barrier.rs b/tests/ui/arch/workgroup_memory_barrier.rs new file mode 100644 index 0000000000..13216ab093 --- /dev/null +++ b/tests/ui/arch/workgroup_memory_barrier.rs @@ -0,0 +1,15 @@ +// build-pass +// compile-flags: -C llvm-args=--disassemble-fn=workgroup_memory_barrier::workgroup_memory_barrier + +use spirv_std as _; + +unsafe fn workgroup_memory_barrier() { + spirv_std::arch::workgroup_memory_barrier(); +} + +#[spirv(compute(threads(1, 1, 1)))] +pub fn main() { + unsafe { + workgroup_memory_barrier(); + } +} diff --git a/tests/ui/arch/workgroup_memory_barrier.stderr b/tests/ui/arch/workgroup_memory_barrier.stderr new file mode 100644 index 0000000000..6dc7539441 --- /dev/null +++ b/tests/ui/arch/workgroup_memory_barrier.stderr @@ -0,0 +1,7 @@ +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 72 4 +OpMemoryBarrier %6 %7 +OpLine %8 8 1 +OpReturn +OpFunctionEnd diff --git a/tests/ui/arch/workgroup_memory_barrier_with_group_sync.rs b/tests/ui/arch/workgroup_memory_barrier_with_group_sync.rs new file mode 100644 index 0000000000..0e16fbd8bc --- /dev/null +++ b/tests/ui/arch/workgroup_memory_barrier_with_group_sync.rs @@ -0,0 +1,15 @@ +// build-pass +// compile-flags: -C llvm-args=--disassemble-fn=workgroup_memory_barrier_with_group_sync::workgroup_memory_barrier_with_group_sync + +use spirv_std as _; + +unsafe fn workgroup_memory_barrier_with_group_sync() { + spirv_std::arch::workgroup_memory_barrier_with_group_sync(); +} + +#[spirv(compute(threads(1, 1, 1)))] +pub fn main() { + unsafe { + workgroup_memory_barrier_with_group_sync(); + } +} diff --git a/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr b/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr new file mode 100644 index 0000000000..d3fa886ff8 --- /dev/null +++ b/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr @@ -0,0 +1,7 @@ +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 38 4 +OpControlBarrier %6 %6 %7 +OpLine %8 8 1 +OpReturn +OpFunctionEnd