brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 3550409 Raw
175 lines · c
1//===----- hlsl_intrinsic_helpers.h - HLSL helpers intrinsics -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _HLSL_HLSL_INTRINSIC_HELPERS_H_10#define _HLSL_HLSL_INTRINSIC_HELPERS_H_11 12namespace hlsl {13namespace __detail {14 15constexpr int4 d3d_color_to_ubyte4_impl(float4 V) {16  // Use the same scaling factor used by FXC, and DXC for DXIL17  // (i.e., 255.001953)18  // https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/lib/HLSL/HLOperationLower.cpp#L666C1-L697C219  // The DXC implementation refers to a comment on the following stackoverflow20  // discussion to justify the scaling factor: "Built-in rounding, necessary21  // because of truncation. 0.001953 * 256 = 0.5"22  // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f23  return V.zyxw * 255.001953f;24}25 26template <typename T> constexpr T length_impl(T X) { return abs(X); }27 28template <typename T, int N>29constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>30length_vec_impl(vector<T, N> X) {31#if (__has_builtin(__builtin_spirv_length))32  return __builtin_spirv_length(X);33#else34  return sqrt(dot(X, X));35#endif36}37 38template <typename T>39constexpr vector<T, 4> dst_impl(vector<T, 4> Src0, vector<T, 4> Src1) {40  return {1, Src0[1] * Src1[1], Src0[2], Src1[3]};41}42 43template <typename T> constexpr T distance_impl(T X, T Y) {44  return length_impl(X - Y);45}46 47template <typename T, int N>48constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>49distance_vec_impl(vector<T, N> X, vector<T, N> Y) {50  return length_vec_impl(X - Y);51}52 53constexpr float dot2add_impl(half2 a, half2 b, float c) {54#if (__has_builtin(__builtin_dx_dot2add))55  return __builtin_dx_dot2add(a, b, c);56#else57  return dot(a, b) + c;58#endif59}60 61template <typename T> constexpr T reflect_impl(T I, T N) {62  return I - 2 * N * I * N;63}64 65template <typename T, int L>66constexpr vector<T, L> reflect_vec_impl(vector<T, L> I, vector<T, L> N) {67#if (__has_builtin(__builtin_spirv_reflect))68  return __builtin_spirv_reflect(I, N);69#else70  return I - 2 * N * dot(I, N);71#endif72}73 74template <typename T, typename U> constexpr T refract_impl(T I, T N, U Eta) {75#if (__has_builtin(__builtin_spirv_refract))76  return __builtin_spirv_refract(I, N, Eta);77#endif78  T Mul = dot(N, I);79  T K = 1 - Eta * Eta * (1 - Mul * Mul);80  T Result = (Eta * I - (Eta * Mul + sqrt(K)) * N);81  return select<T>(K < 0, static_cast<T>(0), Result);82}83 84template <typename T> constexpr T fmod_impl(T X, T Y) {85#if !defined(__DIRECTX__)86  return __builtin_elementwise_fmod(X, Y);87#else88  T div = X / Y;89  bool ge = div >= 0;90  T frc = frac(abs(div));91  return select<T>(ge, frc, -frc) * Y;92#endif93}94 95template <typename T, int N>96constexpr vector<T, N> fmod_vec_impl(vector<T, N> X, vector<T, N> Y) {97#if !defined(__DIRECTX__)98  return __builtin_elementwise_fmod(X, Y);99#else100  vector<T, N> div = X / Y;101  vector<bool, N> ge = div >= 0;102  vector<T, N> frc = frac(abs(div));103  return select<T>(ge, frc, -frc) * Y;104#endif105}106 107template <typename T> constexpr T smoothstep_impl(T Min, T Max, T X) {108#if (__has_builtin(__builtin_spirv_smoothstep))109  return __builtin_spirv_smoothstep(Min, Max, X);110#else111  T S = saturate((X - Min) / (Max - Min));112  return (3 - 2 * S) * S * S;113#endif114}115 116template <typename T, int N>117constexpr vector<T, N> smoothstep_vec_impl(vector<T, N> Min, vector<T, N> Max,118                                           vector<T, N> X) {119#if (__has_builtin(__builtin_spirv_smoothstep))120  return __builtin_spirv_smoothstep(Min, Max, X);121#else122  vector<T, N> S = saturate((X - Min) / (Max - Min));123  return (3 - 2 * S) * S * S;124#endif125}126 127template <typename T> constexpr vector<T, 4> lit_impl(T NDotL, T NDotH, T M) {128  bool DiffuseCond = NDotL < 0;129  T Diffuse = select<T>(DiffuseCond, 0, NDotL);130  vector<T, 4> Result = {1, Diffuse, 0, 1};131  // clang-format off132  bool SpecularCond = or(DiffuseCond, (NDotH < 0));133  // clang-format on134  T SpecularExp = exp(log(NDotH) * M);135  Result[2] = select<T>(SpecularCond, 0, SpecularExp);136  return Result;137}138 139template <typename T> constexpr T faceforward_impl(T N, T I, T Ng) {140  return select(dot(I, Ng) < 0, N, -N);141}142 143template <typename T> constexpr T ldexp_impl(T X, T Exp) {144  return exp2(Exp) * X;145}146 147template <typename K, typename T, int BitWidth>148constexpr K firstbithigh_impl(T X) {149  K FBH = __builtin_hlsl_elementwise_firstbithigh(X);150#if defined(__DIRECTX__)151  // The firstbithigh DXIL ops count bits from the wrong side, so we need to152  // invert it for DirectX.153  K Inversion = (BitWidth - 1) - FBH;154  FBH = select(FBH == -1, FBH, Inversion);155#endif156  return FBH;157}158 159template <typename T> constexpr T fwidth_impl(T input) {160#if (__has_builtin(__builtin_spirv_fwidth))161  return __builtin_spirv_fwidth(input);162#else163  T derivCoarseX = ddx_coarse(input);164  derivCoarseX = abs(derivCoarseX);165  T derivCoarseY = ddy_coarse(input);166  derivCoarseY = abs(derivCoarseY);167  return derivCoarseX + derivCoarseY;168#endif169}170 171} // namespace __detail172} // namespace hlsl173 174#endif // _HLSL_HLSL_INTRINSIC_HELPERS_H_175