Skip to content

Intrinsics adjustments #856

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

Merged
merged 4 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
82 changes: 61 additions & 21 deletions include/nbl/builtin/hlsl/cpp_compat/impl/intrinsics_impl.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ template<typename T NBL_STRUCT_CONSTRAINABLE>
struct nMax_helper;
template<typename T NBL_STRUCT_CONSTRAINABLE>
struct nClamp_helper;

template<typename T NBL_STRUCT_CONSTRAINABLE>
struct fma_helper;

#ifdef __HLSL_VERSION // HLSL only specializations

Expand Down Expand Up @@ -134,6 +135,7 @@ template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(find_lsb_helper, findIL
#undef FIND_MSB_LSB_RETURN_TYPE

template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(bitReverse_helper, bitReverse, (T), (T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(dot_helper, dot, (T), (T)(T), typename vector_traits<T>::scalar_type)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(transpose_helper, transpose, (T), (T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(length_helper, length, (T), (T), typename vector_traits<T>::scalar_type)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(normalize_helper, normalize, (T), (T), T)
Expand Down Expand Up @@ -162,6 +164,7 @@ template<typename T, typename U> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(refract_hel
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(nMax_helper, nMax, (T), (T)(T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(nMin_helper, nMin, (T), (T)(T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(nClamp_helper, nClamp, (T), (T)(T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(fma_helper, fma, (T), (T)(T)(T), T)

#define BITCOUNT_HELPER_RETRUN_TYPE conditional_t<is_vector_v<T>, vector<int32_t, vector_traits<T>::Dimension>, int32_t>
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(bitCount_helper, bitCount, (T), (T), BITCOUNT_HELPER_RETRUN_TYPE)
Expand Down Expand Up @@ -599,6 +602,16 @@ struct nClamp_helper<T>
}
};

template<typename FloatingPoint>
requires concepts::FloatingPointScalar<FloatingPoint>
struct fma_helper<FloatingPoint>
{
static FloatingPoint __call(NBL_CONST_REF_ARG(FloatingPoint) x, NBL_CONST_REF_ARG(FloatingPoint) y, NBL_CONST_REF_ARG(FloatingPoint) z)
{
return std::fma(x, y, z);
}
};

#endif // C++ only specializations

// C++ and HLSL specializations
Expand All @@ -613,25 +626,6 @@ struct bitReverseAs_helper<T NBL_PARTIAL_REQ_BOT(concepts::UnsignedIntegralScala
}
};

template<typename Vectorial>
NBL_PARTIAL_REQ_TOP(concepts::Vectorial<Vectorial>)
struct dot_helper<Vectorial NBL_PARTIAL_REQ_BOT(concepts::Vectorial<Vectorial>) >
{
using scalar_type = typename vector_traits<Vectorial>::scalar_type;

static inline scalar_type __call(NBL_CONST_REF_ARG(Vectorial) lhs, NBL_CONST_REF_ARG(Vectorial) rhs)
{
static const uint32_t ArrayDim = vector_traits<Vectorial>::Dimension;
static array_get<Vectorial, scalar_type> getter;

scalar_type retval = getter(lhs, 0) * getter(rhs, 0);
for (uint32_t i = 1; i < ArrayDim; ++i)
retval = retval + getter(lhs, i) * getter(rhs, i);

return retval;
}
};

#ifdef __HLSL_VERSION
// SPIR-V already defines specializations for builtin vector types
#define VECTOR_SPECIALIZATION_CONCEPT concepts::Vectorial<T> && !is_vector_v<T>
Expand Down Expand Up @@ -888,8 +882,54 @@ struct mix_helper<T, U NBL_PARTIAL_REQ_BOT(concepts::Vectorial<T> && concepts::B
}
};

template<typename T>
NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT)
struct fma_helper<T NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT) >
{
using return_t = T;
static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(T) z)
{
using traits = hlsl::vector_traits<T>;
array_get<T, typename traits::scalar_type> getter;
array_set<T, typename traits::scalar_type> setter;

return_t output;
for (uint32_t i = 0; i < traits::Dimension; ++i)
setter(output, i, fma_helper<typename traits::scalar_type>::__call(getter(x, i), getter(y, i), getter(z, i)));

return output;
}
};

#ifdef __HLSL_VERSION
#define DOT_HELPER_REQUIREMENT (concepts::Vectorial<Vectorial> && !is_vector_v<Vectorial>)
#else
#define DOT_HELPER_REQUIREMENT concepts::Vectorial<Vectorial>
#endif

template<typename Vectorial>
NBL_PARTIAL_REQ_TOP(DOT_HELPER_REQUIREMENT)
struct dot_helper<Vectorial NBL_PARTIAL_REQ_BOT(DOT_HELPER_REQUIREMENT) >
{
using scalar_type = typename vector_traits<Vectorial>::scalar_type;

static inline scalar_type __call(NBL_CONST_REF_ARG(Vectorial) lhs, NBL_CONST_REF_ARG(Vectorial) rhs)
{
static const uint32_t ArrayDim = vector_traits<Vectorial>::Dimension;
static array_get<Vectorial, scalar_type> getter;

scalar_type retval = getter(lhs, 0) * getter(rhs, 0);
for (uint32_t i = 1; i < ArrayDim; ++i)
retval = fma_helper<scalar_type>::__call(getter(lhs, i), getter(rhs, i), retval);

return retval;
}
};

#undef DOT_HELPER_REQUIREMENT

}
}
}

#endif
#endif
6 changes: 6 additions & 0 deletions include/nbl/builtin/hlsl/cpp_compat/intrinsics.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ inline int32_t2 unpackDouble2x32(T val)
return NAMESPACE::unpackDouble2x32(val);
}

template<typename T>
inline T fma(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(T) z)
{
return cpp_compat_intrinsics_impl::fma_helper<T>::__call(x, y, z);
}

#undef NAMESPACE

}
Expand Down
4 changes: 4 additions & 0 deletions include/nbl/builtin/hlsl/spirv_intrinsics/core.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ template<typename T NBL_FUNC_REQUIRES(is_floating_point_v<T> && is_vector_v<T>)
[[vk::ext_instruction(spv::OpIsInf)]]
vector<bool, vector_traits<T>::Dimension> isInf(T val);

