-
Notifications
You must be signed in to change notification settings - Fork 248
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add memory_barrier and control_barrier (#519)
- Loading branch information
1 parent
40359bd
commit dd60da0
Showing
6 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use crate::memory::{Scope, Semantics}; | ||
|
||
/// Wait for other invocations of this module to reach the current point | ||
/// of execution. | ||
/// | ||
/// All invocations of this module within Execution scope reach this point of | ||
/// execution before any invocation proceeds beyond it. | ||
/// | ||
/// When Execution is [`Scope::Workgroup`] or larger, behavior is undefined | ||
/// unless all invocations within Execution execute the same dynamic instance of | ||
/// this instruction. When Execution is Subgroup or Invocation, the behavior of | ||
/// this instruction in non-uniform control flow is defined by the client API. | ||
/// | ||
/// If [`Semantics`] is not [`Semantics::None`], this instruction also serves as | ||
/// an [`memory_barrier`] function call, and also performs and adheres to the | ||
/// description and semantics of an [`memory_barrier`] function with the same | ||
/// `MEMORY` and `SEMANTICS` operands. This allows atomically specifying both a | ||
/// control barrier and a memory barrier (that is, without needing two | ||
/// instructions). If [`Semantics`] is [`Semantics::None`], `MEMORY` is ignored. | ||
/// | ||
/// Before SPIRV-V version 1.3, it is only valid to use this instruction with | ||
/// `TessellationControl`, `GLCompute`, or `Kernel` execution models. There is | ||
/// no such restriction starting with version 1.3. | ||
/// | ||
/// If used with the `TessellationControl` execution model, it also implicitly | ||
/// synchronizes the [`crate::storage_class::Output`] Storage Class: Writes to | ||
/// `Output` variables performed by any invocation executed prior to a | ||
/// [`control_barrier`] are visible to any other invocation proceeding beyond | ||
/// that [`control_barrier`]. | ||
#[spirv_std_macros::gpu_only] | ||
#[doc(alias = "OpControlBarrier")] | ||
#[inline] | ||
pub unsafe fn control_barrier< | ||
const EXECUTION: Scope, | ||
const MEMORY: Scope, | ||
const SEMANTICS: Semantics, | ||
>() { | ||
asm! { | ||
"%u32 = OpTypeInt 32 0", | ||
"%execution = OpConstant %u32 {execution}", | ||
"%memory = OpConstant %u32 {memory}", | ||
"%semantics = OpConstant %u32 {semantics}", | ||
"OpControlBarrier %execution %memory %semantics", | ||
execution = const EXECUTION as u8, | ||
memory = const MEMORY as u8, | ||
semantics = const SEMANTICS as u8, | ||
} | ||
} | ||
|
||
/// Control the order that memory accesses are observed. | ||
/// | ||
/// Ensures that memory accesses issued before this instruction are observed | ||
/// before memory accesses issued after this instruction. This control is | ||
/// ensured only for memory accesses issued by this invocation and observed by | ||
/// another invocation executing within `MEMORY` scope. If the `vulkan` memory | ||
/// model is declared, this ordering only applies to memory accesses that | ||
/// use the `NonPrivatePointer` memory operand or `NonPrivateTexel` | ||
/// image operand. | ||
/// | ||
/// `SEMANTICS` declares what kind of memory is being controlled and what kind | ||
/// of control to apply. | ||
/// | ||
/// To execute both a memory barrier and a control barrier, | ||
/// see [`control_barrier`]. | ||
#[spirv_std_macros::gpu_only] | ||
#[doc(alias = "OpMemoryBarrier")] | ||
#[inline] | ||
pub unsafe fn memory_barrier<const MEMORY: Scope, const SEMANTICS: Semantics>() { | ||
asm! { | ||
"%u32 = OpTypeInt 32 0", | ||
"%memory = OpConstant %u32 {memory}", | ||
"%semantics = OpConstant %u32 {semantics}", | ||
"OpMemoryBarrier %memory %semantics", | ||
memory = const MEMORY as u8, | ||
semantics = const SEMANTICS as u8, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
//! Types for handling memory ordering constraints for concurrent memory access. | ||
#[derive(Debug, PartialEq, Eq)] | ||
pub enum Scope { | ||
/// Crosses multiple devices. | ||
CrossDevice = 0, | ||
|
||
/// The current device. | ||
Device = 1, | ||
|
||
/// The current workgroup. | ||
Workgroup = 2, | ||
|
||
/// The current subgroup. | ||
Subgroup = 3, | ||
|
||
/// The current invocation. | ||
Invocation = 4, | ||
|
||
/// The current queue family. | ||
QueueFamily = 5, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Eq)] | ||
pub enum Semantics { | ||
/// No memory semantics. | ||
None = 0, | ||
|
||
/// On an atomic instruction, orders memory operations provided in program | ||
/// order after this atomic instruction against this atomic instruction. On | ||
/// a barrier, orders memory operations provided in program order after this | ||
/// barrier against atomic instructions before this barrier. | ||
Acquire = 0x2, | ||
|
||
/// On an atomic instruction, orders memory operations provided in program | ||
/// order before this atomic instruction against this atomic instruction. On | ||
/// a barrier, orders memory operations provided in program order before | ||
/// this barrier against atomic instructions after this barrier. | ||
Release = 0x4, | ||
|
||
/// Has the properties of both [`Self::Acquire`] and [`Self::Release`] semantics. It | ||
/// is used for read-modify-write operations. | ||
AcquireRelease = 0x8, | ||
|
||
/// All observers see this memory access in the same order with respect to | ||
/// other sequentially-consistent memory accesses from this invocation. | ||
/// If the declared memory model is `vulkan`, `SequentiallyConsistent` must | ||
/// not be used. | ||
SequentiallyConsistent = 0x10, | ||
|
||
/// Apply the memory-ordering constraints to | ||
/// [`crate::storage_class::StorageBuffer`], | ||
/// [`crate::storage_class::PhysicalStorageBuffer`], or | ||
/// [`crate::storage_class::Uniform`] Storage Class memory. | ||
UniformMemory = 0x40, | ||
|
||
/// Apply the memory-ordering constraints to subgroup memory. | ||
SubgroupMemory = 0x80, | ||
|
||
/// Apply the memory-ordering constraints to | ||
/// [`crate::storage_class::Workgroup`] Storage Class memory. | ||
WorkgroupMemory = 0x100, | ||
|
||
/// Apply the memory-ordering constraints to | ||
/// [`crate::storage_class::CrossWorkgroup`] Storage Class memory. | ||
CrossWorkgroupMemory = 0x200, | ||
|
||
/// Apply the memory-ordering constraints to | ||
/// [`crate::storage_class::AtomicCounter`] Storage Class memory. | ||
AtomicCounterMemory = 0x400, | ||
|
||
/// Apply the memory-ordering constraints to image contents (types declared | ||
/// by `OpTypeImage`), or to accesses done through pointers to the | ||
/// [`crate::storage_class::Image`] Storage Class. | ||
ImageMemory = 0x800, | ||
|
||
/// Apply the memory-ordering constraints to the | ||
/// [`crate::storage_class::Output`] Storage Class memory. | ||
OutputMemory = 0x1000, | ||
|
||
/// Perform an availability operation on all references in the selected | ||
/// storage classes. | ||
MakeAvailable = 0x2000, | ||
|
||
/// Perform a visibility operation on all references in the selected | ||
/// storage classes. | ||
MakeVisible = 0x4000, | ||
|
||
/// This access cannot be eliminated, duplicated, or combined with | ||
/// other accesses. | ||
Volatile = 0x8000, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// build-pass | ||
|
||
#![feature(const_generics)] | ||
#![allow(incomplete_features)] | ||
|
||
use spirv_std::memory::{Scope, Semantics}; | ||
|
||
#[spirv(fragment)] | ||
pub fn main() { | ||
unsafe { | ||
spirv_std::arch::control_barrier::< | ||
{ Scope::Workgroup }, | ||
{ Scope::Workgroup }, | ||
{ Semantics::None }, | ||
>(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// build-pass | ||
|
||
#![feature(const_generics)] | ||
#![allow(incomplete_features)] | ||
|
||
use spirv_std::memory::{Scope, Semantics}; | ||
|
||
#[spirv(fragment)] | ||
pub fn main() { | ||
unsafe { | ||
spirv_std::arch::memory_barrier::< | ||
{ Scope::Workgroup }, | ||
{ Semantics::None }, | ||
>(); | ||
} | ||
} |