12
12
#include < CL/__spirv/spirv_vars.hpp>
13
13
#include < CL/sycl/detail/generic_type_traits.hpp>
14
14
#include < CL/sycl/detail/type_traits.hpp>
15
+ #include < CL/sycl/intel/atomic_enums.hpp>
15
16
16
17
#ifdef __SYCL_DEVICE_ONLY__
17
18
__SYCL_INLINE_NAMESPACE (cl) {
@@ -28,7 +29,7 @@ template <int Dimensions> struct group_scope<group<Dimensions>> {
28
29
static constexpr __spv::Scope::Flag value = __spv::Scope::Flag::Workgroup;
29
30
};
30
31
31
- template <> struct group_scope <intel::sub_group> {
32
+ template <> struct group_scope <::cl::sycl:: intel::sub_group> {
32
33
static constexpr __spv::Scope::Flag value = __spv::Scope::Flag::Subgroup;
33
34
};
34
35
@@ -69,6 +70,226 @@ T GroupBroadcast(T x, id<Dimensions> local_id) {
69
70
return __spirv_GroupBroadcast (group_scope<Group>::value, ocl_x, ocl_id);
70
71
}
71
72
73
+ // Single happens-before means semantics should always apply to all spaces
74
+ // Although consume is unsupported, forwarding to acquire is valid
75
+ static inline constexpr __spv::MemorySemanticsMask::Flag
76
+ getMemorySemanticsMask (intel::memory_order Order) {
77
+ __spv::MemorySemanticsMask::Flag SpvOrder = __spv::MemorySemanticsMask::None;
78
+ switch (Order) {
79
+ case intel::memory_order::relaxed:
80
+ SpvOrder = __spv::MemorySemanticsMask::None;
81
+ break ;
82
+ case intel::memory_order::__consume_unsupported:
83
+ case intel::memory_order::acquire:
84
+ SpvOrder = __spv::MemorySemanticsMask::Acquire;
85
+ break ;
86
+ case intel::memory_order::release:
87
+ SpvOrder = __spv::MemorySemanticsMask::Release;
88
+ break ;
89
+ case intel::memory_order::acq_rel:
90
+ SpvOrder = __spv::MemorySemanticsMask::AcquireRelease;
91
+ break ;
92
+ case intel::memory_order::seq_cst:
93
+ SpvOrder = __spv::MemorySemanticsMask::SequentiallyConsistent;
94
+ break ;
95
+ }
96
+ return static_cast <__spv::MemorySemanticsMask::Flag>(
97
+ SpvOrder | __spv::MemorySemanticsMask::SubgroupMemory |
98
+ __spv::MemorySemanticsMask::WorkgroupMemory |
99
+ __spv::MemorySemanticsMask::CrossWorkgroupMemory);
100
+ }
101
+
102
+ static inline constexpr __spv::Scope::Flag getScope (intel::memory_scope Scope) {
103
+ switch (Scope) {
104
+ case intel::memory_scope::work_item:
105
+ return __spv::Scope::Invocation;
106
+ case intel::memory_scope::sub_group:
107
+ return __spv::Scope::Subgroup;
108
+ case intel::memory_scope::work_group:
109
+ return __spv::Scope::Workgroup;
110
+ case intel::memory_scope::device:
111
+ return __spv::Scope::Device;
112
+ case intel::memory_scope::system:
113
+ return __spv::Scope::CrossDevice;
114
+ }
115
+ }
116
+
117
+ template <typename T, access::address_space AddressSpace>
118
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
119
+ AtomicCompareExchange (multi_ptr<T, AddressSpace> MPtr,
120
+ intel::memory_scope Scope, intel::memory_order Success,
121
+ intel::memory_order Failure, T Desired, T Expected) {
122
+ auto SPIRVSuccess = getMemorySemanticsMask (Success);
123
+ auto SPIRVFailure = getMemorySemanticsMask (Failure);
124
+ auto SPIRVScope = getScope (Scope);
125
+ auto *Ptr = MPtr.get ();
126
+ return __spirv_AtomicCompareExchange (Ptr, SPIRVScope, SPIRVSuccess,
127
+ SPIRVFailure, Desired, Expected);
128
+ }
129
+
130
+ template <typename T, access::address_space AddressSpace>
131
+ inline typename detail::enable_if_t <std::is_floating_point<T>::value, T>
132
+ AtomicCompareExchange (multi_ptr<T, AddressSpace> MPtr,
133
+ intel::memory_scope Scope, intel::memory_order Success,
134
+ intel::memory_order Failure, T Desired, T Expected) {
135
+ using I = detail::make_unsinged_integer_t <T>;
136
+ auto SPIRVSuccess = getMemorySemanticsMask (Success);
137
+ auto SPIRVFailure = getMemorySemanticsMask (Failure);
138
+ auto SPIRVScope = getScope (Scope);
139
+ auto *PtrInt =
140
+ reinterpret_cast <typename multi_ptr<I, AddressSpace>::pointer_t >(
141
+ MPtr.get ());
142
+ I DesiredInt = detail::bit_cast<I>(Desired);
143
+ I ExpectedInt = detail::bit_cast<I>(Expected);
144
+ I ResultInt = __spirv_AtomicCompareExchange (
145
+ PtrInt, SPIRVScope, SPIRVSuccess, SPIRVFailure, DesiredInt, ExpectedInt);
146
+ return detail::bit_cast<T>(ResultInt);
147
+ }
148
+
149
+ template <typename T, access::address_space AddressSpace>
150
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
151
+ AtomicLoad (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
152
+ intel::memory_order Order) {
153
+ auto *Ptr = MPtr.get ();
154
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
155
+ auto SPIRVScope = getScope (Scope);
156
+ return __spirv_AtomicLoad (Ptr, SPIRVScope, SPIRVOrder);
157
+ }
158
+
159
+ template <typename T, access::address_space AddressSpace>
160
+ inline typename detail::enable_if_t <std::is_floating_point<T>::value, T>
161
+ AtomicLoad (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
162
+ intel::memory_order Order) {
163
+ using I = detail::make_unsinged_integer_t <T>;
164
+ auto *PtrInt =
165
+ reinterpret_cast <typename multi_ptr<I, AddressSpace>::pointer_t >(
166
+ MPtr.get ());
167
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
168
+ auto SPIRVScope = getScope (Scope);
169
+ I ResultInt = __spirv_AtomicLoad (PtrInt, SPIRVScope, SPIRVOrder);
170
+ return detail::bit_cast<T>(ResultInt);
171
+ }
172
+
173
+ template <typename T, access::address_space AddressSpace>
174
+ inline typename detail::enable_if_t <std::is_integral<T>::value>
175
+ AtomicStore (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
176
+ intel::memory_order Order, T Value) {
177
+ auto *Ptr = MPtr.get ();
178
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
179
+ auto SPIRVScope = getScope (Scope);
180
+ __spirv_AtomicStore (Ptr, SPIRVScope, SPIRVOrder, Value);
181
+ }
182
+
183
+ template <typename T, access::address_space AddressSpace>
184
+ inline typename detail::enable_if_t <std::is_floating_point<T>::value>
185
+ AtomicStore (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
186
+ intel::memory_order Order, T Value) {
187
+ using I = detail::make_unsinged_integer_t <T>;
188
+ auto *PtrInt =
189
+ reinterpret_cast <typename multi_ptr<I, AddressSpace>::pointer_t >(
190
+ MPtr.get ());
191
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
192
+ auto SPIRVScope = getScope (Scope);
193
+ I ValueInt = detail::bit_cast<I>(Value);
194
+ __spirv_AtomicStore (PtrInt, SPIRVScope, SPIRVOrder, ValueInt);
195
+ }
196
+
197
+ template <typename T, access::address_space AddressSpace>
198
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
199
+ AtomicExchange (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
200
+ intel::memory_order Order, T Value) {
201
+ auto *Ptr = MPtr.get ();
202
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
203
+ auto SPIRVScope = getScope (Scope);
204
+ return __spirv_AtomicExchange (Ptr, SPIRVScope, SPIRVOrder, Value);
205
+ }
206
+
207
+ template <typename T, access::address_space AddressSpace>
208
+ inline typename detail::enable_if_t <std::is_floating_point<T>::value, T>
209
+ AtomicExchange (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
210
+ intel::memory_order Order, T Value) {
211
+ using I = detail::make_unsinged_integer_t <T>;
212
+ auto *PtrInt =
213
+ reinterpret_cast <typename multi_ptr<I, AddressSpace>::pointer_t >(
214
+ MPtr.get ());
215
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
216
+ auto SPIRVScope = getScope (Scope);
217
+ I ValueInt = detail::bit_cast<I>(Value);
218
+ I ResultInt =
219
+ __spirv_AtomicExchange (PtrInt, SPIRVScope, SPIRVOrder, ValueInt);
220
+ return detail::bit_cast<T>(ResultInt);
221
+ }
222
+
223
+ template <typename T, access::address_space AddressSpace>
224
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
225
+ AtomicIAdd (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
226
+ intel::memory_order Order, T Value) {
227
+ auto *Ptr = MPtr.get ();
228
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
229
+ auto SPIRVScope = getScope (Scope);
230
+ return __spirv_AtomicIAdd (Ptr, SPIRVScope, SPIRVOrder, Value);
231
+ }
232
+
233
+ template <typename T, access::address_space AddressSpace>
234
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
235
+ AtomicISub (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
236
+ intel::memory_order Order, T Value) {
237
+ auto *Ptr = MPtr.get ();
238
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
239
+ auto SPIRVScope = getScope (Scope);
240
+ return __spirv_AtomicISub (Ptr, SPIRVScope, SPIRVOrder, Value);
241
+ }
242
+
243
+ template <typename T, access::address_space AddressSpace>
244
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
245
+ AtomicAnd (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
246
+ intel::memory_order Order, T Value) {
247
+ auto *Ptr = MPtr.get ();
248
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
249
+ auto SPIRVScope = getScope (Scope);
250
+ return __spirv_AtomicAnd (Ptr, SPIRVScope, SPIRVOrder, Value);
251
+ }
252
+
253
+ template <typename T, access::address_space AddressSpace>
254
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
255
+ AtomicOr (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
256
+ intel::memory_order Order, T Value) {
257
+ auto *Ptr = MPtr.get ();
258
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
259
+ auto SPIRVScope = getScope (Scope);
260
+ return __spirv_AtomicOr (Ptr, SPIRVScope, SPIRVOrder, Value);
261
+ }
262
+
263
+ template <typename T, access::address_space AddressSpace>
264
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
265
+ AtomicXor (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
266
+ intel::memory_order Order, T Value) {
267
+ auto *Ptr = MPtr.get ();
268
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
269
+ auto SPIRVScope = getScope (Scope);
270
+ return __spirv_AtomicXor (Ptr, SPIRVScope, SPIRVOrder, Value);
271
+ }
272
+
273
+ template <typename T, access::address_space AddressSpace>
274
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
275
+ AtomicMin (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
276
+ intel::memory_order Order, T Value) {
277
+ auto *Ptr = MPtr.get ();
278
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
279
+ auto SPIRVScope = getScope (Scope);
280
+ return __spirv_AtomicMin (Ptr, SPIRVScope, SPIRVOrder, Value);
281
+ }
282
+
283
+ template <typename T, access::address_space AddressSpace>
284
+ inline typename detail::enable_if_t <std::is_integral<T>::value, T>
285
+ AtomicMax (multi_ptr<T, AddressSpace> MPtr, intel::memory_scope Scope,
286
+ intel::memory_order Order, T Value) {
287
+ auto *Ptr = MPtr.get ();
288
+ auto SPIRVOrder = getMemorySemanticsMask (Order);
289
+ auto SPIRVScope = getScope (Scope);
290
+ return __spirv_AtomicMax (Ptr, SPIRVScope, SPIRVOrder, Value);
291
+ }
292
+
72
293
} // namespace spirv
73
294
} // namespace detail
74
295
} // namespace sycl
0 commit comments