Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cpp compat intrinsics refactor #801

Merged
merged 21 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/nbl/asset/ICPUGraphicsPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class ICPUGraphicsPipeline final : public ICPUPipeline<IGraphicsPipeline<ICPUPip

inline int8_t stageToIndex(const ICPUShader::E_SHADER_STAGE stage) const override
{
const auto stageIx = hlsl::findLSB(stage);
const auto stageIx = hlsl::findLSB(static_cast<std::underlying_type_t<ICPUShader::E_SHADER_STAGE>>(stage));
if (stageIx<0 || stageIx>=GRAPHICS_SHADER_STAGE_COUNT || hlsl::bitCount(stage)!=1)
return -1;
return stageIx;
Expand Down
6 changes: 3 additions & 3 deletions include/nbl/asset/ICPURenderpassIndependentPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ class ICPURenderpassIndependentPipeline : public IRenderpassIndependentPipeline<
inline IShader::SSpecInfo<ICPUShader> getSpecInfo(const ICPUShader::E_SHADER_STAGE stage)
{
assert(isMutable());
const auto stageIx = hlsl::findLSB(stage);
const auto stageIx = hlsl::findLSB(static_cast<std::underlying_type_t<ICPUShader::E_SHADER_STAGE>>(stage));
if (stageIx<0 || stageIx>=GRAPHICS_SHADER_STAGE_COUNT || hlsl::bitCount(stage)!=1)
return {};
return m_infos[stageIx];
}
inline IShader::SSpecInfo<const ICPUShader> getSpecInfo(const ICPUShader::E_SHADER_STAGE stage) const
{
const auto stageIx = hlsl::findLSB(stage);
const auto stageIx = hlsl::findLSB(static_cast<std::underlying_type_t<ICPUShader::E_SHADER_STAGE>>(stage));
if (stageIx<0 || stageIx>=GRAPHICS_SHADER_STAGE_COUNT || hlsl::bitCount(stage)!=1)
return {};
return m_infos[stageIx];
Expand All @@ -110,7 +110,7 @@ class ICPURenderpassIndependentPipeline : public IRenderpassIndependentPipeline<
if (specSize<0)
return false;
const auto stage = info.shader->getStage();
const auto stageIx = hlsl::findLSB(stage);
const auto stageIx = hlsl::findLSB(static_cast<std::underlying_type_t<ICPUShader::E_SHADER_STAGE>>(stage));
if (stageIx<0 || stageIx>=GRAPHICS_SHADER_STAGE_COUNT || hlsl::bitCount(stage)!=1)
return false;
m_infos[stageIx] = info;
Expand Down
150 changes: 95 additions & 55 deletions include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef _NBL_BUILTIN_HLSL_CPP_COMPAT_IMPL_INTRINSICS_IMPL_INCLUDED_
#define _NBL_BUILTIN_HLSL_CPP_COMPAT_IMPL_INTRINSICS_IMPL_INCLUDED_

#include <nbl/builtin/hlsl/cpp_compat/basic.h>
#include <nbl/builtin/hlsl/concepts.hlsl>

namespace nbl
{
namespace hlsl
Expand All @@ -12,7 +15,7 @@ struct dot_helper
{
using scalar_type = typename vector_traits<T>::scalar_type;

static inline scalar_type dot(NBL_CONST_REF_ARG(T) lhs, NBL_CONST_REF_ARG(T) rhs)
static inline scalar_type dot_product(NBL_CONST_REF_ARG(T) lhs, NBL_CONST_REF_ARG(T) rhs)
{
static array_get<T, scalar_type> getter;
scalar_type retval = getter(lhs, 0) * getter(rhs, 0);
Expand All @@ -32,7 +35,7 @@ struct dot_helper<vector<FLOAT_TYPE, N> >\
using VectorType = vector<FLOAT_TYPE, N>;\
using ScalarType = typename vector_traits<VectorType>::scalar_type;\
\
static inline ScalarType dot(NBL_CONST_REF_ARG(VectorType) lhs, NBL_CONST_REF_ARG(VectorType) rhs)\
static inline ScalarType dot_product(NBL_CONST_REF_ARG(VectorType) lhs, NBL_CONST_REF_ARG(VectorType) rhs)\
{\
return RETURN_VALUE;\
}\
Expand All @@ -51,33 +54,8 @@ DEFINE_BUILTIN_VECTOR_SPECIALIZATION(float64_t, BUILTIN_VECTOR_SPECIALIZATION_RE
#undef BUILTIN_VECTOR_SPECIALIZATION_RET_VAL
#undef DEFINE_BUILTIN_VECTOR_SPECIALIZATION

#ifdef __HLSL_VERSION
template<typename Integer>
struct find_msb_helper;
#else
// legacy code wouldn't work without it
template<typename Integer>
struct find_msb_helper
{
static int findMSB(NBL_CONST_REF_ARG(Integer) val)
{
if (is_signed_v<Integer>)
{
// GLM accepts only integer types, so idea is to cast input to integer type
using as_int = typename integer_of_size<sizeof(Integer)>::type;
const as_int valAsInt = reinterpret_cast<const as_int&>(val);
return glm::findMSB(valAsInt);
}
else
{
// GLM accepts only integer types, so idea is to cast input to integer type
using as_uint = typename unsigned_integer_of_size<sizeof(Integer)>::type;
const as_uint valAsUnsignedInt = reinterpret_cast<const as_uint&>(val);
return glm::findMSB(valAsUnsignedInt);
}
}
};
#endif

template<>
struct find_msb_helper<uint32_t>
Expand Down Expand Up @@ -105,6 +83,50 @@ struct find_msb_helper<int32_t>
}
};

#define DEFINE_FIND_MSB_COMMON_SPECIALIZATION(INPUT_INTEGER_TYPE, INTEGER_TYPE)\
template<>\
struct find_msb_helper<INPUT_INTEGER_TYPE>\
{\
static int32_t findMSB(NBL_CONST_REF_ARG(INPUT_INTEGER_TYPE) val)\
{\
return find_msb_helper<INTEGER_TYPE>::findMSB(val);\
}\
};\

DEFINE_FIND_MSB_COMMON_SPECIALIZATION(int16_t, int32_t)
DEFINE_FIND_MSB_COMMON_SPECIALIZATION(uint16_t, uint32_t)
#ifndef __HLSL_VERSION
DEFINE_FIND_MSB_COMMON_SPECIALIZATION(int8_t, int32_t)
DEFINE_FIND_MSB_COMMON_SPECIALIZATION(uint8_t, uint32_t)
#endif

template<>
struct find_msb_helper<uint64_t>
{
static int32_t findMSB(NBL_CONST_REF_ARG(uint64_t) val)
{
#ifdef __HLSL_VERSION
const uint64_t lowBits = uint32_t(val);
const uint64_t highBits = uint32_t(val >> 32);

const int32_t lowMsb = findMSB(lowBits);
if (lowMsb == -1)
{
const uint64_t highBits = uint32_t(val >> 32);
const int32_t highMsb = findMSB(highBits);
if (highBits == -1)
return -1;
else
return 32 + highMsb;
}

return lowMsb;
#else
return glm::findMSB(val);
#endif
}
};

template<int N>
struct find_msb_helper<vector<uint32_t, N> >
{
Expand All @@ -131,42 +153,26 @@ struct find_msb_helper<vector<int32_t, N> >
}
};

#ifdef __HLSL_VERSION
template<typename Integer>
struct find_lsb_helper;
#else
// legacy code wouldn't work without it
template<typename Integer>
struct find_lsb_helper

template<>
struct find_lsb_helper<int32_t>
{
static int32_t findLSB(NBL_CONST_REF_ARG(Integer) val)
static int32_t findLSB(NBL_CONST_REF_ARG(int32_t) val)
{
#ifdef __HLSL_VERSION
return spirv::findILsb(val);
#else
if (is_signed_v<Integer>)
{
// GLM accepts only integer types, so idea is to cast input to integer type
using as_int = typename integer_of_size<sizeof(Integer)>::type;
const as_int valAsInt = reinterpret_cast<const as_int&>(val);
return glm::findLSB(valAsInt);
}
else
{
// GLM accepts only integer types, so idea is to cast input to integer type
using as_uint = typename unsigned_integer_of_size<sizeof(Integer)>::type;
const as_uint valAsUnsignedInt = reinterpret_cast<const as_uint&>(val);
return glm::findLSB(valAsUnsignedInt);
}
return glm::findLSB(val);
#endif
}
};
#endif

template<>
struct find_lsb_helper<int32_t>
struct find_lsb_helper<uint32_t>
{
static int32_t findLSB(NBL_CONST_REF_ARG(int32_t) val)
static int32_t findLSB(NBL_CONST_REF_ARG(uint32_t) val)
{
#ifdef __HLSL_VERSION
return spirv::findILsb(val);
Expand All @@ -176,13 +182,44 @@ struct find_lsb_helper<int32_t>
}
};

#define DEFINE_FIND_LSB_COMMON_SPECIALIZATION(INPUT_INTEGER_TYPE, INTEGER_TYPE)\
template<>\
struct find_lsb_helper<INPUT_INTEGER_TYPE>\
{\
static int32_t findLSB(NBL_CONST_REF_ARG(INPUT_INTEGER_TYPE) val)\
{\
return find_lsb_helper<INTEGER_TYPE>::findLSB(val);\
}\
};\

DEFINE_FIND_LSB_COMMON_SPECIALIZATION(int16_t, int32_t)
DEFINE_FIND_LSB_COMMON_SPECIALIZATION(uint16_t, uint32_t)
#ifndef __HLSL_VERSION
DEFINE_FIND_LSB_COMMON_SPECIALIZATION(int8_t, int32_t)
DEFINE_FIND_LSB_COMMON_SPECIALIZATION(uint8_t, uint32_t)
#endif

template<>
struct find_lsb_helper<uint32_t>
struct find_lsb_helper<uint64_t>
{
static int32_t findLSB(NBL_CONST_REF_ARG(uint32_t) val)
static int32_t findLSB(NBL_CONST_REF_ARG(uint64_t) val)
{
#ifdef __HLSL_VERSION
return spirv::findILsb(val);
const uint64_t lowBits = uint32_t(val);
const uint64_t highBits = uint32_t(val >> 32);

const int32_t lowLsb = findLSB(lowBits);
if (lowLsb == -1)
{
const uint64_t highBits = uint32_t(val >> 32);
const int32_t highLsb = findLSB(highBits);
if (highBits == -1)
return -1;
else
return 32 + highLsb;
}

return lowLsb;
#else
return glm::findLSB(val);
#endif
Expand Down Expand Up @@ -228,7 +265,7 @@ struct find_msb_return_type<vector<Integer, N> >
template<typename Integer>
using find_lsb_return_type = find_msb_return_type<Integer>;

template<typename T, typename U>
template<typename T, typename U NBL_STRUCT_CONSTRAINABLE>
struct lerp_helper;

#ifdef __HLSL_VERSION
Expand Down Expand Up @@ -276,7 +313,10 @@ struct lerp_helper<T, bool>
{
static inline T lerp(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(bool) a)
{
return a ? y : x;
if (a)
return y;
else
return x;
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/nbl/builtin/hlsl/cpp_compat/intrinsics.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ T clamp(NBL_CONST_REF_ARG(T) val, NBL_CONST_REF_ARG(T) min, NBL_CONST_REF_ARG(T)
template<typename T>
typename vector_traits<T>::scalar_type dot(NBL_CONST_REF_ARG(T) lhs, NBL_CONST_REF_ARG(T) rhs)
{
return cpp_compat_intrinsics_impl::dot_helper<T>::dot(lhs, rhs);
return cpp_compat_intrinsics_impl::dot_helper<T>::dot_product(lhs, rhs);
}

// TODO: for clearer error messages, use concepts to ensure that input type is a square matrix
Expand Down
25 changes: 25 additions & 0 deletions include/nbl/core/util/bitflag.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define _NBL_CORE_C_BITFLAG_H_INCLUDED_

#include "BuildConfigOptions.h"
#include <nbl/builtin/hlsl/cpp_compat/intrinsics.hlsl>

namespace nbl::core
{
Expand Down Expand Up @@ -50,5 +51,29 @@ struct blake3_hasher::update_impl<core::bitflag<T>,Dummy>

template<typename T>
concept Bitflag = std::is_same_v<bitflag<typename T::enum_t>, T>;

}

namespace nbl::hlsl::cpp_compat_intrinsics_impl
{
template<typename ENUM_TYPE>
struct find_lsb_helper<core::bitflag<ENUM_TYPE>>
{
static int32_t findLSB(NBL_CONST_REF_ARG(core::bitflag<ENUM_TYPE>) val)
{
using underlying_t = typename core::bitflag<ENUM_TYPE>::UNDERLYING_TYPE;
return find_lsb_helper<underlying_t>::findLSB(static_cast<underlying_t>(val.value));
}
};

template<typename ENUM_TYPE>
struct find_msb_helper<core::bitflag<ENUM_TYPE>>
{
static int32_t findMSB(NBL_CONST_REF_ARG(core::bitflag<ENUM_TYPE>) val)
{
using underlying_t = typename core::bitflag<ENUM_TYPE>::UNDERLYING_TYPE;
return find_msb_helper<underlying_t>::findMSB(static_cast<underlying_t>(val.value));
}
};
}
#endif
2 changes: 1 addition & 1 deletion src/nbl/video/CVulkanGraphicsPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CVulkanGraphicsPipeline final : public IGPUGraphicsPipeline
for (const auto& info : params.shaders)
if (info.shader)
{
const auto stageIx = hlsl::findLSB(info.shader->getStage());
const auto stageIx = hlsl::findLSB(static_cast<std::underlying_type_t<asset::IShader::E_SHADER_STAGE>>(info.shader->getStage()));
m_shaders[stageIx] = core::smart_refctd_ptr<const CVulkanShader>(static_cast<const CVulkanShader*>(info.shader));
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/nbl/video/utilities/CAssetConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1509,7 +1509,7 @@ class GetDependantVisit<ICPUComputePipeline> : public GetDependantVisitBase<ICPU
inline auto& getSpecInfo(const IShader::E_SHADER_STAGE stage)
{
assert(hlsl::bitCount(stage)==1);
return specInfo[hlsl::findLSB(stage)];
return specInfo[hlsl::findLSB(static_cast<std::underlying_type_t<IShader::E_SHADER_STAGE>>(stage))];
}

// ok to do non owning since some cache owns anyway
Expand Down Expand Up @@ -1557,7 +1557,7 @@ class GetDependantVisit<ICPUGraphicsPipeline> : public GetDependantVisitBase<ICP
inline auto& getSpecInfo(const IShader::E_SHADER_STAGE stage)
{
assert(hlsl::bitCount(stage)==1);
return specInfo[hlsl::findLSB(stage)];
return specInfo[hlsl::findLSB(static_cast<std::underlying_type_t<IShader::E_SHADER_STAGE>>(stage))];
}

// ok to do non owning since some cache owns anyway
Expand Down