Skip to main content

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}