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