Skip to content

Commit 8e771d0

Browse files
committed
Some spirv intrinsic function will work with vectors now
1 parent e0e1b8c commit 8e771d0

File tree

2 files changed

+235
-46
lines changed

2 files changed

+235
-46
lines changed

include/nbl/builtin/hlsl/cpp_compat/intrinsics.hlsl

Lines changed: 210 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ inline int bitCount(NBL_CONST_REF_ARG(Integer) val)
2525
#ifdef __HLSL_VERSION
2626
if (sizeof(Integer) == 8u)
2727
{
28-
uint32_t lowBits = val;
29-
uint32_t highBits = val >> 32u;
28+
uint32_t lowBits = uint32_t(val);
29+
uint32_t highBits = uint32_t(uint64_t(val) >> 32u);
3030

3131
return countbits(lowBits) + countbits(highBits);
3232
}
@@ -125,57 +125,198 @@ inline T determinant(NBL_CONST_REF_ARG(matrix<T, N, N>) m)
125125
#endif
126126
}
127127

128-
template<typename Integer>
129-
int findLSB(NBL_CONST_REF_ARG(Integer) val)
128+
namespace cpp_compat_intrinsics_impl
130129
{
130+
131131
#ifdef __HLSL_VERSION
132-
return spirv::findILsb(val);
132+
template<typename Integer>
133+
struct find_msb_helper;
133134
#else
134-
if (is_signed_v<Integer>)
135+
// legacy code wouldn't work without it
136+
template<typename Integer>
137+
struct find_msb_helper
138+
{
139+
static int findMSB(NBL_CONST_REF_ARG(Integer) val)
135140
{
136-
// GLM accepts only integer types, so idea is to cast input to integer type
137-
using as_int = typename integer_of_size<sizeof(Integer)>::type;
138-
const as_int valAsInt = reinterpret_cast<const as_int&>(val);
139-
return glm::findLSB(valAsInt);
141+
if (is_signed_v<Integer>)
142+
{
143+
// GLM accepts only integer types, so idea is to cast input to integer type
144+
using as_int = typename integer_of_size<sizeof(Integer)>::type;
145+
const as_int valAsInt = reinterpret_cast<const as_int&>(val);
146+
return glm::findMSB(valAsInt);
147+
}
148+
else
149+
{
150+
// GLM accepts only integer types, so idea is to cast input to integer type
151+
using as_uint = typename unsigned_integer_of_size<sizeof(Integer)>::type;
152+
const as_uint valAsUnsignedInt = reinterpret_cast<const as_uint&>(val);
153+
return glm::findMSB(valAsUnsignedInt);
154+
}
140155
}
141-
else
156+
};
157+
#endif
158+
159+
template<>
160+
struct find_msb_helper<uint32_t>
161+
{
162+
static int32_t findMSB(NBL_CONST_REF_ARG(uint32_t) val)
142163
{
143-
// GLM accepts only integer types, so idea is to cast input to integer type
144-
using as_uint = typename unsigned_integer_of_size<sizeof(Integer)>::type;
145-
const as_uint valAsUnsignedInt = reinterpret_cast<const as_uint&>(val);
146-
return glm::findLSB(valAsUnsignedInt);
164+
#ifdef __HLSL_VERSION
165+
return spirv::findUMsb(val);
166+
#else
167+
return glm::findMSB(val);
168+
#endif
147169
}
170+
};
171+
172+
template<>
173+
struct find_msb_helper<int32_t>
174+
{
175+
static int32_t findMSB(NBL_CONST_REF_ARG(int32_t) val)
176+
{
177+
#ifdef __HLSL_VERSION
178+
return spirv::findSMsb(val);
179+
#else
180+
return glm::findMSB(val);
148181
#endif
149-
}
182+
}
183+
};
150184

