From 4a4d1134ef1874abd693621ebf760bc806bcdfd5 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Thu, 16 Nov 2017 14:23:03 -0500 Subject: [PATCH] [spirv] Emit unsupported error for some intrinsics (#797) * abort * GetRenderTargetSampleCount * GetRenderTargetSamplePosition * GatherCmpGreen * GatherCmpBlue * GatherCmpAlpha * GetSamplePosition * CalculateLevelOfDetailUnclamped --- docs/SPIR-V.rst | 28 +++++++++++++++++++ tools/clang/lib/SPIRV/SPIRVEmitter.cpp | 28 +++++++++++++++---- .../test/CodeGenSPIRV/intrinsics.abort.hlsl | 7 +++++ ...insics.get-render-target-sample-count.hlsl | 7 +++++ ...ics.get-render-target-sample-position.hlsl | 7 +++++ .../texture.calculate-lod-unclamped.hlsl | 13 +++++++++ .../texture.gather-cmp-alpha.hlsl | 11 ++++++++ .../CodeGenSPIRV/texture.gather-cmp-blue.hlsl | 11 ++++++++ .../texture.gather-cmp-green.hlsl | 11 ++++++++ .../texture.get-sample-position.hlsl | 9 ++++++ .../unittests/SPIRV/CodeGenSPIRVTest.cpp | 28 +++++++++++++++++++ 11 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 tools/clang/test/CodeGenSPIRV/intrinsics.abort.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-count.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-position.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/texture.calculate-lod-unclamped.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/texture.gather-cmp-alpha.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/texture.gather-cmp-blue.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/texture.gather-cmp-green.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/texture.get-sample-position.hlsl diff --git a/docs/SPIR-V.rst b/docs/SPIR-V.rst index c8db1564d..79be2f259 100644 --- a/docs/SPIR-V.rst +++ b/docs/SPIR-V.rst @@ -2237,3 +2237,31 @@ codegen for Vulkan: - ``-fvk-stage-io-order={alpha|decl}``: Assigns the stage input/output variable location number according to alphabetical order or declaration order. See `HLSL semantic and Vulkan Location`_ for more details. + +Unsupported HLSL Features +========================= + +The following HLSL language features are not supported in SPIR-V codegen, +either because of no Vulkan equivalents at the moment, or because of deprecation. + +* Literal/immediate sampler state: deprecated feature. The compiler will + emit a warning and ignore it. +* ``abort()`` intrinsic function: no Vulkan equivalent. The compiler will emit + an error. +* ``GetRenderTargetSampleCount()`` intrinsic function: no Vulkan equivalent. + (Its GLSL counterpart is ``gl_NumSamples``, which is not available in GLSL for + Vulkan.) The compiler will emit an error. +* ``GetRenderTargetSamplePosition()`` intrinsic function: no Vulkan equivalent. + (``gl_SamplePosition`` provides similar functionality but it's only for the + sample currently being processed.) The compiler will emit an error. +* ``tex*()`` intrinsic functions: deprecated features. The compiler will + emit errors. +* ``.GatherCmpGreen()``, ``.GatherCmpBlue()``, ``.GatherCmpAlpha()`` intrinsic + method: no Vulkan equivalent. (SPIR-V ``OpImageDrefGather`` instruction does + not take component as input.) The compiler will emit an error. +* ``.CalculateLevelOfDetailUnclamped()`` intrinsic method: no Vulkan equivalent. + (SPIR-V ``OpImageQueryLod`` returns the clamped LOD in Vulkan.) The compiler + will emit an error. +* ``.GetSamplePosition()`` intrinsic method: no Vulkan equivalent. + (``gl_SamplePosition`` provides similar functionality but it's only for the + sample currently being processed.) The compiler will emit an error. diff --git a/tools/clang/lib/SPIRV/SPIRVEmitter.cpp b/tools/clang/lib/SPIRV/SPIRVEmitter.cpp index fd6c14e11..03feecc05 100644 --- a/tools/clang/lib/SPIRV/SPIRVEmitter.cpp +++ b/tools/clang/lib/SPIRV/SPIRVEmitter.cpp @@ -2513,9 +2513,19 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr, case IntrinsicOp::MOP_InterlockedCompareExchange: case IntrinsicOp::MOP_InterlockedCompareStore: return processRWByteAddressBufferAtomicMethods(opcode, expr); + case IntrinsicOp::MOP_GatherCmpGreen: + case IntrinsicOp::MOP_GatherCmpBlue: + case IntrinsicOp::MOP_GatherCmpAlpha: + case IntrinsicOp::MOP_GetSamplePosition: + case IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped: + emitError("no equivalent for %0 intrinsic method in Vulkan", + expr->getCallee()->getExprLoc()) + << expr->getMethodDecl()->getName(); + return 0; } - emitError("intrinsic '%0' method unimplemented", expr->getExprLoc()) + emitError("intrinsic '%0' method unimplemented", + expr->getCallee()->getExprLoc()) << expr->getDirectCallee()->getName(); return 0; } @@ -4212,6 +4222,14 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) { return processIntrinsicF16ToF32(callExpr); case hlsl::IntrinsicOp::IOP_f32tof16: return processIntrinsicF32ToF16(callExpr); + case hlsl::IntrinsicOp::IOP_abort: + case hlsl::IntrinsicOp::IOP_GetRenderTargetSampleCount: + case hlsl::IntrinsicOp::IOP_GetRenderTargetSamplePosition: { + emitError("no equivalent for %0 intrinsic function in Vulkan", + callExpr->getExprLoc()) + << callee->getName(); + return 0; + } INTRINSIC_SPIRV_OP_CASE(transpose, Transpose, false); INTRINSIC_SPIRV_OP_CASE(ddx, DPdx, true); INTRINSIC_SPIRV_OP_WITH_CAP_CASE(ddx_coarse, DPdxCoarse, false, @@ -4276,7 +4294,7 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) { INTRINSIC_OP_CASE(sqrt, Sqrt, true); INTRINSIC_OP_CASE(trunc, Trunc, true); default: - emitError("intrinsic '%0' function unimplemented", callExpr->getExprLoc()) + emitError("%0 intrinsic function unimplemented", callExpr->getExprLoc()) << callee->getName(); return 0; } @@ -5181,7 +5199,7 @@ uint32_t SPIRVEmitter::processIntrinsicAsType(const CallExpr *callExpr) { return 0; } default: - emitError("unrecognized signature for intrinsic function %0", + emitError("unrecognized signature for %0 intrinsic function", callExpr->getExprLoc()) << callExpr->getDirectCallee()->getName(); return 0; @@ -5429,7 +5447,7 @@ uint32_t SPIRVEmitter::processIntrinsicUsingSpirvInst( return theBuilder.createBinaryOp(opcode, returnType, arg0Id, arg1Id); } - emitError("unsupported intrinsic function %0", callExpr->getExprLoc()) + emitError("unsupported %0 intrinsic function", callExpr->getExprLoc()) << cast(callExpr->getCallee())->getNameInfo().getAsString(); return 0; } @@ -5501,7 +5519,7 @@ uint32_t SPIRVEmitter::processIntrinsicUsingGLSLInst( {arg0Id, arg1Id, arg2Id}); } - emitError("unsupported intrinsic function %0", callExpr->getExprLoc()) + emitError("unsupported %0 intrinsic function", callExpr->getExprLoc()) << cast(callExpr->getCallee())->getNameInfo().getAsString(); return 0; } diff --git a/tools/clang/test/CodeGenSPIRV/intrinsics.abort.hlsl b/tools/clang/test/CodeGenSPIRV/intrinsics.abort.hlsl new file mode 100644 index 000000000..0b1defbb8 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.abort.hlsl @@ -0,0 +1,7 @@ +// Run: %dxc -T ps_6_0 -E main + +void main() { + abort(); +} + +// CHECK: :4:5: error: no equivalent for abort intrinsic function in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-count.hlsl b/tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-count.hlsl new file mode 100644 index 000000000..4e54b75e4 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-count.hlsl @@ -0,0 +1,7 @@ +// Run: %dxc -T ps_6_0 -E main + +void main() { + uint a = GetRenderTargetSampleCount(); +} + +// CHECK: :4:14: error: no equivalent for GetRenderTargetSampleCount intrinsic function in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-position.hlsl b/tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-position.hlsl new file mode 100644 index 000000000..f1db8038d --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.get-render-target-sample-position.hlsl @@ -0,0 +1,7 @@ +// Run: %dxc -T ps_6_0 -E main + +void main() { + uint a = GetRenderTargetSamplePosition(2); +} + +// CHECK: :4:14: error: no equivalent for GetRenderTargetSamplePosition intrinsic function in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/texture.calculate-lod-unclamped.hlsl b/tools/clang/test/CodeGenSPIRV/texture.calculate-lod-unclamped.hlsl new file mode 100644 index 000000000..fbc12fa45 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/texture.calculate-lod-unclamped.hlsl @@ -0,0 +1,13 @@ +// Run: %dxc -T ps_6_0 -E main + +SamplerState ss : register(s2); + +Texture1D t1; + +void main() { + float x = 0.5; + + float lod1 = t1.CalculateLevelOfDetailUnclamped(ss, x); +} + +// CHECK: :10:19: error: no equivalent for CalculateLevelOfDetailUnclamped intrinsic method in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-alpha.hlsl b/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-alpha.hlsl new file mode 100644 index 000000000..e0e7c0401 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-alpha.hlsl @@ -0,0 +1,11 @@ +// Run: %dxc -T ps_6_0 -E main + +SamplerComparisonState gSampler : register(s5); + +Texture2D myTexture : register(t1); + +float4 main(float2 location: A, float comparator: B) : SV_Target { + return myTexture.GatherCmpAlpha(gSampler, location, comparator, int2(1, 2)); +} + +// CHECK: :8:22: error: no equivalent for GatherCmpAlpha intrinsic method in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-blue.hlsl b/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-blue.hlsl new file mode 100644 index 000000000..b7b5ebaa9 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-blue.hlsl @@ -0,0 +1,11 @@ +// Run: %dxc -T ps_6_0 -E main + +SamplerComparisonState gSampler : register(s5); + +Texture2D gTexture : register(t1); + +float4 main(float2 location: A, float comparator: B) : SV_Target { + return gTexture.GatherCmpBlue(gSampler, location, comparator, int2(1, 2)); +} + +// CHECK: :8:21: error: no equivalent for GatherCmpBlue intrinsic method in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-green.hlsl b/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-green.hlsl new file mode 100644 index 000000000..edd3f2fd2 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/texture.gather-cmp-green.hlsl @@ -0,0 +1,11 @@ +// Run: %dxc -T ps_6_0 -E main + +SamplerComparisonState gSampler : register(s5); + +Texture2D myTexture : register(t1); + +float4 main(float2 location: A, float comparator: B) : SV_Target { + return myTexture.GatherCmpGreen(gSampler, location, comparator, int2(1, 2)); +} + +// CHECK: :8:22: error: no equivalent for GatherCmpGreen intrinsic method in Vulkan diff --git a/tools/clang/test/CodeGenSPIRV/texture.get-sample-position.hlsl b/tools/clang/test/CodeGenSPIRV/texture.get-sample-position.hlsl new file mode 100644 index 000000000..641b16687 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/texture.get-sample-position.hlsl @@ -0,0 +1,9 @@ +// Run: %dxc -T ps_6_0 -E main + +Texture2DMS myTexture; + +void main() { + float2 ret = myTexture.GetSamplePosition(2); +} + +// CHECK: :6:26: error: no equivalent for GetSamplePosition intrinsic method in Vulkan diff --git a/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp index 5f22b5b91..c84b2d83b 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp @@ -512,9 +512,15 @@ TEST_F(FileTest, TextureArrayLoad) { runFileTest("texture.array.load.hlsl"); } TEST_F(FileTest, TextureGetDimensions) { runFileTest("texture.get-dimensions.hlsl"); } +TEST_F(FileTest, TextureGetSamplePosition) { + runFileTest("texture.get-sample-position.hlsl", Expect::Failure); +} TEST_F(FileTest, TextureCalculateLevelOfDetail) { runFileTest("texture.calculate-lod.hlsl"); } +TEST_F(FileTest, TextureCalculateLevelOfDetailUnclamped) { + runFileTest("texture.calculate-lod-unclamped.hlsl", Expect::Failure); +} TEST_F(FileTest, TextureGather) { runFileTest("texture.gather.hlsl"); } TEST_F(FileTest, TextureArrayGather) { runFileTest("texture.array.gather.hlsl"); @@ -549,6 +555,15 @@ TEST_F(FileTest, TextureGatherCmpRed) { TEST_F(FileTest, TextureArrayGatherCmpRed) { runFileTest("texture.array.gather-cmp-red.hlsl"); } +TEST_F(FileTest, TextureArrayGatherCmpGreen) { + runFileTest("texture.gather-cmp-green.hlsl", Expect::Failure); +} +TEST_F(FileTest, TextureArrayGatherCmpBlue) { + runFileTest("texture.gather-cmp-blue.hlsl", Expect::Failure); +} +TEST_F(FileTest, TextureArrayGatherCmpAlpha) { + runFileTest("texture.gather-cmp-alpha.hlsl", Expect::Failure); +} TEST_F(FileTest, TextureSampleLevel) { runFileTest("texture.sample-level.hlsl"); } @@ -771,6 +786,19 @@ TEST_F(FileTest, IntrinsicsAcos) { runFileTest("intrinsics.acos.hlsl"); } TEST_F(FileTest, IntrinsicsAtan) { runFileTest("intrinsics.atan.hlsl"); } TEST_F(FileTest, IntrinsicsAtan2) { runFileTest("intrinsics.atan2.hlsl"); } +// Unspported intrinsic functions +TEST_F(FileTest, IntrinsicsAbort) { + runFileTest("intrinsics.abort.hlsl", Expect::Failure); +} +TEST_F(FileTest, IntrinsicsGetRenderTargetSampleCount) { + runFileTest("intrinsics.get-render-target-sample-count.hlsl", + Expect::Failure); +} +TEST_F(FileTest, IntrinsicsGetRenderTargetSamplePosition) { + runFileTest("intrinsics.get-render-target-sample-position.hlsl", + Expect::Failure); +} + // For attributes TEST_F(FileTest, AttributeNumThreads) { runFileTest("attribute.numthreads.hlsl");