ソースを参照

[spirv] Emit unsupported error for some intrinsics (#797)

* abort
* GetRenderTargetSampleCount
* GetRenderTargetSamplePosition
* GatherCmpGreen
* GatherCmpBlue
* GatherCmpAlpha
* GetSamplePosition
* CalculateLevelOfDetailUnclamped
Lei Zhang 7 年 前
コミット
4a4d1134ef

+ 28 - 0
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.

+ 23 - 5
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<DeclRefExpr>(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<DeclRefExpr>(callExpr->getCallee())->getNameInfo().getAsString();
   return 0;
 }

+ 7 - 0
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

+ 7 - 0
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

+ 7 - 0
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

+ 13 - 0
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        <float>  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

+ 11 - 0
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<float4> 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

+ 11 - 0
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<float4> 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

+ 11 - 0
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<float4> 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

+ 9 - 0
tools/clang/test/CodeGenSPIRV/texture.get-sample-position.hlsl

@@ -0,0 +1,9 @@
+// Run: %dxc -T ps_6_0 -E main
+
+Texture2DMS       <float> myTexture;
+
+void main() {
+  float2 ret = myTexture.GetSamplePosition(2);
+}
+
+// CHECK: :6:26: error: no equivalent for GetSamplePosition intrinsic method in Vulkan

+ 28 - 0
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");