151-
template<typename Integer>
152-
int findMSB(NBL_CONST_REF_ARG(Integer) val)
185+
template<int N>
186+
struct find_msb_helper<vector<uint32_t, N> >
153187
{
188+
static vector<int32_t, N> findMSB(NBL_CONST_REF_ARG(vector<uint32_t, N>) val)
189+
{
154190
#ifdef __HLSL_VERSION
155-
if (is_signed_v<Integer>)
191+
return spirv::findUMsb(val);
192+
#else
193+
return glm::findMSB(val);
194+
#endif
195+
}
196+
};
197+
198+
template<int N>
199+
struct find_msb_helper<vector<int32_t, N> >
200+
{
201+
static vector<int32_t, N> findMSB(NBL_CONST_REF_ARG(vector<int32_t, N>) val)
156202
{
203+
#ifdef __HLSL_VERSION
157204
return spirv::findSMsb(val);
205+
#else
206+
return glm::findMSB(val);
207+
#endif
158208
}
159-
else
209+
};
210+
211+
#ifdef __HLSL_VERSION
212+
template<typename Integer>
213+
struct find_lsb_helper;
214+
#else
215+
// legacy code wouldn't work without it
216+
template<typename Integer>
217+
struct find_lsb_helper
218+
{
219+
static int32_t findLSB(NBL_CONST_REF_ARG(Integer) val)
160220
{
161-
return spirv::findUMsb(val);
221+
#ifdef __HLSL_VERSION
222+
return spirv::findILsb(val);
223+
#else
224+
if (is_signed_v<Integer>)
225+
{
226+
// GLM accepts only integer types, so idea is to cast input to integer type
227+
using as_int = typename integer_of_size<sizeof(Integer)>::type;
228+
const as_int valAsInt = reinterpret_cast<const as_int&>(val);
229+
return glm::findLSB(valAsInt);
230+
}
231+
else
232+
{
233+
// GLM accepts only integer types, so idea is to cast input to integer type
234+
using as_uint = typename unsigned_integer_of_size<sizeof(Integer)>::type;
235+
const as_uint valAsUnsignedInt = reinterpret_cast<const as_uint&>(val);
236+
return glm::findLSB(valAsUnsignedInt);
237+
}
238+
#endif
162239
}
240+
};
241+
#endif
242+
243+
template<>
244+
struct find_lsb_helper<int32_t>
245+
{
246+
static int32_t findLSB(NBL_CONST_REF_ARG(int32_t) val)
247+
{
248+
#ifdef __HLSL_VERSION
249+
return spirv::findILsb(val);
163250
#else
164-
if (is_signed_v<Integer>)
251+
return glm::findLSB(val);
252+
#endif
253+
}
254+
};
255+
256+
template<>
257+
struct find_lsb_helper<uint32_t>
258+
{
259+
static int32_t findLSB(NBL_CONST_REF_ARG(uint32_t) val)
165260
{
166-
// GLM accepts only integer types, so idea is to cast input to integer type
167-
using as_int = typename integer_of_size<sizeof(Integer)>::type;
168-
const as_int valAsInt = reinterpret_cast<const as_int&>(val);
169-
return glm::findMSB(valAsInt);
261+
#ifdef __HLSL_VERSION
262+
return spirv::findILsb(val);
263+
#else
264+
return glm::findLSB(val);
265+
#endif
170266
}
171-
else
267+
};
268+
269+
template<int N>
270+
struct find_lsb_helper<vector<int32_t, N> >
271+
{
272+
static vector<int32_t, N> findLSB(NBL_CONST_REF_ARG(vector<int32_t, N>) val)
172273
{
173-
// GLM accepts only integer types, so idea is to cast input to integer type
174-
using as_uint = typename unsigned_integer_of_size<sizeof(Integer)>::type;
175-
const as_uint valAsUnsignedInt = reinterpret_cast<const as_uint&>(val);
176-
return glm::findMSB(valAsUnsignedInt);
274+
#ifdef __HLSL_VERSION
275+
return spirv::findILsb(val);
276+
#else
277+
return glm::findLSB(val);
278+
#endif
177279
}
280+
};
281+
282+
template<int N>
283+
struct find_lsb_helper<vector<uint32_t, N> >
284+
{
285+
static vector<int32_t, N> findLSB(NBL_CONST_REF_ARG(vector<uint32_t, N>) val)
286+
{
287+
#ifdef __HLSL_VERSION
288+
return spirv::findILsb(val);
289+
#else
290+
return glm::findLSB(val);
178291
#endif
292+
}
293+
};
294+
295+
template<typename Integer>
296+
struct find_msb_return_type
297+
{
298+
using type = int32_t;
299+
};
300+
template<typename Integer, int N>
301+
struct find_msb_return_type<vector<Integer, N> >
302+
{
303+
using type = vector<int32_t, N>;
304+
};
305+
template<typename Integer>
306+
using find_lsb_return_type = find_msb_return_type<Integer>;
307+
308+
}
309+
310+
template<typename Integer>
311+
inline typename cpp_compat_intrinsics_impl::find_lsb_return_type<Integer>::type findLSB(NBL_CONST_REF_ARG(Integer) val)
312+
{
313+
return cpp_compat_intrinsics_impl::find_lsb_helper<Integer>::findLSB(val);
314+
}
315+
316+
template<typename Integer>
317+
inline typename cpp_compat_intrinsics_impl::find_msb_return_type<Integer>::type findMSB(NBL_CONST_REF_ARG(Integer) val)
318+
{
319+
return cpp_compat_intrinsics_impl::find_msb_helper<Integer>::findMSB(val);
179320
}
180321