template<typename Vector NBL_FUNC_REQUIRES(is_vector_v<Vector>)
[[vk::ext_instruction( spv::OpDot )]]
typename vector_traits<Vector>::scalar_type dot(Vector lhs, Vector rhs);

template<typename Matrix>
[[vk::ext_instruction( spv::OpTranspose )]]
Matrix transpose(Matrix mat);
Expand Down
8 changes: 2 additions & 6 deletions include/nbl/builtin/hlsl/tgmath.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <nbl/builtin/hlsl/spirv_intrinsics/core.hlsl>
#include <nbl/builtin/hlsl/concepts/core.hlsl>
#include <nbl/builtin/hlsl/concepts/vector.hlsl>
#include <nbl/builtin/hlsl/cpp_compat/intrinsics.hlsl>

// C++ headers
#ifndef __HLSL_VERSION
#include <algorithm>
Expand Down Expand Up @@ -211,12 +213,6 @@ inline T ceil(NBL_CONST_REF_ARG(T) val)
return tgmath_impl::ceil_helper<T>::__call(val);
}

template<typename T>
inline T fma(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(T) z)
{
return tgmath_impl::fma_helper<T>::__call(x, y, z);
}

template<typename T, typename U>
inline T ldexp(NBL_CONST_REF_ARG(T) arg, NBL_CONST_REF_ARG(U) exp)
{
Expand Down
32 changes: 0 additions & 32 deletions include/nbl/builtin/hlsl/tgmath/impl.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ template<typename T NBL_STRUCT_CONSTRAINABLE>
struct trunc_helper;
template<typename T NBL_STRUCT_CONSTRAINABLE>
struct ceil_helper;
template<typename T NBL_STRUCT_CONSTRAINABLE>
struct fma_helper;
template<typename T, typename U NBL_STRUCT_CONSTRAINABLE>
struct ldexp_helper;
template<typename T NBL_STRUCT_CONSTRAINABLE>
Expand Down Expand Up @@ -138,7 +136,6 @@ template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(roundEven_helper, round
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(trunc_helper, trunc, (T), (T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(ceil_helper, ceil, (T), (T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(pow_helper, pow, (T), (T)(T), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(fma_helper, fma, (T), (T)(T)(T), T)
template<typename T, typename U> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(ldexp_helper, ldexp, (T)(U), (T)(U), T)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(modfStruct_helper, modfStruct, (T), (T), ModfOutput<T>)
template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(frexpStruct_helper, frexpStruct, (T), (T), FrexpOutput<T>)
Expand Down Expand Up @@ -337,16 +334,6 @@ struct roundEven_helper<FloatingPoint NBL_PARTIAL_REQ_BOT(concepts::FloatingPoin
}
};

template<typename FloatingPoint>
NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar<FloatingPoint>)
struct fma_helper<FloatingPoint NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<FloatingPoint>) >
{
static FloatingPoint __call(NBL_CONST_REF_ARG(FloatingPoint) x, NBL_CONST_REF_ARG(FloatingPoint) y, NBL_CONST_REF_ARG(FloatingPoint) z)
{
return std::fma(x, y, z);
}
};

template<typename T, typename U>
NBL_PARTIAL_REQ_TOP(concepts::FloatingPointScalar<T> && concepts::IntegralScalar<U>)
struct ldexp_helper<T, U NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T> && concepts::IntegralScalar<U>) >
Expand Down Expand Up @@ -510,25 +497,6 @@ struct pow_helper<T NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT) >
}
};

template<typename T>
NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT)
struct fma_helper<T NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT) >
{
using return_t = T;
static return_t __call(NBL_CONST_REF_ARG(T) x, NBL_CONST_REF_ARG(T) y, NBL_CONST_REF_ARG(T) z)
{
using traits = hlsl::vector_traits<T>;
array_get<T, typename traits::scalar_type> getter;
array_set<T, typename traits::scalar_type> setter;

return_t output;
for (uint32_t i = 0; i < traits::Dimension; ++i)
setter(output, i, fma_helper<typename traits::scalar_type>::__call(getter(x, i), getter(y, i), getter(z, i)));

return output;
}
};

template<typename T, typename U>
NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT && (vector_traits<T>::Dimension == vector_traits<U>::Dimension))
struct ldexp_helper<T, U NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT && (vector_traits<T>::Dimension == vector_traits<U>::Dimension)) >
Expand Down