diff --git a/examples_tests b/examples_tests index e4906b5ab..73ac5c8aa 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit e4906b5ab6187ab1be4a34df9f3eef8002366a27 +Subproject commit 73ac5c8aaabb4a33c46599de51ad2a5d5fff77cc diff --git a/include/nbl/builtin/hlsl/array_accessors.hlsl b/include/nbl/builtin/hlsl/array_accessors.hlsl new file mode 100644 index 000000000..b025f9d67 --- /dev/null +++ b/include/nbl/builtin/hlsl/array_accessors.hlsl @@ -0,0 +1,30 @@ +#ifndef _NBL_BUILTIN_HLSL_ARRAY_ACCESSORS_HLSL_INCLUDED_ +#define _NBL_BUILTIN_HLSL_ARRAY_ACCESSORS_HLSL_INCLUDED_ + +#include + +namespace nbl +{ +namespace hlsl +{ +template +struct array_get +{ + ComponentType operator()(NBL_CONST_REF_ARG(ArrayType) arr, const I ix) NBL_CONST_MEMBER_FUNC + { + return arr[ix]; + } +}; + +template +struct array_set +{ + void operator()(NBL_REF_ARG(ArrayType) arr, I index, ComponentType val) NBL_CONST_MEMBER_FUNC + { + arr[index] = val; + } +}; +} +} + +#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/cpp_compat.hlsl b/include/nbl/builtin/hlsl/cpp_compat.hlsl index 2d8a13e63..175a3e76c 100644 --- a/include/nbl/builtin/hlsl/cpp_compat.hlsl +++ b/include/nbl/builtin/hlsl/cpp_compat.hlsl @@ -3,7 +3,7 @@ #include // it includes vector and matrix -#include +#include #include #endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/cpp_compat/basic.h b/include/nbl/builtin/hlsl/cpp_compat/basic.h index 8788794cc..402a640cf 100644 --- a/include/nbl/builtin/hlsl/cpp_compat/basic.h +++ b/include/nbl/builtin/hlsl/cpp_compat/basic.h @@ -55,8 +55,12 @@ namespace nbl::hlsl // We need variadic macro in order to handle multi parameter templates because the // preprocessor parses the template parameters as different macro parameters. -#define NBL_REF_ARG(...) typename nbl::hlsl::add_reference<__VA_ARGS__ >::type -#define NBL_CONST_REF_ARG(...) typename nbl::hlsl::add_reference>::type +#define NBL_REF_ARG(...) __VA_ARGS__& +#define NBL_CONST_REF_ARG(...) const __VA_ARGS__& + +// NOTE: implementation below will mess up template parameter deduction +//#define NBL_REF_ARG(...) typename nbl::hlsl::add_reference<__VA_ARGS__ >::type +//#define NBL_CONST_REF_ARG(...) typename nbl::hlsl::add_reference>::type #else diff --git a/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl new file mode 100644 index 000000000..236544076 --- /dev/null +++ b/include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl @@ -0,0 +1,369 @@ +#ifndef _NBL_BUILTIN_HLSL_CPP_COMPAT_IMPL_INTRINSICS_IMPL_INCLUDED_ +#define _NBL_BUILTIN_HLSL_CPP_COMPAT_IMPL_INTRINSICS_IMPL_INCLUDED_ + +#include +#include + +namespace nbl +{ +namespace hlsl +{ +namespace cpp_compat_intrinsics_impl +{ +template +struct dot_helper +{ + using scalar_type = typename vector_traits::scalar_type; + + static inline scalar_type dot_product(NBL_CONST_REF_ARG(T) lhs, NBL_CONST_REF_ARG(T) rhs) + { + static array_get getter; + scalar_type retval = getter(lhs, 0) * getter(rhs, 0); + + static const uint32_t ArrayDim = sizeof(T) / sizeof(scalar_type); + for (uint32_t i = 1; i < ArrayDim; ++i) + retval = retval + getter(lhs, i) * getter(rhs, i); + + return retval; + } +}; + +#define DEFINE_BUILTIN_VECTOR_SPECIALIZATION(FLOAT_TYPE, RETURN_VALUE)\ +template\ +struct dot_helper >\ +{\ + using VectorType = vector;\ + using ScalarType = typename vector_traits::scalar_type;\ +\ + static inline ScalarType dot_product(NBL_CONST_REF_ARG(VectorType) lhs, NBL_CONST_REF_ARG(VectorType) rhs)\ + {\ + return RETURN_VALUE;\ + }\ +};\ + +#ifdef __HLSL_VERSION +#define BUILTIN_VECTOR_SPECIALIZATION_RET_VAL dot(lhs, rhs) +#else +#define BUILTIN_VECTOR_SPECIALIZATION_RET_VAL glm::dot(lhs, rhs) +#endif + +DEFINE_BUILTIN_VECTOR_SPECIALIZATION(float16_t, BUILTIN_VECTOR_SPECIALIZATION_RET_VAL) +DEFINE_BUILTIN_VECTOR_SPECIALIZATION(float32_t, BUILTIN_VECTOR_SPECIALIZATION_RET_VAL) +DEFINE_BUILTIN_VECTOR_SPECIALIZATION(float64_t, BUILTIN_VECTOR_SPECIALIZATION_RET_VAL) + +#undef BUILTIN_VECTOR_SPECIALIZATION_RET_VAL +#undef DEFINE_BUILTIN_VECTOR_SPECIALIZATION + +template +struct find_msb_helper; + +template<> +struct find_msb_helper +{ + static int32_t findMSB(NBL_CONST_REF_ARG(uint32_t) val) + { +#ifdef __HLSL_VERSION + return spirv::findUMsb(val); +#else + return glm::findMSB(val); +#endif + } +}; + +template<> +struct find_msb_helper +{ + static int32_t findMSB(NBL_CONST_REF_ARG(int32_t) val) + { +#ifdef __HLSL_VERSION + return spirv::findSMsb(val); +#else + return glm::findMSB(val); +#endif + } +}; + +#define DEFINE_FIND_MSB_COMMON_SPECIALIZATION(INPUT_INTEGER_TYPE, INTEGER_TYPE)\ +template<>\ +struct find_msb_helper\ +{\ + static int32_t findMSB(NBL_CONST_REF_ARG(INPUT_INTEGER_TYPE) val)\ + {\ + return find_msb_helper::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 +{ + static int32_t findMSB(NBL_CONST_REF_ARG(uint64_t) val) + { +#ifdef __HLSL_VERSION + const uint32_t highBits = uint32_t(val >> 32); + const int32_t highMsb = find_msb_helper::findMSB(highBits); + + if (highMsb == -1) + { + const uint32_t lowBits = uint32_t(val); + const int32_t lowMsb = find_msb_helper::findMSB(lowBits); + if (lowMsb == -1) + return -1; + + return lowMsb; + } + + return highMsb + 32; +#else + return glm::findMSB(val); +#endif + } +}; + +template +struct find_msb_helper > +{ + static vector findMSB(NBL_CONST_REF_ARG(vector) val) + { +#ifdef __HLSL_VERSION + return spirv::findUMsb(val); +#else + return glm::findMSB(val); +#endif + } +}; + +template +struct find_msb_helper > +{ + static vector findMSB(NBL_CONST_REF_ARG(vector) val) + { +#ifdef __HLSL_VERSION + return spirv::findSMsb(val); +#else + return glm::findMSB(val); +#endif + } +}; + +#ifndef __HLSL_VERSION + +template + requires std::is_enum_v +struct find_msb_helper +{ + static int32_t findMSB(NBL_CONST_REF_ARG(EnumType) val) + { + using underlying_t = std::underlying_type_t; + return find_msb_helper::findMSB(static_cast(val)); + } +}; + +#endif + +template +struct find_lsb_helper; + +template<> +struct find_lsb_helper +{ + static int32_t findLSB(NBL_CONST_REF_ARG(int32_t) val) + { +#ifdef __HLSL_VERSION + return spirv::findILsb(val); +#else + return glm::findLSB(val); +#endif + } +}; + +template<> +struct find_lsb_helper +{ + static int32_t findLSB(NBL_CONST_REF_ARG(uint32_t) val) + { +#ifdef __HLSL_VERSION + return spirv::findILsb(val); +#else + return glm::findLSB(val); +#endif + } +}; + +#define DEFINE_FIND_LSB_COMMON_SPECIALIZATION(INPUT_INTEGER_TYPE, INTEGER_TYPE)\ +template<>\ +struct find_lsb_helper\ +{\ + static int32_t findLSB(NBL_CONST_REF_ARG(INPUT_INTEGER_TYPE) val)\ + {\ + return find_lsb_helper::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 +{ + static int32_t findLSB(NBL_CONST_REF_ARG(uint64_t) val) + { +#ifdef __HLSL_VERSION + const uint32_t lowBits = uint32_t(val); + const int32_t lowLsb = find_lsb_helper::findLSB(lowBits); + + if (lowLsb == -1) + { + const uint32_t highBits = uint32_t(val >> 32); + const int32_t highLsb = find_lsb_helper::findLSB(highBits); + if (highLsb == -1) + return -1; + else + return 32 + highLsb; + } + + return lowLsb; +#else + return glm::findLSB(val); +#endif + } +}; + +template +struct find_lsb_helper > +{ + static vector findLSB(NBL_CONST_REF_ARG(vector) val) + { +#ifdef __HLSL_VERSION + return spirv::findILsb(val); +#else + return glm::findLSB(val); +#endif + } +}; + +template +struct find_lsb_helper > +{ + static vector findLSB(NBL_CONST_REF_ARG(vector) val) + { +#ifdef __HLSL_VERSION + return spirv::findILsb(val); +#else + return glm::findLSB(val); +#endif + } +}; + +#ifndef __HLSL_VERSION + +template +requires std::is_enum_v +struct find_lsb_helper +{ + static int32_t findLSB(NBL_CONST_REF_ARG(EnumType) val) + { + using underlying_t = std::underlying_type_t; + return find_lsb_helper::findLSB(static_cast(val)); + } +}; + +#endif + +template +struct find_msb_return_type +{ + using type = int32_t; +}; +template +struct find_msb_return_type > +{ + using type = vector; +}; +template +using find_lsb_return_type = find_msb_return_type; + +template +struct lerp_helper; + +#ifdef __HLSL_VERSION +#define MIX_FUNCTION spirv::fMix +#else +#define MIX_FUNCTION glm::mix +#endif + +#define DEFINE_LERP_HELPER_COMMON_SPECIALIZATION(TYPE)\ +template<>\ +struct lerp_helper\ +{\ + static inline TYPE lerp(NBL_CONST_REF_ARG(TYPE) x, NBL_CONST_REF_ARG(TYPE) y, NBL_CONST_REF_ARG(TYPE) a)\ + {\ + return MIX_FUNCTION(x, y, a);\ + }\ +};\ +\ +template\ +struct lerp_helper, vector >\ +{\ + static inline vector lerp(NBL_CONST_REF_ARG(vector) x, NBL_CONST_REF_ARG(vector) y, NBL_CONST_REF_ARG(vector) a)\ + {\ + return MIX_FUNCTION(x, y, a);\ + }\ +};\ +\ +template\ +struct lerp_helper, TYPE>\ +{\ + static inline vector lerp(NBL_CONST_REF_ARG(vector) x, NBL_CONST_REF_ARG(vector) y, NBL_CONST_REF_ARG(TYPE) a)\ + {\ + return MIX_FUNCTION(x, y, a);\ + }\ +};\ + +DEFINE_LERP_HELPER_COMMON_SPECIALIZATION(float32_t) +DEFINE_LERP_HELPER_COMMON_SPECIALIZATION(float64_t) + +#undef DEFINE_LERP_HELPER_COMMON_SPECIALIZATION +#undef MIX_FUNCTION + +template +struct lerp_helper +{ + static inline T lerp(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(bool) a) + { + if (a) + return y; + else + return x; + } +}; + +template +struct lerp_helper, vector > +{ + using output_vec_t = vector; + + static inline output_vec_t lerp(NBL_CONST_REF_ARG(output_vec_t) x, NBL_CONST_REF_ARG(output_vec_t) y, NBL_CONST_REF_ARG(vector) a) + { + output_vec_t retval; + for (uint32_t i = 0; i < vector_traits::Dimension; i++) + retval[i] = a[i] ? y[i] : x[i]; + return retval; + } +}; + +} +} +} + +#endif \ No newline at end of file diff --git a/include/nbl/builtin/hlsl/cpp_compat/intrinsics.h b/include/nbl/builtin/hlsl/cpp_compat/intrinsics.h deleted file mode 100644 index e83ced0bc..000000000 --- a/include/nbl/builtin/hlsl/cpp_compat/intrinsics.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef _NBL_BUILTIN_HLSL_CPP_COMPAT_INTRINSICS_INCLUDED_ -#define _NBL_BUILTIN_HLSL_CPP_COMPAT_INTRINSICS_INCLUDED_ - - -#include -#include - -// this is a C++ only header, hence the `.h` extension, it only implements HLSL's built-in functions -#ifndef __HLSL_VERSION -#include -#include -#include "nbl/core/util/bitflag.h" - -namespace nbl::hlsl -{ -// TODO: remove this macro and write stuff by hand, the aliasing stuff doesn't work -#define NBL_SIMPLE_GLM_PASSTHROUGH(HLSL_ID,GLSL_ID,...) template\ -inline auto HLSL_ID(Args&&... args) \ -{ \ - return glm::GLSL_ID(std::forward(args)...);\ -} -#define NBL_BIT_OP_GLM_PASSTHROUGH(HLSL_ID,GLSL_ID) template \ -inline auto HLSL_ID(const T bitpattern) \ -{ \ - if constexpr (std::is_integral_v) \ - return glm::GLSL_ID(bitpattern); \ - else \ - { \ - if constexpr (std::is_enum_v) \ - { \ - const auto as_underlying = static_cast>(bitpattern); \ - return glm::GLSL_ID(as_underlying); \ - } \ - else \ - { \ - if constexpr (std::is_same_v>) \ - return HLSL_ID(bitpattern.value); \ - } \ - } \ -} - -NBL_BIT_OP_GLM_PASSTHROUGH(bitCount,bitCount) - -NBL_SIMPLE_GLM_PASSTHROUGH(cross,cross) -NBL_SIMPLE_GLM_PASSTHROUGH(clamp,clamp) - -template -inline scalar_type_t dot(const T& lhs, const T& rhs) -{ - scalar_type_t retval = lhs[0]*rhs[0]; - // whatever has a `scalar_type` specialization should be a pure vector - for (auto i=1; i