181322
// TODO: some of the functions in this header should move to `tgmath`
@@ -204,19 +345,48 @@ inline matrix<T, N, N> inverse(NBL_CONST_REF_ARG(matrix<T, N, N>) m)
204345

205346
namespace cpp_compat_intrinsics_impl
206347
{
207-
// TODO: concept requiring T to be a float when U is not bool
208348
template<typename T, typename U>
209-
struct lerp_helper
210-
{
211-
static inline T lerp(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(U) a)
212-
{
349+
struct lerp_helper;
350+
213351
#ifdef __HLSL_VERSION
214-
return spirv::fMix(x, y, a);
352+
#define MIX_FUNCTION spirv::fMix
215353
#else
216-
return glm::mix<T, U>(x, y, a);
354+
#define MIX_FUNCTION glm::mix
217355
#endif
218-
}
219-
};
356+
357+
#define DEFINE_LERP_HELPER_COMMON_SPECIALIZATION(TYPE)\
358+
template<>\
359+
struct lerp_helper<TYPE, TYPE>\
360+
{\
361+
static inline TYPE lerp(NBL_CONST_REF_ARG(TYPE) x, NBL_CONST_REF_ARG(TYPE) y, NBL_CONST_REF_ARG(TYPE) a)\
362+
{\
363+
return MIX_FUNCTION(x, y, a);\
364+
}\
365+
};\
366+
\
367+
template<int N>\
368+
struct lerp_helper<vector<TYPE, N>, vector<TYPE, N> >\
369+
{\
370+
static inline vector<TYPE, N> lerp(NBL_CONST_REF_ARG(vector<TYPE, N>) x, NBL_CONST_REF_ARG(vector<TYPE, N>) y, NBL_CONST_REF_ARG(vector<TYPE, N>) a)\
371+
{\
372+
return MIX_FUNCTION(x, y, a);\
373+
}\
374+
};\
375+
\
376+
template<int N>\
377+
struct lerp_helper<vector<TYPE, N>, TYPE>\
378+
{\
379+
static inline vector<TYPE, N> lerp(NBL_CONST_REF_ARG(vector<TYPE, N>) x, NBL_CONST_REF_ARG(vector<TYPE, N>) y, NBL_CONST_REF_ARG(TYPE) a)\
380+
{\
381+
return MIX_FUNCTION(x, y, a);\
382+
}\
383+
};\
384+
385+
DEFINE_LERP_HELPER_COMMON_SPECIALIZATION(float32_t)
386+
DEFINE_LERP_HELPER_COMMON_SPECIALIZATION(float64_t)
387+
388+
#undef DEFINE_LERP_HELPER_COMMON_SPECIALIZATION
389+
#undef MIX_FUNCTION
220390

221391
template<typename T>
222392
struct lerp_helper<T, bool>

include/nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#ifdef __HLSL_VERSION
55
#include <nbl/builtin/hlsl/cpp_compat.hlsl>
6+
#include <nbl/builtin/hlsl/concepts.hlsl>
67
#include "spirv/unified1/GLSL.std.450.h"
78

89
namespace nbl
@@ -13,15 +14,33 @@ namespace spirv
1314
{
1415

1516
// Find MSB and LSB restricted to 32-bit width component types https://registry.khronos.org/SPIR-V/specs/unified1/GLSL.std.450.html
16-
template<typename Integral>
17+
template<typename Integral32 NBL_FUNC_REQUIRES(is_same_v<Integral32, int32_t> || is_same_v<Integral32, uint32_t>)
1718
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindILsb, "GLSL.std.450")]]
18-
enable_if_t<is_integral_v<Integral> && (sizeof(scalar_type_t<Integral>) == 4 && !is_matrix_v<Integral>), Integral> findILsb(Integral value);
19+
Integral32 findILsb(Integral32 value);
1920

