@@ -92,7 +92,23 @@ template<uint32_t StorageClass, typename T>
9292using pointer_t = vk::SpirvOpaqueType<spv::OpTypePointer,vk::Literal<vk::integral_constant<uint32_t,StorageClass> >,T>;
9393
9494template<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;
96112
97113
98114//! General Operations
@@ -116,7 +132,7 @@ template<typename T, typename U>
116132enable_if_t<!is_same_v<T,U>,T> copyLogical ([[vk::ext_reference]] U v);
117133template<typename T, typename Ptr_U>
118134[[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);
120136
121137// Here's the thing with atomics, it's not only the data type that dictates whether you can do an atomic or not.
122138// 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
126142
127143template<typename T, typename Ptr_T> // DXC Workaround
128144[[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);
130146
131147template<typename T> // integers operate on 2s complement so same op for signed and unsigned
132148[[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
136152template<typename T, typename Ptr_T> // DXC Workaround
137153[[vk::ext_capability (spv::CapabilityInt64Atomics)]]
138154[[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);
140156
141157template<typename T> // integers operate on 2s complement so same op for signed and unsigned
142158[[vk::ext_instruction (spv::OpAtomicISub)]]
143159enable_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);
144160
145161template<typename T, typename Ptr_T> // DXC Workaround
146162[[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);
148164
149165template<typename T> // integers operate on 2s complement so same op for signed and unsigned
150166[[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
154170template<typename T, typename Ptr_T> // DXC Workaround
155171[[vk::ext_capability (spv::CapabilityInt64Atomics)]]
156172[[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);
158174
159175template<typename T>
160176[[vk::ext_instruction (spv::OpAtomicAnd)]]
161177enable_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);
162178
163179template<typename T, typename Ptr_T> // DXC Workaround
164180[[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);
166182
167183template<typename T>
168184[[vk::ext_instruction (spv::OpAtomicOr)]]
169185enable_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);
170186
171187template<typename T, typename Ptr_T> // DXC Workaround
172188[[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);
174190
175191template<typename T>
176192[[vk::ext_instruction (spv::OpAtomicXor)]]
177193enable_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);
178194
179195template<typename T, typename Ptr_T> // DXC Workaround
180196[[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);
182198
183199template<typename Signed>
184200[[vk::ext_instruction ( spv::OpAtomicSMin )]]
185201enable_if_t<is_same_v<Signed,int32_t>, Signed> atomicSMin ([[vk::ext_reference]] int32_t ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
186202
187203template<typename Signed, typename Ptr_T> // DXC Workaround
188204[[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);
190206
191207template<typename Unsigned>
192208[[vk::ext_instruction ( spv::OpAtomicUMin )]]
193209enable_if_t<is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMin ([[vk::ext_reference]] Unsigned ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
194210
195211template<typename Unsigned, typename Ptr_T> // DXC Workaround
196212[[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);
198214
199215template<typename Signed>
200216[[vk::ext_instruction ( spv::OpAtomicSMax )]]
201217enable_if_t<is_same_v<Signed,int32_t>, Signed> atomicSMax ([[vk::ext_reference]] Signed ptr, uint32_t memoryScope, uint32_t memorySemantics, Signed value);
202218
203219template<typename Signed, typename Ptr_T> // DXC Workaround
204220[[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);
206222
207223template<typename Unsigned>
208224[[vk::ext_instruction ( spv::OpAtomicUMax )]]
209225enable_if_t<is_same_v<Unsigned,uint32_t>, Unsigned> atomicUMax ([[vk::ext_reference]] uint32_t ptr, uint32_t memoryScope, uint32_t memorySemantics, Unsigned value);
210226
211227template<typename Unsigned, typename Ptr_T> // DXC Workaround
212228[[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);
214230
215231template<typename T>
216232[[vk::ext_instruction (spv::OpAtomicExchange)]]
217233T atomicExchange ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memorySemantics, T value);
218234
219235template<typename T, typename Ptr_T> // DXC Workaround
220236[[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);
222238
223239template<typename T>
224240[[vk::ext_instruction (spv::OpAtomicCompareExchange)]]
225241T atomicCompareExchange ([[vk::ext_reference]] T ptr, uint32_t memoryScope, uint32_t memSemanticsEqual, uint32_t memSemanticsUnequal, T value, T comparator);
226242
227243template<typename T, typename Ptr_T> // DXC Workaround
228244[[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);
230246
231247
232248template<typename T, uint32_t alignment>
@@ -236,7 +252,7 @@ T load(bda_pointer_t<T> pointer, [[vk::ext_literal]] uint32_t __aligned = /*Alig
236252
237253template<typename T, typename P>
238254[[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);
240256
241257template<typename T, uint32_t alignment>
242258__NBL_CAPABILITY_PhysicalStorageBufferAddresses
@@ -245,7 +261,7 @@ void store(bda_pointer_t<T> pointer, T obj, [[vk::ext_literal]] uint32_t __align
245261
246262template<typename T, typename P>
247263[[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);
249265
250266// Memory Semantics link here: https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Memory_Semantics_-id-
251267
@@ -261,19 +277,10 @@ void memoryBarrier(uint32_t memoryScope, uint32_t memorySemantics);
261277// 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)
262278// TODO: better constraints, one should only be able to cast fundamental types, etc. https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpBitcast
263279#if 0
280+ // mutitple overloads should be possible
264281template<typename T, typename U>
265282[[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);
277284#endif
278285template<class T, class U>
279286[[vk::ext_instruction (spv::OpBitcast)]]
0 commit comments