diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-02-12 10:44:07 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-12 10:44:07 -0500 |
| commit | e1e7a6eec04ee1d04dc7e0d0212208d4c7a9592b (patch) | |
| tree | 18543abbb95cb93accedf4b0ecc894b6a363f11b | |
| parent | fe9d27af9de047ea75db1334c961bb025fb732f6 (diff) | |
Support for isinf/isfinite/isnan/ldexp (#1219)
* Added support ldexp.
* Added classify-float.slang test
Fixed glsl output.
* Added classify-double.slang
* Added ldexp test to scalar-double.slang
* isnan, isinf, isfinite are macros (on some targets) so remove :: prefix.
| -rw-r--r-- | prelude/slang-cpp-scalar-intrinsics.h | 20 | ||||
| -rw-r--r-- | prelude/slang-cuda-prelude.h | 16 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 28 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang.h | 30 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-intrinsic-set.h | 7 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/classify-double.slang | 31 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/classify-double.slang.expected.txt | 4 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/classify-float.slang | 28 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/classify-float.slang.expected.txt | 4 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/scalar-double.slang | 2 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/scalar-double.slang.expected.txt | 8 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/scalar-float.slang | 6 | ||||
| -rw-r--r-- | tests/hlsl-intrinsic/scalar-float.slang.expected.txt | 8 |
13 files changed, 166 insertions, 26 deletions
diff --git a/prelude/slang-cpp-scalar-intrinsics.h b/prelude/slang-cpp-scalar-intrinsics.h index 9fc387b6e..95acd9335 100644 --- a/prelude/slang-cpp-scalar-intrinsics.h +++ b/prelude/slang-cpp-scalar-intrinsics.h @@ -67,6 +67,10 @@ SLANG_FORCE_INLINE float F32_saturate(float f) { return (f < 0.0f) ? 0.0f : (f > SLANG_FORCE_INLINE float F32_frac(float f) { return f - F32_floor(f); } SLANG_FORCE_INLINE float F32_radians(float f) { return f * 0.01745329222f; } +SLANG_FORCE_INLINE bool F32_isnan(float f) { return isnan(f); } +SLANG_FORCE_INLINE bool F32_isfinite(float f) { return isfinite(f); } +SLANG_FORCE_INLINE bool F32_isinf(float f) { return isinf(f); } + // Binary SLANG_FORCE_INLINE float F32_min(float a, float b) { return a < b ? a : b; } SLANG_FORCE_INLINE float F32_max(float a, float b) { return a > b ? a : b; } @@ -74,7 +78,11 @@ SLANG_FORCE_INLINE float F32_pow(float a, float b) { return ::powf(a, b); } SLANG_FORCE_INLINE float F32_fmod(float a, float b) { return ::fmodf(a, b); } SLANG_FORCE_INLINE float F32_remainder(float a, float b) { return ::remainderf(a, b); } SLANG_FORCE_INLINE float F32_step(float a, float b) { return float(b >= a); } -SLANG_FORCE_INLINE float F32_atan2(float a, float b) { return float(atan2(a, b)); } +SLANG_FORCE_INLINE float F32_atan2(float a, float b) { return float(::atan2(a, b)); } + +// TODO(JS): +// Note C++ has ldexp, but it takes an integer for the exponent, it seems HLSL takes both as float +SLANG_FORCE_INLINE float F32_ldexp(float m, float e) { return m * ::powf(2.0f, e); } // Ternary SLANG_FORCE_INLINE float F32_smoothstep(float min, float max, float x) @@ -125,6 +133,10 @@ SLANG_FORCE_INLINE double F64_saturate(double f) { return (f < 0.0) ? 0.0 : (f > SLANG_FORCE_INLINE double F64_frac(double f) { return f - F64_floor(f); } SLANG_FORCE_INLINE double F64_radians(double f) { return f * 0.01745329222; } +SLANG_FORCE_INLINE bool F64_isnan(double f) { return isnan(f); } +SLANG_FORCE_INLINE bool F64_isfinite(double f) { return isfinite(f); } +SLANG_FORCE_INLINE bool F64_isinf(double f) { return isinf(f); } + // Binary SLANG_FORCE_INLINE double F64_min(double a, double b) { return a < b ? a : b; } SLANG_FORCE_INLINE double F64_max(double a, double b) { return a > b ? a : b; } @@ -132,7 +144,11 @@ SLANG_FORCE_INLINE double F64_pow(double a, double b) { return ::pow(a, b); } SLANG_FORCE_INLINE double F64_fmod(double a, double b) { return ::fmod(a, b); } SLANG_FORCE_INLINE double F64_remainder(double a, double b) { return ::remainder(a, b); } SLANG_FORCE_INLINE double F64_step(double a, double b) { return double(b >= a); } -SLANG_FORCE_INLINE double F64_atan2(double a, double b) { return atan2(a, b); } +SLANG_FORCE_INLINE double F64_atan2(double a, double b) { return ::atan2(a, b); } + +// TODO(JS): +// Note C++ has ldexp, but it takes an integer for the exponent, it seems HLSL takes both as float +SLANG_FORCE_INLINE double F64_ldexp(double m, double e) { return m * ::pow(2.0, e); } // Ternary SLANG_FORCE_INLINE double F64_smoothstep(double min, double max, double x) diff --git a/prelude/slang-cuda-prelude.h b/prelude/slang-cuda-prelude.h index dc0ba4b5e..768e33d13 100644 --- a/prelude/slang-cuda-prelude.h +++ b/prelude/slang-cuda-prelude.h @@ -120,11 +120,19 @@ SLANG_CUDA_CALL float F32_sign(float f) { return ( f == 0.0f) ? f : (( f < 0.0f) SLANG_CUDA_CALL float F32_saturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } SLANG_CUDA_CALL float F32_frac(float f) { return f - floorf(f); } +SLANG_CUDA_CALL bool F32_isnan(float f) { return isnan(f); } +SLANG_CUDA_CALL bool F32_isfinite(float f) { return isfinite(f); } +SLANG_CUDA_CALL bool F32_isinf(float f) { return isinf(f); } + // Binary SLANG_CUDA_CALL float F32_min(float a, float b) { return a < b ? a : b; } SLANG_CUDA_CALL float F32_max(float a, float b) { return a > b ? a : b; } SLANG_CUDA_CALL float F32_step(float a, float b) { return float(b >= a); } +// TODO(JS): +// Note CUDA has ldexp, but it takes an integer for the exponent, it seems HLSL takes both as float +SLANG_CUDA_CALL float F32_ldexp(float m, float e) { return m * powf(2.0f, e); } + // Ternary SLANG_CUDA_CALL float F32_lerp(float x, float y, float s) { return x + s * (y - x); } SLANG_CUDA_CALL void F32_sincos(float f, float& outSin, float& outCos) { sincosf(f, &outSin, &outCos); } @@ -146,11 +154,19 @@ SLANG_CUDA_CALL double F64_sign(double f) { return (f == 0.0) ? f : ((f < 0.0) ? SLANG_CUDA_CALL double F64_saturate(double f) { return (f < 0.0) ? 0.0 : (f > 1.0) ? 1.0 : f; } SLANG_CUDA_CALL double F64_frac(double f) { return f - floor(f); } +SLANG_CUDA_CALL bool F64_isnan(double f) { return isnan(f); } +SLANG_CUDA_CALL bool F64_isfinite(double f) { return isfinite(f); } +SLANG_CUDA_CALL bool F64_isinf(double f) { return isinf(f); } + // Binary SLANG_CUDA_CALL double F64_min(double a, double b) { return a < b ? a : b; } SLANG_CUDA_CALL double F64_max(double a, double b) { return a > b ? a : b; } SLANG_CUDA_CALL double F64_step(double a, double b) { return double(b >= a); } +// TODO(JS): +// Note CUDA has ldexp, but it takes an integer for the exponent, it seems HLSL takes both as float +SLANG_CUDA_CALL double F64_ldexp(double m, double e) { return m * pow(2.0, e); } + // Ternary SLANG_CUDA_CALL double F64_lerp(double x, double y, double s) { return x + s * (y - x); } SLANG_CUDA_CALL void F64_sincos(double f, double& outSin, double& outCos) { sincos(f, &outSin, &outCos); } diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 669fbb440..41a69382d 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -944,9 +944,17 @@ __target_intrinsic(cuda, "($2 = (uint)atomicXor((int*)&$0, $1))") void InterlockedXor(__ref uint dest, uint value, out uint original_value); // Is floating-point value finite? -__generic<T : __BuiltinFloatingPointType> bool isfinite(T x); -__generic<T : __BuiltinFloatingPointType, let N : int> vector<bool,N> isfinite(vector<T,N> x); -__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> matrix<bool,N,M> isfinite(matrix<T,N,M> x); + +__generic<T : __BuiltinFloatingPointType> +__target_intrinsic(glsl, "(!(isinf($0) || isnan($0)))") +bool isfinite(T x); + +__generic<T : __BuiltinFloatingPointType, let N : int> +__target_intrinsic(glsl, "(!(isinf($0) || isnan($0)))") +vector<bool,N> isfinite(vector<T,N> x); + +__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> +matrix<bool,N,M> isfinite(matrix<T,N,M> x); // Is floating-point value infinite? __generic<T : __BuiltinFloatingPointType> bool isinf(T x); @@ -959,9 +967,17 @@ __generic<T : __BuiltinFloatingPointType, let N : int> vector<bool,N> isnan(vect __generic<T : __BuiltinFloatingPointType, let N : int, let M : int> matrix<bool,N,M> isnan(matrix<T,N,M> x); // Construct float from mantissa and exponent -__generic<T : __BuiltinFloatingPointType> T ldexp(T x, T exp); -__generic<T : __BuiltinFloatingPointType, let N : int> vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp); -__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp); + +__generic<T : __BuiltinFloatingPointType> +__target_intrinsic(glsl, "($0 * pow(2.0f, $1))") +T ldexp(T x, T exp); + +__generic<T : __BuiltinFloatingPointType, let N : int> +__target_intrinsic(glsl, "($0 * pow(2.0f, $1))") +vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp); + +__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> +matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp); // Vector length __generic<T : __BuiltinFloatingPointType, let N : int> T length(vector<T,N> x); diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h index f69d0cb3d..6721d4a28 100644 --- a/source/slang/hlsl.meta.slang.h +++ b/source/slang/hlsl.meta.slang.h @@ -1020,9 +1020,17 @@ SLANG_RAW("__target_intrinsic(cuda, \"($2 = (uint)atomicXor((int*)&$0, $1))\")\n SLANG_RAW("void InterlockedXor(__ref uint dest, uint value, out uint original_value);\n") SLANG_RAW("\n") SLANG_RAW("// Is floating-point value finite?\n") -SLANG_RAW("__generic<T : __BuiltinFloatingPointType> bool isfinite(T x);\n") -SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int> vector<bool,N> isfinite(vector<T,N> x);\n") -SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> matrix<bool,N,M> isfinite(matrix<T,N,M> x);\n") +SLANG_RAW("\n") +SLANG_RAW("__generic<T : __BuiltinFloatingPointType>\n") +SLANG_RAW("__target_intrinsic(glsl, \"(!(isinf($0) || isnan($0)))\")\n") +SLANG_RAW("bool isfinite(T x);\n") +SLANG_RAW("\n") +SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int>\n") +SLANG_RAW("__target_intrinsic(glsl, \"(!(isinf($0) || isnan($0)))\")\n") +SLANG_RAW("vector<bool,N> isfinite(vector<T,N> x);\n") +SLANG_RAW("\n") +SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n") +SLANG_RAW("matrix<bool,N,M> isfinite(matrix<T,N,M> x);\n") SLANG_RAW("\n") SLANG_RAW("// Is floating-point value infinite?\n") SLANG_RAW("__generic<T : __BuiltinFloatingPointType> bool isinf(T x);\n") @@ -1035,9 +1043,17 @@ SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int> vector<bool,N> SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> matrix<bool,N,M> isnan(matrix<T,N,M> x);\n") SLANG_RAW("\n") SLANG_RAW("// Construct float from mantissa and exponent\n") -SLANG_RAW("__generic<T : __BuiltinFloatingPointType> T ldexp(T x, T exp);\n") -SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int> vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp);\n") -SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int, let M : int> matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp);\n") +SLANG_RAW("\n") +SLANG_RAW("__generic<T : __BuiltinFloatingPointType>\n") +SLANG_RAW("__target_intrinsic(glsl, \"($0 * pow(2.0f, $1))\")\n") +SLANG_RAW("T ldexp(T x, T exp);\n") +SLANG_RAW("\n") +SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int>\n") +SLANG_RAW("__target_intrinsic(glsl, \"($0 * pow(2.0f, $1))\")\n") +SLANG_RAW("vector<T,N> ldexp(vector<T,N> x, vector<T,N> exp);\n") +SLANG_RAW("\n") +SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int, let M : int>\n") +SLANG_RAW("matrix<T,N,M> ldexp(matrix<T,N,M> x, matrix<T,N,M> exp);\n") SLANG_RAW("\n") SLANG_RAW("// Vector length\n") SLANG_RAW("__generic<T : __BuiltinFloatingPointType, let N : int> T length(vector<T,N> x);\n") @@ -1625,7 +1641,7 @@ for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa) sb << "};\n"; } -SLANG_RAW("#line 1552 \"hlsl.meta.slang\"") +SLANG_RAW("#line 1568 \"hlsl.meta.slang\"") SLANG_RAW("\n") SLANG_RAW("\n") SLANG_RAW("\n") diff --git a/source/slang/slang-hlsl-intrinsic-set.h b/source/slang/slang-hlsl-intrinsic-set.h index 90ed9368f..ce951a008 100644 --- a/source/slang/slang-hlsl-intrinsic-set.h +++ b/source/slang/slang-hlsl-intrinsic-set.h @@ -124,7 +124,12 @@ just constructXXXFromScalar. Would be good if there was a suitable name to encom \ x(GetAt, "", 2) \ \ - x(CountBits, "countbits", 1) + x(CountBits, "countbits", 1) \ + \ + x(IsInfinite, "isinf", 1) \ + x(IsFinite, "isfinite", 1) \ + x(IsNan, "isnan", 1) \ + x(LdExp, "ldexp", 2) struct HLSLIntrinsic { diff --git a/tests/hlsl-intrinsic/classify-double.slang b/tests/hlsl-intrinsic/classify-double.slang new file mode 100644 index 000000000..ba7f2cbf9 --- /dev/null +++ b/tests/hlsl-intrinsic/classify-double.slang @@ -0,0 +1,31 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cuda -compute + +// inf, -inf, nan, finite +//TEST_INPUT:ubuffer(data=[ 0 0x7ff00000 0 0xfff00000 0xffffffff 0x7fffffff 1 0], stride=4):name inputBuffer +RWStructuredBuffer<uint> inputBuffer; + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = int(dispatchThreadID.x); + + uint low = inputBuffer[idx * 2 + 0]; + uint high = inputBuffer[idx * 2 + 1]; + + double v = asdouble(low, high); + + int flags = 0; + + flags |= isnan(v) ? 1 : 0; + flags |= isfinite(v) ? 2 : 0; + flags |= isinf(v) ? 4 : 0; + + outputBuffer[idx] = flags; +}
\ No newline at end of file diff --git a/tests/hlsl-intrinsic/classify-double.slang.expected.txt b/tests/hlsl-intrinsic/classify-double.slang.expected.txt new file mode 100644 index 000000000..1688f7508 --- /dev/null +++ b/tests/hlsl-intrinsic/classify-double.slang.expected.txt @@ -0,0 +1,4 @@ +4 +4 +1 +2 diff --git a/tests/hlsl-intrinsic/classify-float.slang b/tests/hlsl-intrinsic/classify-float.slang new file mode 100644 index 000000000..1b23dc748 --- /dev/null +++ b/tests/hlsl-intrinsic/classify-float.slang @@ -0,0 +1,28 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cuda -compute + +// inf, -inf, nan, finite +//TEST_INPUT:ubuffer(data=[ 0x7f800000 0xff800000 0x7fffffff 1 ], stride=4):name inputBuffer +RWStructuredBuffer<float> inputBuffer; + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<int> outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = int(dispatchThreadID.x); + + float v = inputBuffer[idx]; + + int flags = 0; + + flags |= isnan(v) ? 1 : 0; + flags |= isfinite(v) ? 2 : 0; + flags |= isinf(v) ? 4 : 0; + + outputBuffer[idx] = flags; +}
\ No newline at end of file diff --git a/tests/hlsl-intrinsic/classify-float.slang.expected.txt b/tests/hlsl-intrinsic/classify-float.slang.expected.txt new file mode 100644 index 000000000..1688f7508 --- /dev/null +++ b/tests/hlsl-intrinsic/classify-float.slang.expected.txt @@ -0,0 +1,4 @@ +4 +4 +1 +2 diff --git a/tests/hlsl-intrinsic/scalar-double.slang b/tests/hlsl-intrinsic/scalar-double.slang index 705a6d88a..35f530269 100644 --- a/tests/hlsl-intrinsic/scalar-double.slang +++ b/tests/hlsl-intrinsic/scalar-double.slang @@ -86,5 +86,7 @@ void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) ft += asdouble(low, high); } + ft += ldexp(23.2, f); + outputBuffer[idx] = int(ft * 16); }
\ No newline at end of file diff --git a/tests/hlsl-intrinsic/scalar-double.slang.expected.txt b/tests/hlsl-intrinsic/scalar-double.slang.expected.txt index 2fedcded2..05bb16948 100644 --- a/tests/hlsl-intrinsic/scalar-double.slang.expected.txt +++ b/tests/hlsl-intrinsic/scalar-double.slang.expected.txt @@ -1,4 +1,4 @@ -FFFFFA0C -FFFFFDE8 -1D5 -5CA +FFFFFB7F +FFFFFFA1 +3E2 +83B diff --git a/tests/hlsl-intrinsic/scalar-float.slang b/tests/hlsl-intrinsic/scalar-float.slang index 6c090cff1..e0d338075 100644 --- a/tests/hlsl-intrinsic/scalar-float.slang +++ b/tests/hlsl-intrinsic/scalar-float.slang @@ -82,9 +82,11 @@ void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) int vi = asint(f - f) + idx; ft += float(vi); - + + ft += ldexp(23.2, f); + uint vu = asuint(f); ft += asfloat(vu); outputBuffer[idx] = int(ft * 16); -}
\ No newline at end of file +} diff --git a/tests/hlsl-intrinsic/scalar-float.slang.expected.txt b/tests/hlsl-intrinsic/scalar-float.slang.expected.txt index 3ad5914c4..2b6c42d94 100644 --- a/tests/hlsl-intrinsic/scalar-float.slang.expected.txt +++ b/tests/hlsl-intrinsic/scalar-float.slang.expected.txt @@ -1,4 +1,4 @@ -FFFFFA0C -FFFFFDF4 -1ED -5EE +FFFFFB7F +FFFFFFAD +3FA +85F |
