From c74a700681b0be44a74f16b0f9eaad05bba159d2 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 22 Jan 2020 11:06:20 -0500 Subject: WIP HLSL intrinsic coverage (#1171) * Added hlsl-intrinsic test folder. Enabled ceil as works across targets. * log10 support. * Fix float % on CPU/CUDA to match HLSL which is fmod (not fremainder). * Added log10 tests back to scalar-float.slang * Don't add the ( for $Sx - it's clearer what's going on without it. * Works on CUDA/CPU. Problem with asint/asuint do not seem to be found. * Only asuint exists for double. * Support countbits on CUDA and C++. * Fix typo in C++ population count. * First pass at int vector intrinsic tests. * Swizzle for int. * Bit cast tests on CUDA. * Fix warning on gcc. * Fix bit-cast-double execution on CUDA. * scalar-int test working on gcc release. --- prelude/slang-cpp-scalar-intrinsics.h | 22 ++++++- prelude/slang-cuda-prelude.h | 7 +++ source/slang/slang-emit-cpp.cpp | 6 ++ source/slang/slang-hlsl-intrinsic-set.h | 4 +- tests/compute/bit-cast-double.slang | 21 ------- tests/compute/bit-cast-double.slang.expected.txt | 4 -- tests/compute/bit-cast.slang | 71 --------------------- tests/compute/bit-cast.slang.expected.txt | 12 ---- tests/hlsl-intrinsic/bit-cast-double.slang | 22 +++++++ .../bit-cast-double.slang.expected.txt | 4 ++ tests/hlsl-intrinsic/bit-cast.slang | 72 ++++++++++++++++++++++ tests/hlsl-intrinsic/bit-cast.slang.expected.txt | 12 ++++ tests/hlsl-intrinsic/scalar-int.slang | 25 ++++++++ tests/hlsl-intrinsic/scalar-int.slang.expected.txt | 4 ++ tests/hlsl-intrinsic/scalar-uint.slang | 26 ++++++++ .../hlsl-intrinsic/scalar-uint.slang.expected.txt | 4 ++ tests/hlsl-intrinsic/vector-int.slang | 50 +++++++++++++++ tests/hlsl-intrinsic/vector-int.slang.expected.txt | 4 ++ tools/render-test/bind-location.cpp | 2 +- 19 files changed, 261 insertions(+), 111 deletions(-) delete mode 100644 tests/compute/bit-cast-double.slang delete mode 100644 tests/compute/bit-cast-double.slang.expected.txt delete mode 100644 tests/compute/bit-cast.slang delete mode 100644 tests/compute/bit-cast.slang.expected.txt create mode 100644 tests/hlsl-intrinsic/bit-cast-double.slang create mode 100644 tests/hlsl-intrinsic/bit-cast-double.slang.expected.txt create mode 100644 tests/hlsl-intrinsic/bit-cast.slang create mode 100644 tests/hlsl-intrinsic/bit-cast.slang.expected.txt create mode 100644 tests/hlsl-intrinsic/scalar-int.slang create mode 100644 tests/hlsl-intrinsic/scalar-int.slang.expected.txt create mode 100644 tests/hlsl-intrinsic/scalar-uint.slang create mode 100644 tests/hlsl-intrinsic/scalar-uint.slang.expected.txt create mode 100644 tests/hlsl-intrinsic/vector-int.slang create mode 100644 tests/hlsl-intrinsic/vector-int.slang.expected.txt diff --git a/prelude/slang-cpp-scalar-intrinsics.h b/prelude/slang-cpp-scalar-intrinsics.h index 63fe9c926..6c577733d 100644 --- a/prelude/slang-cpp-scalar-intrinsics.h +++ b/prelude/slang-cpp-scalar-intrinsics.h @@ -3,6 +3,11 @@ #include "../slang.h" +#if SLANG_PROCESSOR_X86_64 && SLANG_VC +// If we have visual studio and 64 bit processor, we can assume we have popcnt, and can include x86 intrinsics +# include +#endif + #ifdef SLANG_PRELUDE_NAMESPACE namespace SLANG_PRELUDE_NAMESPACE { #endif @@ -192,7 +197,22 @@ SLANG_FORCE_INLINE double U32_asdouble(uint32_t low, uint32_t hi) return u.d; } - +SLANG_FORCE_INLINE uint32_t U32_countbits(uint32_t v) +{ +#if SLANG_GCC_FAMILY + return __builtin_popcount(v); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + return __popcnt(v); +#else + uint32_t c = 0; + while (v) + { + c++; + v &= v - 1; + } + return c; +#endif +} #ifdef SLANG_PRELUDE_NAMESPACE diff --git a/prelude/slang-cuda-prelude.h b/prelude/slang-cuda-prelude.h index 8d100b0db..f78814486 100644 --- a/prelude/slang-cuda-prelude.h +++ b/prelude/slang-cuda-prelude.h @@ -161,6 +161,13 @@ SLANG_CUDA_CALL double U32_asdouble(uint32_t low, uint32_t hi) return u.d; } +SLANG_CUDA_CALL uint32_t U32_countbits(uint32_t v) +{ + // https://docs.nvidia.com/cuda/cuda-math-api/group__CUDA__MATH__INTRINSIC__INT.html#group__CUDA__MATH__INTRINSIC__INT_1g43c9c7d2b9ebf202ff1ef5769989be46 + return __popc(v); +} + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index db442d131..5dd028182 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -969,6 +969,8 @@ void CPPSourceEmitter::_emitGetAtDefinition(const UnownedStringSlice& funcName, IRType* srcType = funcType->getParamType(0); + emitSpecializedOperationDefinitionPreamble(specOp); + IRType* retType = specOp->returnType; emitType(retType); m_writer->emit("& "); @@ -1046,6 +1048,8 @@ void CPPSourceEmitter::_emitConstructConvertDefinition(const UnownedStringSlice& IRType* srcType = funcType->getParamType(1); IRType* retType = specOp->returnType; + emitSpecializedOperationDefinitionPreamble(specOp); + emitType(retType); writer->emit(" "); writer->emit(funcName); @@ -1112,6 +1116,8 @@ void CPPSourceEmitter::_emitConstructFromScalarDefinition(const UnownedStringSli IRType* srcType = funcType->getParamType(1); IRType* retType = specOp->returnType; + emitSpecializedOperationDefinitionPreamble(specOp); + emitType(retType); writer->emit(" "); writer->emit(funcName); diff --git a/source/slang/slang-hlsl-intrinsic-set.h b/source/slang/slang-hlsl-intrinsic-set.h index d55c908ae..df1677b17 100644 --- a/source/slang/slang-hlsl-intrinsic-set.h +++ b/source/slang/slang-hlsl-intrinsic-set.h @@ -123,7 +123,9 @@ just constructXXXFromScalar. Would be good if there was a suitable name to encom x(ConstructFromScalar, "", 1) \ \ x(GetAt, "", 2) \ - x(SetAt, "", 3) + x(SetAt, "", 3) \ + \ + x(CountBits, "countbits", 1) struct HLSLIntrinsic { diff --git a/tests/compute/bit-cast-double.slang b/tests/compute/bit-cast-double.slang deleted file mode 100644 index 6b0925a58..000000000 --- a/tests/compute/bit-cast-double.slang +++ /dev/null @@ -1,21 +0,0 @@ -//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cpu -//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute - -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer -RWStructuredBuffer outputBuffer; - -[numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - double d = double(dispatchThreadID.x); - - uint hi, low; - asuint(d, low, hi); - - // Reconstruct - double r = asdouble(low, hi); - - outputBuffer[dispatchThreadID.x] = int(r); -} \ No newline at end of file diff --git a/tests/compute/bit-cast-double.slang.expected.txt b/tests/compute/bit-cast-double.slang.expected.txt deleted file mode 100644 index bc856dafa..000000000 --- a/tests/compute/bit-cast-double.slang.expected.txt +++ /dev/null @@ -1,4 +0,0 @@ -0 -1 -2 -3 diff --git a/tests/compute/bit-cast.slang b/tests/compute/bit-cast.slang deleted file mode 100644 index a8fec61e3..000000000 --- a/tests/compute/bit-cast.slang +++ /dev/null @@ -1,71 +0,0 @@ -//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_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name outputBuffer - -RWStructuredBuffer outputBuffer; - -[numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - const int id = asint(dispatchThreadID.x); - - { - int4 i4 = int4(id, id + 1, id + 2, id + 3); - - // Identity - int vector - i4 = asint(i4); - - uint3 u3 = asuint(i4.xyz); - // Identity - uint vec - u3 = asuint(u3); - - int2 i2 = asint(u3.xy); - uint u1 = asuint(i2.x); - - // Identity - uint scalar - u1 = asuint(u1); - - outputBuffer[id + 0] = int(u1); - } - - { - uint v = asuint(id); - uint4 u4 = uint4(v, v + 1, v + 2, v + 3); - int3 i3 = asint(u4.xyz); - uint2 u2 = asuint(i3.xy); - int i1 = asint(u2.x); - - // Identity - int scalar - i1 = asint(i1); - - outputBuffer[id + 4] = i1; - } - - { - // Make i4 holds id as floats so we know they are valid float values and not denormals - int4 i4 = int4(asint(float(id)), asint(float(id + 1)), asint(float(id + 2)), asint(float(id + 3))); - float4 f4 = asfloat(asfloat(i4)); - - // Identity - float vector - f4 = asfloat(f4); - - uint3 u3 = asuint(f4.xyz); - float2 f2 = asfloat(u3.xy); - uint u1 = asuint(f2.x); - - float f1 = asfloat(asfloat(u1)); - - // Identity - float scalar - f1 = asfloat(f1); - - int i1 = asint(f1); - - float f1_ = asfloat(i1); - int i1_ = asint(f1_); - - outputBuffer[id + 8] = (int)asfloat(i1_); - } -} \ No newline at end of file diff --git a/tests/compute/bit-cast.slang.expected.txt b/tests/compute/bit-cast.slang.expected.txt deleted file mode 100644 index f5414793f..000000000 --- a/tests/compute/bit-cast.slang.expected.txt +++ /dev/null @@ -1,12 +0,0 @@ -0 -1 -2 -3 -0 -1 -2 -3 -0 -1 -2 -3 \ No newline at end of file diff --git a/tests/hlsl-intrinsic/bit-cast-double.slang b/tests/hlsl-intrinsic/bit-cast-double.slang new file mode 100644 index 000000000..b52c9de2b --- /dev/null +++ b/tests/hlsl-intrinsic/bit-cast-double.slang @@ -0,0 +1,22 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cpu +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-slang -vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -cuda -compute + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + double d = double(dispatchThreadID.x); + + uint hi, low; + asuint(d, low, hi); + + // Reconstruct + double r = asdouble(low, hi); + + outputBuffer[dispatchThreadID.x] = int(r); +} \ No newline at end of file diff --git a/tests/hlsl-intrinsic/bit-cast-double.slang.expected.txt b/tests/hlsl-intrinsic/bit-cast-double.slang.expected.txt new file mode 100644 index 000000000..bc856dafa --- /dev/null +++ b/tests/hlsl-intrinsic/bit-cast-double.slang.expected.txt @@ -0,0 +1,4 @@ +0 +1 +2 +3 diff --git a/tests/hlsl-intrinsic/bit-cast.slang b/tests/hlsl-intrinsic/bit-cast.slang new file mode 100644 index 000000000..4ecd911d7 --- /dev/null +++ b/tests/hlsl-intrinsic/bit-cast.slang @@ -0,0 +1,72 @@ +//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):COMPARE_COMPUTE_EX:-cuda -compute + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0], stride=4):out,name outputBuffer + +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + const int id = asint(dispatchThreadID.x); + + { + int4 i4 = int4(id, id + 1, id + 2, id + 3); + + // Identity - int vector + i4 = asint(i4); + + uint3 u3 = asuint(i4.xyz); + // Identity - uint vec + u3 = asuint(u3); + + int2 i2 = asint(u3.xy); + uint u1 = asuint(i2.x); + + // Identity - uint scalar + u1 = asuint(u1); + + outputBuffer[id + 0] = int(u1); + } + + { + uint v = asuint(id); + uint4 u4 = uint4(v, v + 1, v + 2, v + 3); + int3 i3 = asint(u4.xyz); + uint2 u2 = asuint(i3.xy); + int i1 = asint(u2.x); + + // Identity - int scalar + i1 = asint(i1); + + outputBuffer[id + 4] = i1; + } + + { + // Make i4 holds id as floats so we know they are valid float values and not denormals + int4 i4 = int4(asint(float(id)), asint(float(id + 1)), asint(float(id + 2)), asint(float(id + 3))); + float4 f4 = asfloat(asfloat(i4)); + + // Identity - float vector + f4 = asfloat(f4); + + uint3 u3 = asuint(f4.xyz); + float2 f2 = asfloat(u3.xy); + uint u1 = asuint(f2.x); + + float f1 = asfloat(asfloat(u1)); + + // Identity - float scalar + f1 = asfloat(f1); + + int i1 = asint(f1); + + float f1_ = asfloat(i1); + int i1_ = asint(f1_); + + outputBuffer[id + 8] = (int)asfloat(i1_); + } +} \ No newline at end of file diff --git a/tests/hlsl-intrinsic/bit-cast.slang.expected.txt b/tests/hlsl-intrinsic/bit-cast.slang.expected.txt new file mode 100644 index 000000000..f5414793f --- /dev/null +++ b/tests/hlsl-intrinsic/bit-cast.slang.expected.txt @@ -0,0 +1,12 @@ +0 +1 +2 +3 +0 +1 +2 +3 +0 +1 +2 +3 \ No newline at end of file diff --git a/tests/hlsl-intrinsic/scalar-int.slang b/tests/hlsl-intrinsic/scalar-int.slang new file mode 100644 index 000000000..7fccc8645 --- /dev/null +++ b/tests/hlsl-intrinsic/scalar-int.slang @@ -0,0 +1,25 @@ +//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 + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = int(dispatchThreadID.x); + + int ti =0; + + ti += max(2, idx); + ti += min(idx, 1); + ti += abs(idx - 2); + ti += (idx * 3) % 5; + + ti += clamp(idx * 10, 11, 23); + + outputBuffer[idx] = ti; +} \ No newline at end of file diff --git a/tests/hlsl-intrinsic/scalar-int.slang.expected.txt b/tests/hlsl-intrinsic/scalar-int.slang.expected.txt new file mode 100644 index 000000000..4efe33dc6 --- /dev/null +++ b/tests/hlsl-intrinsic/scalar-int.slang.expected.txt @@ -0,0 +1,4 @@ +F +12 +18 +20 diff --git a/tests/hlsl-intrinsic/scalar-uint.slang b/tests/hlsl-intrinsic/scalar-uint.slang new file mode 100644 index 000000000..eb16bb3b8 --- /dev/null +++ b/tests/hlsl-intrinsic/scalar-uint.slang @@ -0,0 +1,26 @@ +//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 + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + uint idx = dispatchThreadID.x; + + uint ti = 0; + + ti += max(2, idx); + ti += min(idx, 1); + ti += (idx * 3) %5; + + ti += clamp(idx * 10, 11, 23); + + ti += countbits(idx * 13); + + outputBuffer[idx] = ti; +} \ No newline at end of file diff --git a/tests/hlsl-intrinsic/scalar-uint.slang.expected.txt b/tests/hlsl-intrinsic/scalar-uint.slang.expected.txt new file mode 100644 index 000000000..1a7befbe1 --- /dev/null +++ b/tests/hlsl-intrinsic/scalar-uint.slang.expected.txt @@ -0,0 +1,4 @@ +D +14 +1B +23 diff --git a/tests/hlsl-intrinsic/vector-int.slang b/tests/hlsl-intrinsic/vector-int.slang new file mode 100644 index 000000000..9a3f1faaa --- /dev/null +++ b/tests/hlsl-intrinsic/vector-int.slang @@ -0,0 +1,50 @@ +//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 + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = int(dispatchThreadID.x); + + int3 a = { idx + 10, idx - 9, idx + 3}; + int3 b = { idx * 2, idx * 3, idx * 10}; + + int3 t = { 0, 0, 0}; + + t += max(a, b); + t += min(a, b); + t += abs(a); + t += b % 5; + + t += clamp(a, int3(10), int3(23)); + + // Swizzle + t += a.zyx; + // Swizzle from scalar + t += idx.xxx; + +#if 0 + // TODO(JS): On C++ not all accesses are turned into getAt/setAt, so disable for now. + // Reads + { + t += int3(a[idx % 3], a[0], b[2]); + } + + // Writes + { + int3 v = int3(b[(idx + 1) % 3], b[(idx + 2) % 3], b[(idx + 3) % 3]); + v[1] += v[0]; + v[idx & 1] += v[2]; + + t += v; + } +#endif + + outputBuffer[idx] = t.x + t.y + t.z; +} \ No newline at end of file diff --git a/tests/hlsl-intrinsic/vector-int.slang.expected.txt b/tests/hlsl-intrinsic/vector-int.slang.expected.txt new file mode 100644 index 000000000..e4c658883 --- /dev/null +++ b/tests/hlsl-intrinsic/vector-int.slang.expected.txt @@ -0,0 +1,4 @@ +3C +5B +75 +8F diff --git a/tools/render-test/bind-location.cpp b/tools/render-test/bind-location.cpp index 30b9de0f8..114ca7e8e 100644 --- a/tools/render-test/bind-location.cpp +++ b/tools/render-test/bind-location.cpp @@ -482,7 +482,7 @@ BindLocation BindSet::toIndex(const BindLocation& loc, Index index) const size_t baseOffset = loc.m_bindPointSet->m_points[category].m_offset; - if (category == SLANG_PARAMETER_CATEGORY_UNIFORM && uniformValue != loc.m_value) + if (category == slang::ParameterCategory::Uniform && uniformValue != loc.m_value) { baseOffset = 0; } -- cgit v1.2.3