spirv_std/memory.rs
1//! Types for handling memory ordering constraints for concurrent memory access.
2
3// NOTE(eddyb) "&-masking with zero", likely due to `NONE = 0` in `bitflags!`.
4#![allow(clippy::bad_bit_mask)]
5
6/// Specification for how large of a scope some instructions should operate on - used when calling
7/// functions that take a configurable scope.
8#[derive(Debug, PartialEq, Eq)]
9#[cfg_attr(feature = "adt_const_params", derive(core::marker::ConstParamTy))]
10#[repr(u32)]
11pub enum Scope {
12 /// Crosses multiple devices.
13 CrossDevice = 0,
14
15 /// The current device.
16 Device = 1,
17
18 /// The current workgroup.
19 Workgroup = 2,
20
21 /// The current subgroup.
22 Subgroup = 3,
23
24 /// The current invocation.
25 Invocation = 4,
26
27 /// The current queue family.
28 QueueFamily = 5,
29}
30
31/// Memory semantics to determine how some operations should function - used when calling such
32/// configurable operations.
33#[repr(transparent)]
34#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
35#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
36#[cfg_attr(feature = "adt_const_params", derive(core::marker::ConstParamTy))]
37pub struct Semantics(u32);
38
39bitflags::bitflags! {
40 impl Semantics: u32 {
41 /// No memory semantics.
42 const NONE = 0;
43
44 /// On an atomic instruction, orders memory operations provided in program
45 /// order after this atomic instruction against this atomic instruction. On
46 /// a barrier, orders memory operations provided in program order after this
47 /// barrier against atomic instructions before this barrier.
48 const ACQUIRE = 0x2;
49
50 /// On an atomic instruction, orders memory operations provided in program
51 /// order before this atomic instruction against this atomic instruction. On
52 /// a barrier, orders memory operations provided in program order before
53 /// this barrier against atomic instructions after this barrier.
54 const RELEASE = 0x4;
55
56 /// Has the properties of both [`Self::ACQUIRE`] and [`Self::RELEASE`] semantics. It
57 /// is used for read-modify-write operations.
58 const ACQUIRE_RELEASE = 0x8;
59
60 /// All observers see this memory access in the same order with respect to
61 /// other sequentially-consistent memory accesses from this invocation.
62 /// If the declared memory model is `vulkan`, `SEQUENTIALLY_CONST` must
63 /// not be used.
64 const SEQUENTIALLY_CONST = 0x10;
65
66 /// Apply the memory-ordering constraints to
67 /// [`crate::storage_class::StorageBuffer`],
68 /// [`crate::storage_class::PhysicalStorageBuffer`], or
69 /// [`crate::storage_class::Uniform`] Storage Class memory.
70 const UNIFORM_MEMORY = 0x40;
71
72 /// Apply the memory-ordering constraints to subgroup memory.
73 const SUBGROUP_MEMORY = 0x80;
74
75 /// Apply the memory-ordering constraints to
76 /// [`crate::storage_class::Workgroup`] Storage Class memory.
77 const WORKGROUP_MEMORY = 0x100;
78
79 /// Apply the memory-ordering constraints to
80 /// [`crate::storage_class::CrossWorkgroup`] Storage Class memory.
81 const CROSS_WORKGROUP_MEMORY = 0x200;
82
83 /// Apply the memory-ordering constraints to
84 /// [`crate::storage_class::AtomicCounter`] Storage Class memory.
85 const ATOMIC_COUNTER_MEMORY = 0x400;
86
87 /// Apply the memory-ordering constraints to image contents (types declared
88 /// by `OpTypeImage`), or to accesses done through pointers to the
89 /// [`crate::storage_class::Image`] Storage Class.
90 const IMAGE_MEMORY = 0x800;
91
92 /// Apply the memory-ordering constraints to the
93 /// [`crate::storage_class::Output`] Storage Class memory.
94 const OUTPUT_MEMORY = 0x1000;
95
96 /// Perform an availability operation on all references in the selected
97 /// storage classes.
98 const MAKE_AVAILABLE = 0x2000;
99
100 /// Perform a visibility operation on all references in the selected
101 /// storage classes.
102 const MAKE_VISIBLE = 0x4000;
103
104 /// This access cannot be eliminated, duplicated, or combined with
105 /// other accesses.
106 const VOLATILE = 0x8000;
107 }
108}
109
110impl Semantics {
111 const ORDERING_MASK: Semantics = Self::ACQUIRE
112 .union(Self::RELEASE)
113 .union(Self::ACQUIRE_RELEASE)
114 .union(Self::SEQUENTIALLY_CONST);
115
116 /// Verify whether the [`Semantics`] flags are valid
117 pub const fn assert_valid(self) {
118 assert!(
119 self.intersection(Self::ORDERING_MASK).bits().count_ones() <= 1,
120 "at most one memory-ordering flag (ACQUIRE, RELEASE, ACQUIRE_RELEASE or \
121 SEQUENTIALLY_CONST) may be set"
122 );
123 }
124}
125
126#[cfg(all(test, feature = "bytemuck"))]
127mod test_bytemuck {
128 fn is_pod<T: bytemuck::Pod>() {}
129
130 #[test]
131 fn test() {
132 is_pod::<crate::memory::Semantics>();
133 is_pod::<crate::ray_tracing::RayFlags>();
134 }
135}