21+
template<int N>
22+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindILsb, "GLSL.std.450")]]
23+
vector<int32_t, N> findILsb(vector<int32_t, N> value);
24+
25+
template<int N>
26+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindILsb, "GLSL.std.450")]]
27+
vector<uint32_t, N> findILsb(vector<uint32_t, N> value);
28+
29+
template<typename Int32_t NBL_FUNC_REQUIRES(is_same_v<Int32_t, int32_t>)
2030
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindSMsb, "GLSL.std.450")]]
21-
int32_t findSMsb(int32_t value);
31+
int32_t findSMsb(Int32_t value);
2232

33+
template<int N>
34+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindSMsb, "GLSL.std.450")]]
35+
vector<int32_t, N> findSMsb(vector<int32_t, N> value);
36+
37+
template<typename Uint32_t NBL_FUNC_REQUIRES(is_same_v<Uint32_t, uint32_t>)
38+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindUMsb, "GLSL.std.450")]]
39+
int32_t findUMsb(Uint32_t value);
40+
41+
template<int N>
2342
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindUMsb, "GLSL.std.450")]]
24-
uint32_t findUMsb(uint32_t value);
43+
vector<uint32_t, N> findUMsb(vector<uint32_t, N> value);
2544

2645
template<typename FloatingPoint>
2746
[[vk::ext_instruction(GLSLstd450::GLSLstd450Exp2, "GLSL.std.450")]]
@@ -30,7 +49,7 @@ enable_if_t<is_floating_point<FloatingPoint>::value && !is_matrix_v<FloatingPoin
3049
template<typename FloatingPoint>
3150
[[vk::ext_instruction(GLSLstd450::GLSLstd450InverseSqrt, "GLSL.std.450")]]
3251
enable_if_t<is_floating_point_v<FloatingPoint> && !is_matrix_v<FloatingPoint>, FloatingPoint> inverseSqrt(FloatingPoint val);
33-
52+
3453
template<typename FloatingPoint>
3554
[[vk::ext_instruction(GLSLstd450::GLSLstd450Floor, "GLSL.std.450")]]
3655
enable_if_t<is_floating_point_v<FloatingPoint> && !is_matrix_v<FloatingPoint>, FloatingPoint> floor(FloatingPoint val);
@@ -41,7 +60,7 @@ enable_if_t<is_floating_point_v<FloatingPoint>, vector<FloatingPoint, 3> > cross
4160

4261
template<typename FloatingPoint>
4362
[[vk::ext_instruction(GLSLstd450::GLSLstd450FMix, "GLSL.std.450")]]
44-
enable_if_t<is_floating_point_v<FloatingPoint> && !is_matrix_v<FloatingPoint>, FloatingPoint> fMix(FloatingPoint val, FloatingPoint min, FloatingPoint max);
63+
enable_if_t<is_floating_point_v<FloatingPoint> && !is_matrix_v<FloatingPoint>, FloatingPoint> fMix(FloatingPoint x, FloatingPoint y, FloatingPoint a);
4564

4665
template<typename T, int N>
4766
[[vk::ext_instruction(GLSLstd450::GLSLstd450Determinant, "GLSL.std.450")]]

0 commit comments

Comments
 (0)