@@ -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
205346namespace cpp_compat_intrinsics_impl
206347{
207- // TODO: concept requiring T to be a float when U is not bool
208348template<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
221391template<typename T>
222392struct lerp_helper<T, bool >
0 commit comments