瀏覽代碼

[spirv] reply on spirv-val for variable offset for OpImage* validation (#3656)

spirv-val reports a validation error when we use variable offset for
OpImage*. We have to rely on spirv-val for the validation instead of
doing it in DXC. In particular, when the HLSL code uses the loop
invariant variable for the Sample() intrinsics, it should be a constant
value after conducting the loop unrolling. Since we rely on spirv-opt
for the loop unrolling, we should not report the validation error in
DXC.

Fixes #3575
Jaebaek Seo 4 年之前
父節點
當前提交
c879f2f9b5

+ 0 - 15
tools/clang/lib/SPIRV/SpirvEmitter.cpp

@@ -4398,13 +4398,6 @@ SpirvInstruction *SpirvEmitter::createImageSample(
     SpirvInstruction *minLod, SpirvInstruction *residencyCodeId,
     SourceLocation loc) {
 
-  if (varOffset) {
-    emitError("Use constant value for offset (SPIR-V spec does not accept a "
-              "variable offset for OpImage* instructions other than "
-              "OpImage*Gather)", loc);
-    return nullptr;
-  }
-
   // SampleDref* instructions in SPIR-V always return a scalar.
   // They also have the correct type in HLSL.
   if (compareVal) {
@@ -4837,14 +4830,6 @@ SpirvEmitter::processBufferTextureLoad(const CXXMemberCallExpr *expr) {
         handleOffsetInMethodCall(expr, 1, &constOffset, &varOffset);
     }
 
-    if (hasOffsetArg && varOffset) {
-      emitError("Use constant value for offset (SPIR-V spec does not accept a "
-                "variable offset for OpImage* instructions other than "
-                "OpImage*Gather)",
-                expr->getArg(textureMS ? 2 : 1)->getExprLoc());
-      return nullptr;
-    }
-
     return processBufferTextureLoad(object, coordinate, constOffset, varOffset,
                                     lod, status, loc);
   }

+ 0 - 20
tools/clang/test/CodeGenSPIRV/texture.load-invalid-offset-operand.hlsl

@@ -1,20 +0,0 @@
-// Run: %dxc -T ps_6_0 -E main
-
-Texture1D       <float4> t1 : register(t1);
-Texture2DMS     <float>  t2 : register(t2);
-
-float4 main(int3 location: A, int offset: B) : SV_Target {
-    uint status;
-
-// CHECK: Use constant value for offset (SPIR-V spec does not accept a variable offset for OpImage* instructions other than OpImage*Gather)
-    float4 val1 = t1.Load(int2(1, 2), offset);
-
-    int sampleIndex = 7;
-    int2 pos2 = int2(2, 3);
-    int2 offset2 = int2(1, 2);
-
-// CHECK: Use constant value for offset (SPIR-V spec does not accept a variable offset for OpImage* instructions other than OpImage*Gather)
-    float val2 = t2.Load(pos2, sampleIndex, offset2);
-
-    return 1.0;
-}

+ 0 - 25
tools/clang/test/CodeGenSPIRV/texture.sample-invalid-offset-operand.hlsl

@@ -1,25 +0,0 @@
-// Run: %dxc -T vs_6_0 -E main
-
-SamplerState gSampler : register(s5);
-
-// Note: The front end forbids sampling from non-floating-point texture formats.
-
-Texture1D   <float4> t1 : register(t1);
-Texture2D   <float4> t2 : register(t2);
-Texture3D   <float4> t3 : register(t3);
-TextureCube <float4> t4 : register(t4);
-
-float4 main(int2 offset: A) : SV_Position {
-// CHECK: Use constant value for offset (SPIR-V spec does not accept a variable offset for OpImage* instructions other than OpImage*Gather)
-    float4 val2 = t2.Sample(gSampler, float2(0.5, 0.25), offset);
-
-    float clamp;
-// CHECK: Use constant value for offset (SPIR-V spec does not accept a variable offset for OpImage* instructions other than OpImage*Gather)
-    float4 val5 = t2.Sample(gSampler, float2(0.5, 0.25), offset, clamp);
-
-    uint status;
-// CHECK: Use constant value for offset (SPIR-V spec does not accept a variable offset for OpImage* instructions other than OpImage*Gather)
-    float4 val7 = t2.Sample(gSampler, float2(0.5, 0.25), offset, clamp, status);
-
-    return float4(0.0, 0.0, 0.0, 1.0);
-}

+ 23 - 0
tools/clang/test/CodeGenSPIRV/texture.sample-offset.with.loop-unroll.hlsl

@@ -0,0 +1,23 @@
+// Run: %dxc -T ps_6_0 -E main -Oconfig=--legalize-hlsl
+
+SamplerState      gSampler  : register(s5);
+Texture2D<float4> t         : register(t1);
+
+// CHECK: [[vi0:%\d+]] = OpConstantComposite %v2int %int_0 %int_0
+// CHECK: [[vi1:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
+// CHECK: [[vi2:%\d+]] = OpConstantComposite %v2int %int_2 %int_2
+
+float4 main(int2 offset: A) : SV_Target {
+    uint status = offset.x;
+    float clamp = offset.x;
+    float4 ret = 0;
+
+// CHECK: OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|ConstOffset %float_0 [[vi0]]
+// CHECK: OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|ConstOffset %float_0 [[vi1]]
+// CHECK: OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|ConstOffset %float_0 [[vi2]]
+
+    [unroll] for(int i = 0; i < 3; ++i)
+        ret += t.SampleLevel(gSampler, float2(0.1, 0.2), 0.0, /*offset*/ i);
+
+    return ret;
+}

+ 3 - 6
tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

@@ -872,9 +872,6 @@ TEST_F(FileTest, TextureArraySample) {
 }
 TEST_F(FileTest, TextureLoad) { runFileTest("texture.load.hlsl"); }
 TEST_F(FileTest, TextureArrayLoad) { runFileTest("texture.array.load.hlsl"); }
-TEST_F(FileTest, TextureLoadInvalidOffsetOperand) {
-  runFileTest("texture.load-invalid-offset-operand.hlsl", Expect::Failure);
-}
 TEST_F(FileTest, TextureGetDimensions) {
   runFileTest("texture.get-dimensions.hlsl");
 }
@@ -957,12 +954,12 @@ TEST_F(FileTest, TextureArraySampleCmpLevelZero) {
 TEST_F(FileTest, TextureSampleInvalidImplicitLod) {
   runFileTest("texture.sample-invalid-implicit-lod.hlsl", Expect::Failure);
 }
-TEST_F(FileTest, TextureSampleInvalidOffsetOperand) {
-  runFileTest("texture.sample-invalid-offset-operand.hlsl", Expect::Failure);
-}
 TEST_F(FileTest, TextureInvalidTex2D) {
   runFileTest("texture.sample.invalid.tex2d.hlsl", Expect::Failure);
 }
+TEST_F(FileTest, TextureSampleOffsetWithLoopUnroll) {
+  runFileTest("texture.sample-offset.with.loop-unroll.hlsl");
+}
 
 // For structured buffer methods
 TEST_F(FileTest, StructuredBufferLoad) {