Skip to content

Commit 20b4e3a

Browse files
committed
adds findLSB and findMSB from std.450 to glsl_compat.hlsl
1 parent e61ab7a commit 20b4e3a

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

include/nbl/builtin/hlsl/glsl_compat/core.hlsl

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "nbl/builtin/hlsl/cpp_compat.hlsl"
88
#include "nbl/builtin/hlsl/spirv_intrinsics/core.hlsl"
99
#include "nbl/builtin/hlsl/type_traits.hlsl"
10+
#include "nbl/builtin/hlsl/bit.hlsl"
1011

1112
namespace nbl
1213
{
@@ -135,6 +136,61 @@ float32_t2 unpackSnorm2x16(uint32_t p)
135136
return spirv::unpackSnorm2x16(p);
136137
}
137138

139+
// No better way to get a vector type of same length as Integral but made up of `int32_t` s?
140+
141+
template<typename T>
142+
vector<int32_t, uint32_t(sizeof(T) / sizeof(scalar_type_t<T>))> findLSB(T value)
143+
{
144+
using return_t = vector<int32_t, uint32_t(sizeof(T) / sizeof(scalar_type_t<T>))>;
145+
return bit_cast<return_t, T>(spirv::findILsb<T>(value));
146+
}
147+
148+
namespace impl
149+
{
150+
template<typename T, bool isSigned, bool isIntegral>
151+
struct findMSB {};
152+
153+
template<typename T, bool isSigned>
154+
struct findMSB<T, isSigned, false>
155+
{
156+
using return_t = vector<int32_t, uint32_t(sizeof(T) / sizeof(scalar_type_t<T>))>;
157+
158+
static return_t __call(T value)
159+
{
160+
static_assert(is_integral<T>::value, "T is not an integral type!");
161+
return value;
162+
}
163+
};
164+
165+
template<typename T>
166+
struct findMSB<T, true, true>
167+
{
168+
using return_t = vector<int32_t, uint32_t(sizeof(T) / sizeof(scalar_type_t<T>))>;
169+
170+
static return_t __call(T value)
171+
{
172+
return bit_cast<return_t, T>(spirv::findSMsb<T>(value));
173+
}
174+
};
175+
176+
template<typename T>
177+
struct findMSB<T, false, true>
178+
{
179+
using return_t = vector<int32_t, uint32_t(sizeof(T) / sizeof(scalar_type_t<T>))>;
180+
181+
static return_t __call(T value)
182+
{
183+
return bit_cast<return_t, T>(spirv::findUMsb<T>(value));
184+
}
185+
};
186+
} // namespace impl
187+
188+
template<typename T>
189+
vector<int32_t, uint32_t(sizeof(T) / sizeof(scalar_type_t<T>))> findMSB(T value)
190+
{
191+
return impl::findMSB<T, is_signed_v<T>, is_integral_v<T> >::__call(value);
192+
}
193+
138194
/**
139195
* For Vertex Shaders
140196
*/

include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,20 @@ float32_t4 unpackSnorm4x8(uint32_t p);
203203
[[vk::ext_instruction(GLSLstd450UnpackUnorm4x8, "GLSL.std.450")]]
204204
float32_t4 unpackUnorm4x8(uint32_t p);
205205

206+
// Find MSB and LSB restricted to 32-bit width component types https://registry.khronos.org/SPIR-V/specs/unified1/GLSL.std.450.html
207+
208+
template<typename Integral NBL_FUNC_REQUIRES(is_integral_v<Integral> && (sizeof(scalar_type_t<Integral>) == 4))
209+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindILsb, "GLSL.std.450")]]
210+
Integral findILsb(Integral value);
211+
212+
template<typename Integral NBL_FUNC_REQUIRES(is_integral_v<Integral> && (sizeof(scalar_type_t<Integral>) == 4))
213+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindSMsb, "GLSL.std.450")]]
214+
Integral findSMsb(Integral value);
215+
216+
template<typename Integral NBL_FUNC_REQUIRES(is_integral_v<Integral> && (sizeof(scalar_type_t<Integral>) == 4))
217+
[[vk::ext_instruction(GLSLstd450::GLSLstd450FindUMsb, "GLSL.std.450")]]
218+
Integral findUMsb(Integral value);
219+
206220
// Memory Semantics link here: https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Memory_Semantics_-id-
207221

208222
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_memory_semantics_id
@@ -234,13 +248,13 @@ template<class T, class U>
234248
[[vk::ext_instruction(spv::OpBitcast)]]
235249
T bitcast(U);
236250

237-
template<typename Unsigned>
251+
template<typename Integral>
238252
[[vk::ext_instruction( spv::OpBitFieldUExtract )]]
239-
enable_if_t<is_unsigned_v<Unsigned>, Unsigned> bitFieldUExtract( Unsigned val, uint32_t offsetBits, uint32_t numBits );
253+
enable_if_t<is_integral_v<Integral>, Integral> bitFieldUExtract( Integral val, uint32_t offsetBits, uint32_t numBits );
240254

241-
template<typename Signed>
255+
template<typename Integral>
242256
[[vk::ext_instruction( spv::OpBitFieldSExtract )]]
243-
enable_if_t<is_signed_v<Signed>, Signed> bitFieldSExtract( Signed val, uint32_t offsetBits, uint32_t numBits );
257+
enable_if_t<is_integral_v<Integral>, Integral> bitFieldSExtract( Integral val, uint32_t offsetBits, uint32_t numBits );
244258

245259
template<typename Integral>
246260
[[vk::ext_instruction( spv::OpBitFieldInsert )]]

include/nbl/builtin/hlsl/type_traits.hlsl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,9 @@ template<class T>
613613
NBL_CONSTEXPR bool is_scalar_v = is_scalar<T>::value;
614614
template<class T>
615615
NBL_CONSTEXPR uint32_t alignment_of_v = alignment_of<T>::value;
616+
template<class T, uint32_t N = 0>
617+
NBL_CONSTEXPR uint64_t extent_v = extent<T, N>::value;
618+
616619

617620
// Overlapping definitions
618621
template<typename T>

0 commit comments

Comments
 (0)