@@ -92,7 +92,23 @@ template<uint32_t StorageClass, typename T>
92
92
using pointer_t = vk::SpirvOpaqueType<spv::OpTypePointer,vk::Literal<vk::integral_constant<uint32_t,StorageClass> >,T>;
93
93
94
94
template<typename T>
95
- using bda_pointer_t __NBL_CAPABILITY_PhysicalStorageBufferAddresses = vk::SpirvType<spv::OpTypePointer, sizeof (uint64_t),/*alignof(uint64_t)*/ 8 , vk::Literal<vk::integral_constant<uint32_t, spv::StorageClassPhysicalStorageBuffer> >, T>;
95
+ struct is_pointer : false_type {};
96
+ template<typename I, I StorageClass, typename TT>
97
+ struct is_pointer<vk::SpirvOpaqueType<spv::OpTypePointer,vk::Literal<vk::integral_constant<I,StorageClass> >,TT> > : is_integral<I> {};
98
+ template<uint32_t Size, uint32_t Alignment, typename I, I StorageClass, typename TT>
99
+ struct is_pointer<vk::SpirvType<spv::OpTypePointer,Size,Alignment,vk::Literal<vk::integral_constant<I,StorageClass> >,TT> > : is_integral<I> {};
100
+ template<class T>
101
+ NBL_CONSTEXPR_STATIC_INLINE bool is_pointer_v = is_pointer<T>::value;
102
+
103
+ template<typename T>
104
+ using bda_pointer_t __NBL_CAPABILITY_PhysicalStorageBufferAddresses = vk::SpirvType<spv::OpTypePointer, sizeof (uint64_t),alignment_of_v<uint64_t>, vk::Literal<vk::integral_constant<uint32_t, spv::StorageClassPhysicalStorageBuffer> >, T>;
105
+
106
+ template<typename T>
107
+ struct is_bda_pointer : false_type {};
108
+ template<typename I, typename TT>
109
+ struct is_pointer<vk::SpirvType<spv::OpTypePointer,sizeof (uint64_t),alignment_of_v<uint64_t>,vk::Literal<vk::integral_constant<I, spv::StorageClassPhysicalStorageBuffer> >, TT> > : is_integral<I> {};
110
+ template<class T>
111
+ NBL_CONSTEXPR_STATIC_INLINE bool is_bda_pointer_v = is_bda_pointer<T>::value;
96
112
97
113
98
114
//! General Operations
@@ -116,7 +132,7 @@ template<typename T, typename U>
116
132
enable_if_t<!is_same_v<T,U>,T> copyLogical ([[vk::ext_reference]] U v);
117
133
template<typename T, typename Ptr_U>
118
134
[[vk::ext_instruction (spv::OpCopyLogical)]]
119
- enable_if_t<is_spirv_type_v <Ptr_U>/* && !is_same_v<T,U>*/ ,T> copyLogical (Ptr_U v);
135
+ enable_if_t<is_pointer_v <Ptr_U>/* && !is_same_v<T,U>*/ ,T> copyLogical (Ptr_U v);
120
136
121
137
// Here's the thing with atomics, it's not only the data type that dictates whether you can do an atomic or not.
122
138
// It's the storage class that has the most effect (shared vs storage vs image) and we can't check that easily
@@ -126,7 +142,7 @@ enable_if_t<is_same_v<T,uint32_t> || is_same_v<T,int32_t>, T> atomicIAdd([[vk::e
126
142
127
143
template<typename T, typename Ptr_T> // DXC Workaround
128
144
[[vk::ext_instruction (spv::OpAtomicIAdd)]]
129
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicIAdd (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
145
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicIAdd (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
130
146
131
147
template<typename T> // integers operate on 2s complement so same op for signed and unsigned
132
148
[[vk::ext_capability (spv::CapabilityInt64Atomics)]]
@@ -136,15 +152,15 @@ enable_if_t<is_same_v<T,uint64_t> || is_same_v<T,int64_t>, T> atomicIAdd([[vk::e
136
152
template<typename T, typename Ptr_T> // DXC Workaround
137
153
[[vk::ext_capability (spv::CapabilityInt64Atomics)]]
138
154
[[vk::ext_instruction (spv::OpAtomicIAdd)]]
139
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint64_t> || is_same_v<T,int64_t>), T> atomicIAdd (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
155
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint64_t> || is_same_v<T,int64_t>), T> atomicIAdd (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
140
156
141
157
template<typename T> // integers operate on 2s complement so same op for signed and unsigned
142
158
[[vk::ext_instruction (spv::OpAtomicISub)]]
143
159
enable_if_t<is_same_v<T,uint32_t> || is_same_v<T,int32_t>, T> atomicISub ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
144
160
145
161
template<typename T, typename Ptr_T> // DXC Workaround
146
162
[[vk::ext_instruction (spv::OpAtomicISub)]]
147
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicISub (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
163
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicISub (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
148
164
149
165
template<typename T> // integers operate on 2s complement so same op for signed and unsigned
150
166
[[vk::ext_capability (spv::CapabilityInt64Atomics)]]
@@ -154,79 +170,79 @@ enable_if_t<is_same_v<T,uint64_t> || is_same_v<T,int64_t>, T> atomicISub([[vk::e
154
170
template<typename T, typename Ptr_T> // DXC Workaround
155
171
[[vk::ext_capability (spv::CapabilityInt64Atomics)]]
156
172
[[vk::ext_instruction (spv::OpAtomicISub)]]
157
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint64_t> || is_same_v<T,int64_t>), T> atomicISub (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
173
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint64_t> || is_same_v<T,int64_t>), T> atomicISub (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
158
174
159
175
template<typename T>
160
176
[[vk::ext_instruction (spv::OpAtomicAnd)]]
161
177
enable_if_t<is_same_v<T,uint32_t> || is_same_v<T,int32_t>, T> atomicAnd ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
162
178
163
179
template<typename T, typename Ptr_T> // DXC Workaround
164
180
[[vk::ext_instruction (spv::OpAtomicAnd)]]
165
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicAnd (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
181
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicAnd (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
166
182
167
183
template<typename T>
168
184
[[vk::ext_instruction (spv::OpAtomicOr)]]
169
185
enable_if_t<is_same_v<T,uint32_t> || is_same_v<T,int32_t>, T> atomicOr ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
170
186
171
187
template<typename T, typename Ptr_T> // DXC Workaround
172
188
[[vk::ext_instruction (spv::OpAtomicOr)]]
173
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicOr (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
189
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicOr (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
174
190
175
191
template<typename T>
176
192
[[vk::ext_instruction (spv::OpAtomicXor)]]
177
193
enable_if_t<is_same_v<T,uint32_t> || is_same_v<T,int32_t>, T> atomicXor ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
178
194
179
195
template<typename T, typename Ptr_T> // DXC Workaround
180
196
[[vk::ext_instruction (spv::OpAtomicXor)]]
181
- enable_if_t<is_spirv_type_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicXor (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
197
+ enable_if_t<is_pointer_v <Ptr_T> && (is_same_v<T,uint32_t> || is_same_v<T,int32_t>), T> atomicXor (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
182
198
183
199
template<typename Signed>
184
200
[[vk::ext_instruction ( spv::OpAtomicSMin )]]
185
201
enable_if_t<is_same_v<Signed,int32_t>, Signed> atomicSMin ([[vk::ext_reference]] int32_t ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
186
202
187
203
template<typename Signed, typename Ptr_T> // DXC Workaround
188
204
[[vk::ext_instruction (spv::OpAtomicSMin)]]
189
- enable_if_t<is_spirv_type_v <Ptr_T> && is_same_v<Signed,int32_t>, Signed> atomicSMin (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
205
+ enable_if_t<is_pointer_v <Ptr_T> && is_same_v<Signed,int32_t>, Signed> atomicSMin (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
190
206
191
207
template<typename Unsigned>
192
208
[[vk::ext_instruction ( spv::OpAtomicUMin )]]
193
209
enable_if_t<is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMin ([[vk::ext_reference]] Unsigned ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
194
210
195
211
template<typename Unsigned, typename Ptr_T> // DXC Workaround
196
212
[[vk::ext_instruction (spv::OpAtomicUMin)]]
197
- enable_if_t<is_spirv_type_v <Ptr_T> && is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMin (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
213
+ enable_if_t<is_pointer_v <Ptr_T> && is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMin (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
198
214
199
215
template<typename Signed>
200
216
[[vk::ext_instruction ( spv::OpAtomicSMax )]]
201
217
enable_if_t<is_same_v<Signed,int32_t>, Signed> atomicSMax ([[vk::ext_reference]] Signed ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
202
218
203
219
template<typename Signed, typename Ptr_T> // DXC Workaround
204
220
[[vk::ext_instruction (spv::OpAtomicSMax)]]
205
- enable_if_t<is_spirv_type_v <Ptr_T> && is_same_v<Signed,int32_t>, Signed> atomicSMax (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
221
+ enable_if_t<is_pointer_v <Ptr_T> && is_same_v<Signed,int32_t>, Signed> atomicSMax (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
206
222
207
223
template<typename Unsigned>
208
224
[[vk::ext_instruction ( spv::OpAtomicUMax )]]
209
225
enable_if_t<is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMax ([[vk::ext_reference]] uint32_t ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
210
226
211
227
template<typename Unsigned, typename Ptr_T> // DXC Workaround
212
228
[[vk::ext_instruction (spv::OpAtomicUMax)]]
213
- enable_if_t<is_spirv_type_v <Ptr_T> && is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMax (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
229
+ enable_if_t<is_pointer_v <Ptr_T> && is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMax (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
214
230
215
231
template<typename T>
216
232
[[vk::ext_instruction (spv::OpAtomicExchange)]]
217
233
T atomicExchange ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
218
234
219
235
template<typename T, typename Ptr_T> // DXC Workaround
220
236
[[vk::ext_instruction (spv::OpAtomicExchange)]]
221
- enable_if_t<is_spirv_type_v <Ptr_T>, T> atomicExchange (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
237
+ enable_if_t<is_pointer_v <Ptr_T>, T> atomicExchange (Ptr_T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
222
238
223
239
template<typename T>
224
240
[[vk::ext_instruction (spv::OpAtomicCompareExchange)]]
225
241
T atomicCompareExchange ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memSemanticsEqual, uint32_t memSemanticsUnequal, T value, T comparator);
226
242
227
243
template<typename T, typename Ptr_T> // DXC Workaround
228
244
[[vk::ext_instruction (spv::OpAtomicCompareExchange)]]
229
- enable_if_t<is_spirv_type_v <Ptr_T>, T> atomicCompareExchange (Ptr_T ptr, uint32_t memoryScope, uint32_t memSemanticsEqual, uint32_t memSemanticsUnequal, T value, T comparator);
245
+ enable_if_t<is_pointer_v <Ptr_T>, T> atomicCompareExchange (Ptr_T ptr, uint32_t memoryScope, uint32_t memSemanticsEqual, uint32_t memSemanticsUnequal, T value, T comparator);
230
246
231
247
232
248
template<typename T, uint32_t alignment>
@@ -236,7 +252,7 @@ T load(bda_pointer_t<T> pointer, [[vk::ext_literal]] uint32_t __aligned = /*Alig
236
252
237
253
template<typename T, typename P>
238
254
[[vk::ext_instruction (spv::OpLoad)]]
239
- enable_if_t<is_spirv_type_v <P>,T> load (P pointer);
255
+ enable_if_t<is_pointer_v <P>,T> load (P pointer);
240
256
241
257
template<typename T, uint32_t alignment>
242
258
__NBL_CAPABILITY_PhysicalStorageBufferAddresses
@@ -245,7 +261,7 @@ void store(bda_pointer_t<T> pointer, T obj, [[vk::ext_literal]] uint32_t __align
245
261
246
262
template<typename T, typename P>
247
263
[[vk::ext_instruction (spv::OpStore)]]
248
- enable_if_t<is_spirv_type_v <P>,void > store (P pointer, T obj);
264
+ enable_if_t<is_pointer_v <P>,void > store (P pointer, T obj);
249
265
250
266
// Memory Semantics link here: https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Memory_Semantics_-id-
251
267
@@ -261,19 +277,10 @@ void memoryBarrier(uint32_t memoryScope, uint32_t memorySemantics);
261
277
// Add specializations if you need to emit a `ext_capability` (this means that the instruction needs to forward through an `impl::` struct and so on)
262
278
// TODO: better constraints, one should only be able to cast fundamental types, etc. https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpBitcast
263
279
#if 0
280
+ // mutitple overloads should be possible
264
281
template<typename T, typename U>
265
282
[[vk::ext_instruction (spv::OpBitcast)]]
266
- enable_if_t<is_spirv_type_v<T> && is_spirv_type_v<U>, T> bitcast (U);
267
-
268
- template<typename U, typename T>
269
- __NBL_CAPABILITY_PhysicalStorageBufferAddresses
270
- [[vk::ext_instruction (spv::OpBitcast)]]
271
- enable_if_t<is_same_v<U,uint64_t2>||is_same_v<U,uint32_t2>,U> bitcast (bda_pointer_t<T>);
272
-
273
- template<typename T, typename U>
274
- __NBL_CAPABILITY_PhysicalStorageBufferAddresses
275
- [[vk::ext_instruction (spv::OpBitcast)]]
276
- enable_if_t<is_same_v<U,uint64_t2>||is_same_v<U,uint32_t2>,bda_pointer_t<T> > bitcast (U);
283
+ enable_if_t<TODO: CONDITIONS, T> bitcast (U);
277
284
#endif
278
285
template<class T, class U>
279
286
[[vk::ext_instruction (spv::OpBitcast)]]
0 commit comments