xref: /freebsd/contrib/llvm-project/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _HLSL_HLSL_INTRINSIC_HELPERS_H_
10 #define _HLSL_HLSL_INTRINSIC_HELPERS_H_
11 
12 namespace hlsl {
13 namespace __detail {
14 
d3d_color_to_ubyte4_impl(vector<float,4> V)15 constexpr vector<uint, 4> d3d_color_to_ubyte4_impl(vector<float, 4> V) {
16   // Use the same scaling factor used by FXC, and DXC for DXIL
17   // (i.e., 255.001953)
18   // https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/lib/HLSL/HLOperationLower.cpp#L666C1-L697C2
19   // The DXC implementation refers to a comment on the following stackoverflow
20   // discussion to justify the scaling factor: "Built-in rounding, necessary
21   // because of truncation. 0.001953 * 256 = 0.5"
22   // https://stackoverflow.com/questions/52103720/why-does-d3dcolortoubyte4-multiplies-components-by-255-001953f
23   return V.zyxw * 255.001953f;
24 }
25 
length_impl(T X)26 template <typename T> constexpr T length_impl(T X) { return abs(X); }
27 
28 template <typename T, int N>
29 constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
length_vec_impl(vector<T,N> X)30 length_vec_impl(vector<T, N> X) {
31 #if (__has_builtin(__builtin_spirv_length))
32   return __builtin_spirv_length(X);
33 #else
34   return sqrt(dot(X, X));
35 #endif
36 }
37 
38 template <typename T>
dst_impl(vector<T,4> Src0,vector<T,4> Src1)39 constexpr 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 
distance_impl(T X,T Y)43 template <typename T> constexpr T distance_impl(T X, T Y) {
44   return length_impl(X - Y);
45 }
46 
47 template <typename T, int N>
48 constexpr enable_if_t<is_same<float, T>::value || is_same<half, T>::value, T>
distance_vec_impl(vector<T,N> X,vector<T,N> Y)49 distance_vec_impl(vector<T, N> X, vector<T, N> Y) {
50   return length_vec_impl(X - Y);
51 }
52 
dot2add_impl(half2 a,half2 b,float c)53 constexpr 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 #else
57   return dot(a, b) + c;
58 #endif
59 }
60 
reflect_impl(T I,T N)61 template <typename T> constexpr T reflect_impl(T I, T N) {
62   return I - 2 * N * I * N;
63 }
64 
65 template <typename T, int L>
reflect_vec_impl(vector<T,L> I,vector<T,L> N)66 constexpr 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 #else
70   return I - 2 * N * dot(I, N);
71 #endif
72 }
73 
fmod_impl(T X,T Y)74 template <typename T> constexpr T fmod_impl(T X, T Y) {
75 #if !defined(__DIRECTX__)
76   return __builtin_elementwise_fmod(X, Y);
77 #else
78   T div = X / Y;
79   bool ge = div >= 0;
80   T frc = frac(abs(div));
81   return select<T>(ge, frc, -frc) * Y;
82 #endif
83 }
84 
85 template <typename T, int N>
fmod_vec_impl(vector<T,N> X,vector<T,N> Y)86 constexpr vector<T, N> fmod_vec_impl(vector<T, N> X, vector<T, N> Y) {
87 #if !defined(__DIRECTX__)
88   return __builtin_elementwise_fmod(X, Y);
89 #else
90   vector<T, N> div = X / Y;
91   vector<bool, N> ge = div >= 0;
92   vector<T, N> frc = frac(abs(div));
93   return select<T>(ge, frc, -frc) * Y;
94 #endif
95 }
96 
smoothstep_impl(T Min,T Max,T X)97 template <typename T> constexpr T smoothstep_impl(T Min, T Max, T X) {
98 #if (__has_builtin(__builtin_spirv_smoothstep))
99   return __builtin_spirv_smoothstep(Min, Max, X);
100 #else
101   T S = saturate((X - Min) / (Max - Min));
102   return (3 - 2 * S) * S * S;
103 #endif
104 }
105 
106 template <typename T, int N>
smoothstep_vec_impl(vector<T,N> Min,vector<T,N> Max,vector<T,N> X)107 constexpr vector<T, N> smoothstep_vec_impl(vector<T, N> Min, vector<T, N> Max,
108                                            vector<T, N> X) {
109 #if (__has_builtin(__builtin_spirv_smoothstep))
110   return __builtin_spirv_smoothstep(Min, Max, X);
111 #else
112   vector<T, N> S = saturate((X - Min) / (Max - Min));
113   return (3 - 2 * S) * S * S;
114 #endif
115 }
116 
lit_impl(T NDotL,T NDotH,T M)117 template <typename T> constexpr vector<T, 4> lit_impl(T NDotL, T NDotH, T M) {
118   bool DiffuseCond = NDotL < 0;
119   T Diffuse = select<T>(DiffuseCond, 0, NDotL);
120   vector<T, 4> Result = {1, Diffuse, 0, 1};
121   // clang-format off
122   bool SpecularCond = or(DiffuseCond, (NDotH < 0));
123   // clang-format on
124   T SpecularExp = exp(log(NDotH) * M);
125   Result[2] = select<T>(SpecularCond, 0, SpecularExp);
126   return Result;
127 }
128 
faceforward_impl(T N,T I,T Ng)129 template <typename T> constexpr T faceforward_impl(T N, T I, T Ng) {
130 #if (__has_builtin(__builtin_spirv_faceforward))
131   return __builtin_spirv_faceforward(N, I, Ng);
132 #else
133   return select(dot(I, Ng) < 0, N, -N);
134 #endif
135 }
136 
ldexp_impl(T X,T Exp)137 template <typename T> constexpr T ldexp_impl(T X, T Exp) {
138   return exp2(Exp) * X;
139 }
140 
141 } // namespace __detail
142 } // namespace hlsl
143 
144 #endif // _HLSL_HLSL_INTRINSIC_HELPERS_H_
145