浏览代码

[spirv] do not accept variable for OpImage* Offset (#3456)

The new spirv-val rule reports an error if we use a variable (not
OpConst*) for OpImage* Offset:
https://github.com/KhronosGroup/SPIRV-Tools/pull/4118

This CL also let the DXC SPIR-V backend report an error if it checks
the HLSL code uses a variable for the `offset` operand of `Sample*`
built-in methods.

It aligns with the DXIL or FXC behavior. They do not accept a variable
for the `offset` operand of `Sample*` built-in methods.
Jaebaek Seo 4 年之前
父节点
当前提交
cff993e0f8

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

@@ -4398,6 +4398,13 @@ 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) {
@@ -4830,6 +4837,14 @@ 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);
   }

+ 1 - 1
tools/clang/test/CodeGenSPIRV/intrinsics.check-access-fully-mapped.hlsl

@@ -10,7 +10,7 @@ Texture2D<float4> t         : register(t1);
 float4 main(int2 offset: A) : SV_Target {
     uint status;
     float clamp;
-    float4 val = t.Sample(gSampler, float2(0.1, 0.2), offset, clamp, status);
+    float4 val = t.Sample(gSampler, float2(0.1, 0.2), 1, clamp, status);
     
 // CHECK: [[residency_code:%\d+]] = OpLoad %uint %status
 // CHECK:        [[success:%\d+]] = OpImageSparseTexelsResident %bool [[residency_code]]

+ 5 - 6
tools/clang/test/CodeGenSPIRV/texture.array.sample-bias.hlsl

@@ -10,12 +10,12 @@ TextureCubeArray <float4> t3 : register(t3);
 Texture2DArray   <float>  t4 : register(t4);
 TextureCubeArray <float3> t5 : register(t5);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability MinLod
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_1
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_1
+// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
 // CHECK: [[v4fc:%\d+]] = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_1
 
 // CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image_array
@@ -32,10 +32,9 @@ float4 main(int2 offset : A) : SV_Target {
 
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|Offset %float_0_5 [[offset]]
-    float4 val2 = t2.SampleBias(gSampler, float3(1, 2, 1), 0.5, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|ConstOffset %float_0_5 [[v2ic]]
+    float4 val2 = t2.SampleBias(gSampler, float3(1, 2, 1), 0.5, 1);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -84,9 +83,9 @@ float4 main(int2 offset : A) : SV_Target {
 // Make sure OpImageSparseSampleImplicitLod returns a struct, in which the second member is a vec4.
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-// CHECK: [[v4result:%\d+]] = OpImageSampleImplicitLod %v4float {{%\d+}} {{%\d+}} Bias|Offset %float_0_5 {{%\d+}}
+// CHECK: [[v4result:%\d+]] = OpImageSampleImplicitLod %v4float {{%\d+}} {{%\d+}} Bias|ConstOffset %float_0_5 {{%\w+}}
 // CHECK:           {{%\d+}} = OpCompositeExtract %float [[v4result]] 0
-    float  val8 = t4.SampleBias(gSampler, float3(1, 2, 1), 0.5, offset);
+    float  val8 = t4.SampleBias(gSampler, float3(1, 2, 1), 0.5, 1);
 
 // CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Bias|MinLod %float_0_5 %float_2_5
 // CHECK:     [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1

+ 5 - 6
tools/clang/test/CodeGenSPIRV/texture.array.sample-cmp-level-zero.hlsl

@@ -10,6 +10,7 @@ TextureCubeArray <float>  t3 : register(t3);
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_1
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_1
+// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
 // CHECK: [[v4fc:%\d+]] = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_1
 
 // CHECK: %SparseResidencyStruct = OpTypeStruct %uint %float
@@ -25,10 +26,9 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefExplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] Lod|Offset %float_0 [[offset]]
-    float val2 = t2.SampleCmpLevelZero(gSampler, float3(1, 2, 1), comparator, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefExplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] Lod|ConstOffset %float_0 [[v2ic]]
+    float val2 = t2.SampleCmpLevelZero(gSampler, float3(1, 2, 1), comparator, 1);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -41,14 +41,13 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK:                [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT:   [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] [[comparator]] Lod|Offset %float_0 [[offset]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] [[comparator]] Lod|ConstOffset %float_0 [[v2ic]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val4 [[result]]
-    float val4 = t2.SampleCmpLevelZero(gSampler, float3(1, 2, 1), comparator, offset, status);
+    float val4 = t2.SampleCmpLevelZero(gSampler, float3(1, 2, 1), comparator, 1, status);
 
 // CHECK:                [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler

+ 7 - 9
tools/clang/test/CodeGenSPIRV/texture.array.sample-cmp.hlsl

@@ -11,6 +11,7 @@ TextureCubeArray <float>  t3 : register(t3);
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_1
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_1
+// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
 // CHECK: [[v4fc:%\d+]] = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_1
 
 // CHECK: %SparseResidencyStruct = OpTypeStruct %uint %float
@@ -26,10 +27,9 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] Offset [[offset]]
-    float val2 = t2.SampleCmp(gSampler, float3(1, 2, 1), comparator, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] ConstOffset [[v2ic]]
+    float val2 = t2.SampleCmp(gSampler, float3(1, 2, 1), comparator, 1);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -43,10 +43,9 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK-NEXT:         [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] Offset|MinLod [[offset]] [[clamp]]
-    float val4 = t2.SampleCmp(gSampler, float3(1, 2, 1), comparator, offset, clamp);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v3fc]] [[comparator]] ConstOffset|MinLod [[v2ic]] [[clamp]]
+    float val4 = t2.SampleCmp(gSampler, float3(1, 2, 1), comparator, 1, clamp);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -60,14 +59,13 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK-NEXT:           [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT:   [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefImplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] [[comparator]] Offset|MinLod [[offset]] [[clamp]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefImplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] [[comparator]] ConstOffset|MinLod [[v2ic]] [[clamp]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val6 [[result]]
-    float val6 = t2.SampleCmp(gSampler, float3(1, 2, 1), comparator, offset, clamp, status);
+    float val6 = t2.SampleCmp(gSampler, float3(1, 2, 1), comparator, 1, clamp, status);
 
 // CHECK:                [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler

+ 9 - 12
tools/clang/test/CodeGenSPIRV/texture.array.sample-grad.hlsl

@@ -11,7 +11,6 @@ Texture2DArray   <float>  t4 : register(t4);
 TextureCubeArray <float2> t5 : register(t5);
 
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability MinLod
 // CHECK: OpCapability SparseResidency
 
@@ -19,6 +18,7 @@ TextureCubeArray <float2> t5 : register(t5);
 // CHECK: [[v3f_1:%\d+]] = OpConstantComposite %v3float %float_1 %float_1 %float_1
 // CHECK: [[v2f_2:%\d+]] = OpConstantComposite %v2float %float_2 %float_2
 // CHECK: [[v2f_3:%\d+]] = OpConstantComposite %v2float %float_3 %float_3
+// CHECK: [[v2i_1:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
 // CHECK: [[v4f_1:%\d+]] = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
 // CHECK: [[v3f_2:%\d+]] = OpConstantComposite %v3float %float_2 %float_2 %float_2
 // CHECK: [[v3f_3:%\d+]] = OpConstantComposite %v3float %float_3 %float_3 %float_3
@@ -37,10 +37,9 @@ float4 main(int2 offset : A) : SV_Target {
 
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_1]] Grad|Offset [[v2f_2]] [[v2f_3]] [[offset]]
-    float4 val2 = t2.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_1]] Grad|ConstOffset [[v2f_2]] [[v2f_3]] [[v2i_1]]
+    float4 val2 = t2.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), 1);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -50,10 +49,9 @@ float4 main(int2 offset : A) : SV_Target {
 
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_1]] Grad|Offset|MinLod [[v2f_2]] [[v2f_3]] [[offset]] %float_2_5
-    float4 val4 = t2.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), offset, /*clamp*/2.5);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3f_1]] Grad|ConstOffset|MinLod [[v2f_2]] [[v2f_3]] [[v2i_1]] %float_2_5
+    float4 val4 = t2.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), 1, /*clamp*/2.5);
 
     float clamp;
 // CHECK:           [[clamp:%\d+]] = OpLoad %float %clamp
@@ -66,14 +64,13 @@ float4 main(int2 offset : A) : SV_Target {
     uint status;
 // CHECK:                [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3f_1]] Grad|Offset|MinLod [[v2f_2]] [[v2f_3]] [[offset]] %float_2_5
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3f_1]] Grad|ConstOffset|MinLod [[v2f_2]] [[v2f_3]] [[v2i_1]] %float_2_5
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val6 [[result]]
-    float4 val6 = t2.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), offset, /*clamp*/2.5, status);
+    float4 val6 = t2.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), 1, /*clamp*/2.5, status);
 
 // CHECK:             [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:           [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
@@ -91,9 +88,9 @@ float4 main(int2 offset : A) : SV_Target {
 // Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4.
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Grad|Offset {{%\d+}} {{%\d+}} {{%\d+}}
+// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Grad|ConstOffset {{%\d+}} {{%\d+}} {{%\w+}}
 // CHECK:          {{%\d+}} = OpCompositeExtract %float [[v4result]] 0
-	float  val8 = t4.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), offset);
+	float  val8 = t4.SampleGrad(gSampler, float3(1, 1, 1), float2(2, 2), float2(3, 3), 1);
 
 // CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Grad|MinLod {{%\d+}} {{%\d+}} {{%\d+}}
 // CHECK:     [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1

+ 6 - 9
tools/clang/test/CodeGenSPIRV/texture.array.sample-level.hlsl

@@ -10,7 +10,6 @@ TextureCubeArray <float4> t3 : register(t3);
 Texture2DArray   <float>  t4 : register(t4);
 TextureCubeArray <float3> t5 : register(t5);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_1
@@ -31,10 +30,9 @@ float4 main(int2 offset : A) : SV_Target {
 
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3fc]] Lod|Offset %float_20 [[offset]]
-    float4 val2 = t2.SampleLevel(gSampler, float3(1, 2, 1), 20, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3fc]] Lod|ConstOffset %float_20
+    float4 val2 = t2.SampleLevel(gSampler, float3(1, 2, 1), 20, 1);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -45,14 +43,13 @@ float4 main(int2 offset : A) : SV_Target {
     uint status;
 // CHECK:                [[t2:%\d+]] = OpLoad %type_2d_image_array %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] Lod|Offset %float_20 [[offset]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] Lod|ConstOffset %float_20
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val4 [[result]]
-    float4 val4 = t2.SampleLevel(gSampler, float3(1, 2, 1), 20, offset, status);
+    float4 val4 = t2.SampleLevel(gSampler, float3(1, 2, 1), 20, 1, status);
 
 // CHECK:                [[t3:%\d+]] = OpLoad %type_cube_image_array %t3
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -69,9 +66,9 @@ float4 main(int2 offset : A) : SV_Target {
 // Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4.
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|Offset %float_20 {{%\d+}}
+// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|ConstOffset %float_20
 // CHECK:          {{%\d+}} = OpCompositeExtract %float [[v4result]] 0
-    float val6 = t4.SampleLevel(gSampler, float3(1, 2, 1), 20, offset);
+    float val6 = t4.SampleLevel(gSampler, float3(1, 2, 1), 20, 1);
 
 // CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Lod %float_30
 // CHECK:     [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1

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

@@ -0,0 +1,20 @@
+// 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;
+}

+ 10 - 15
tools/clang/test/CodeGenSPIRV/texture.load.hlsl

@@ -12,7 +12,6 @@ Texture3D        <uint3> t6 : register(t6);
 Texture2DMS     <float>  t7 : register(t7);
 Texture2DMSArray<float3> t8 : register(t8);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_2
@@ -28,10 +27,9 @@ float4 main(int3 location: A, int offset: B) : SV_Target {
 
 // CHECK:      [[coord:%\d+]] = OpCompositeExtract %int [[v2ic]] 0
 // CHECK-NEXT:   [[lod:%\d+]] = OpCompositeExtract %int [[v2ic]] 1
-// CHECK-NEXT:[[offset:%\d+]] = OpLoad %int %offset
 // CHECK-NEXT:    [[t1:%\d+]] = OpLoad %type_1d_image %t1
-// CHECK-NEXT:       {{%\d+}} = OpImageFetch %v4float [[t1]] [[coord]] Lod|Offset [[lod]] [[offset]]
-    float4 val1 = t1.Load(int2(1, 2), offset);
+// CHECK-NEXT:       {{%\d+}} = OpImageFetch %v4float [[t1]] [[coord]] Lod|ConstOffset [[lod]] %int_1
+    float4 val1 = t1.Load(int2(1, 2), 1);
 
 // CHECK:        [[loc:%\d+]] = OpLoad %v3int %location
 // CHECK-NEXT: [[coord:%\d+]] = OpVectorShuffle %v2int [[loc]] [[loc]] 0 1
@@ -46,9 +44,9 @@ float4 main(int3 location: A, int offset: B) : SV_Target {
 // CHECK-NEXT:       {{%\d+}} = OpImageFetch %v4float [[t3]] [[coord]] Lod|ConstOffset [[lod]] [[v3ic]]
     float4 val3 = t3.Load(int4(1, 2, 3, 4), 3);
 
-// CHECK:      [[f4:%\d+]] = OpImageFetch %v4float {{%\d+}} {{%\d+}} Lod|Offset {{%\d+}} {{%\d+}}
+// CHECK:      [[f4:%\d+]] = OpImageFetch %v4float {{%\d+}} {{%\d+}} Lod|ConstOffset {{%\d+}} %int_1
 // CHECK-NEXT:    {{%\d+}} = OpCompositeExtract %float [[f4]] 0
-    float val4 = t4.Load(int2(1,2), offset);
+    float val4 = t4.Load(int2(1,2), 1);
 
 // CHECK:      [[f5:%\d+]] = OpImageFetch %v4int {{%\d+}} {{%\d+}} Lod|ConstOffset {{%\d+}} {{%\d+}}
 // CHECK-NEXT:    {{%\d+}} = OpVectorShuffle %v2int [[f5]] [[f5]] 0 1
@@ -74,11 +72,10 @@ float4 main(int3 location: A, int offset: B) : SV_Target {
 
 // CHECK:        [[pos1:%\d+]] = OpLoad %v2int %pos2
 // CHECK-NEXT:    [[si1:%\d+]] = OpLoad %int %sampleIndex
-// CHECK-NEXT:[[offset2:%\d+]] = OpLoad %v2int %offset2
 // CHECK-NEXT:    [[t71:%\d+]] = OpLoad %type_2d_image_1 %t7
-// CHECK-NEXT:    [[f71:%\d+]] = OpImageFetch %v4float [[t71]] [[pos1]] Offset|Sample [[offset2]] [[si1]]
+// CHECK-NEXT:    [[f71:%\d+]] = OpImageFetch %v4float [[t71]] [[pos1]] ConstOffset|Sample [[v2ic]] [[si1]]
 // CHECK-NEXT:        {{%\d+}} = OpCompositeExtract %float [[f71]] 0
-    val7 = t7.Load(pos2, sampleIndex, offset2);
+    val7 = t7.Load(pos2, sampleIndex, int2(1, 2));
 
 // CHECK:     [[pos2:%\d+]] = OpLoad %v3int %pos3
 // CHECK-NEXT: [[si2:%\d+]] = OpLoad %int %sampleIndex
@@ -100,15 +97,14 @@ float4 main(int3 location: A, int offset: B) : SV_Target {
 
 // CHECK:            [[coord:%\d+]] = OpCompositeExtract %int [[v2ic]] 0
 // CHECK-NEXT:         [[lod:%\d+]] = OpCompositeExtract %int [[v2ic]] 1
-// CHECK-NEXT:      [[offset:%\d+]] = OpLoad %int %offset
 // CHECK-NEXT:          [[t4:%\d+]] = OpLoad %type_1d_image %t4
-// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t4]] [[coord]] Lod|Offset [[lod]] [[offset]]
+// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t4]] [[coord]] Lod|ConstOffset [[lod]] %int_1
 // CHECK-NEXT:      [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                        OpStore %status [[status]]
 // CHECK-NEXT:    [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:      [[result:%\d+]] = OpCompositeExtract %float [[v4result]] 0
 // CHECK-NEXT:                        OpStore %val14 [[result]]
-    float  val14 = t4.Load(int2(1,2), offset, status);
+    float  val14 = t4.Load(int2(1,2), 1, status);
 
 // CHECK:              [[loc:%\d+]] = OpLoad %v3int %location
 // CHECK-NEXT:       [[coord:%\d+]] = OpVectorShuffle %v2int [[loc]] [[loc]] 0 1
@@ -135,15 +131,14 @@ float4 main(int3 location: A, int offset: B) : SV_Target {
 
 // CHECK:             [[pos1:%\d+]] = OpLoad %v2int %pos2
 // CHECK-NEXT:         [[si1:%\d+]] = OpLoad %int %sampleIndex
-// CHECK-NEXT:     [[offset2:%\d+]] = OpLoad %v2int %offset2
 // CHECK-NEXT:         [[t71:%\d+]] = OpLoad %type_2d_image_1 %t7
-// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t71]] [[pos1]] Offset|Sample [[offset2]] [[si1]]
+// CHECK-NEXT:[[structResult:%\d+]] = OpImageSparseFetch %SparseResidencyStruct [[t71]] [[pos1]] ConstOffset|Sample [[v2ic]] [[si1]]
 // CHECK-NEXT:      [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                        OpStore %status [[status]]
 // CHECK-NEXT:    [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:      [[result:%\d+]] = OpCompositeExtract %float [[v4result]] 0
 // CHECK-NEXT:                        OpStore %val17 [[result]]
-    float  val17 = t7.Load(pos2, sampleIndex, offset2, status);
+    float  val17 = t7.Load(pos2, sampleIndex, int2(1,2), status);
 
 // CHECK:             [[pos3:%\d+]] = OpLoad %v3int %pos3
 // CHECK-NEXT:         [[si3:%\d+]] = OpLoad %int %sampleIndex

+ 9 - 12
tools/clang/test/CodeGenSPIRV/texture.sample-bias.hlsl

@@ -11,13 +11,13 @@ TextureCube <float4> t4 : register(t4);
 Texture1D   <float>  t5 : register(t5);
 Texture3D   <float2> t6 : register(t6);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability MinLod
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_2
 // CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_2 %int_2
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_3
+// CHECK: [[v3ic:%\d+]] = OpConstantComposite %v3int %int_1 %int_1 %int_1
 
 // CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image
 // CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image
@@ -40,10 +40,9 @@ float4 main(int3 offset: A) : SV_Target {
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v3int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|Offset %float_0_5 [[offset]]
-    float4 val3 = t3.SampleBias(gSampler, float3(1, 2, 3), 0.5, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|ConstOffset %float_0_5 [[v3ic]]
+    float4 val3 = t3.SampleBias(gSampler, float3(1, 2, 3), 0.5, 1);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -55,10 +54,9 @@ float4 main(int3 offset: A) : SV_Target {
 // CHECK:           [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:         [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v3int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|Offset|MinLod %float_0_5 [[offset]] [[clamp]]
-    float4 val5 = t3.SampleBias(gSampler, float3(1, 2, 3), 0.5, offset, clamp);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v3fc]] Bias|ConstOffset|MinLod %float_0_5 [[v3ic]] [[clamp]]
+    float4 val5 = t3.SampleBias(gSampler, float3(1, 2, 3), 0.5, 1, clamp);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -70,14 +68,13 @@ float4 main(int3 offset: A) : SV_Target {
 // CHECK:             [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:           [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v3int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] Bias|Offset|MinLod %float_0_5 [[offset]] [[clamp]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] Bias|ConstOffset|MinLod %float_0_5 [[v3ic]] [[clamp]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val7 [[result]]
-    float4 val7 = t3.SampleBias(gSampler, float3(1, 2, 3), 0.5, offset, clamp, status);
+    float4 val7 = t3.SampleBias(gSampler, float3(1, 2, 3), 0.5, 1, clamp, status);
 
 // CHECK:                [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -98,10 +95,10 @@ float4 main(int3 offset: A) : SV_Target {
 // CHECK:           {{%\d+}} = OpCompositeExtract %float [[v4result]] 0
     float val9 = t5.SampleBias(gSampler, 1, 0.5);
 
-// CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Bias|Offset|MinLod %float_0_5 {{%\d+}} {{%\d+}}
+// CHECK: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Bias|ConstOffset|MinLod %float_0_5 {{%\d+}} {{%\d+}}
 // CHECK:     [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK:              {{%\d+}} = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1
-    float2 val10 = t6.SampleBias(gSampler, float3(1, 2, 3), 0.5, offset, clamp, status);
+    float2 val10 = t6.SampleBias(gSampler, float3(1, 2, 3), 0.5, 1, clamp, status);
 
     return 1.0;
 }

+ 5 - 6
tools/clang/test/CodeGenSPIRV/texture.sample-cmp-level-zero.hlsl

@@ -10,6 +10,7 @@ TextureCube <float>  t4 : register(t4);
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_2
+// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_3
 
 // CHECK: %SparseResidencyStruct = OpTypeStruct %uint %float
@@ -25,10 +26,9 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefExplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] Lod|Offset %float_0 [[offset]]
-    float val2 = t2.SampleCmpLevelZero(gSampler, float2(1, 2), comparator, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefExplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] Lod|ConstOffset %float_0 [[v2ic]]
+    float val2 = t2.SampleCmpLevelZero(gSampler, float2(1, 2), comparator, 1);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -41,14 +41,13 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK:                [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT:   [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefExplicitLod %SparseResidencyStruct [[sampledImg]] [[v2fc]] [[comparator]] Lod|Offset %float_0 [[offset]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefExplicitLod %SparseResidencyStruct [[sampledImg]] [[v2fc]] [[comparator]] Lod|ConstOffset %float_0 [[v2ic]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val5 [[result]]
-    float val5 = t2.SampleCmpLevelZero(gSampler, float2(1, 2), comparator, offset, status);
+    float val5 = t2.SampleCmpLevelZero(gSampler, float2(1, 2), comparator, 1, status);
 
 // CHECK:                [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler

+ 7 - 9
tools/clang/test/CodeGenSPIRV/texture.sample-cmp.hlsl

@@ -11,6 +11,7 @@ TextureCube <float>  t4 : register(t4);
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_2
+// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_1 %int_1
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_3
 
 // CHECK: %SparseResidencyStruct = OpTypeStruct %uint %float
@@ -26,10 +27,9 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] Offset [[offset]]
-    float val2 = t2.SampleCmp(gSampler, float2(1, 2), comparator, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] ConstOffset [[v2ic]]
+    float val2 = t2.SampleCmp(gSampler, float2(1, 2), comparator, 1);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -43,10 +43,9 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK-NEXT:         [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT: [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] Offset|MinLod [[offset]] [[clamp]]
-    float val5 = t2.SampleCmp(gSampler, float2(1, 2), comparator, offset, clamp);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleDrefImplicitLod %float [[sampledImg]] [[v2fc]] [[comparator]] ConstOffset|MinLod [[v2ic]] [[clamp]]
+    float val5 = t2.SampleCmp(gSampler, float2(1, 2), comparator, 1, clamp);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -60,14 +59,13 @@ float4 main(int2 offset: A, float comparator: B) : SV_Target {
 // CHECK-NEXT:           [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
 // CHECK-NEXT:   [[comparator:%\d+]] = OpLoad %float %comparator
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefImplicitLod %SparseResidencyStruct [[sampledImg]] [[v2fc]] [[comparator]] Offset|MinLod [[offset]] [[clamp]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleDrefImplicitLod %SparseResidencyStruct [[sampledImg]] [[v2fc]] [[comparator]] ConstOffset|MinLod [[v2ic]] [[clamp]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val7 [[result]]
-    float val7 = t2.SampleCmp(gSampler, float2(1, 2), comparator, offset, clamp, status);
+    float val7 = t2.SampleCmp(gSampler, float2(1, 2), comparator, 1, clamp, status);
 
 // CHECK:                [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler

+ 9 - 12
tools/clang/test/CodeGenSPIRV/texture.sample-grad.hlsl

@@ -11,13 +11,13 @@ TextureCube <float4> t4 : register(t4);
 Texture1D   <float>  t5 : register(t5);
 Texture2D   <float2> t6 : register(t6);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability MinLod
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2f_1:%\d+]] = OpConstantComposite %v2float %float_1 %float_1
 // CHECK: [[v2f_2:%\d+]] = OpConstantComposite %v2float %float_2 %float_2
 // CHECK: [[v2f_3:%\d+]] = OpConstantComposite %v2float %float_3 %float_3
+// CHECK: [[v2i_3:%\d+]] = OpConstantComposite %v2int %int_3 %int_3
 // CHECK: [[v3f_1:%\d+]] = OpConstantComposite %v3float %float_1 %float_1 %float_1
 // CHECK: [[v3f_2:%\d+]] = OpConstantComposite %v3float %float_2 %float_2 %float_2
 // CHECK: [[v3f_3:%\d+]] = OpConstantComposite %v3float %float_3 %float_3 %float_3
@@ -38,10 +38,9 @@ float4 main(int2 offset : A) : SV_Target {
 
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v2f_1]] Grad|Offset [[v2f_2]] [[v2f_3]] [[offset]]
-    float4 val2 = t2.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v2f_1]] Grad|ConstOffset [[v2f_2]] [[v2f_3]] [[v2i_3]]
+    float4 val2 = t2.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), 3);
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -59,10 +58,9 @@ float4 main(int2 offset : A) : SV_Target {
 // CHECK:           [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:         [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v2f_1]] Grad|Offset|MinLod [[v2f_2]] [[v2f_3]] [[offset]] [[clamp]]
-    float4 val5 = t2.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), offset, clamp);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v2f_1]] Grad|ConstOffset|MinLod [[v2f_2]] [[v2f_3]] [[v2i_3]] [[clamp]]
+    float4 val5 = t2.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), 3, clamp);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -74,14 +72,13 @@ float4 main(int2 offset : A) : SV_Target {
 // CHECK:             [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:           [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v2f_1]] Grad|Offset|MinLod [[v2f_2]] [[v2f_3]] [[offset]] [[clamp]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v2f_1]] Grad|ConstOffset|MinLod [[v2f_2]] [[v2f_3]] [[v2i_3]] [[clamp]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val7 [[result]]
-    float4 val7 = t2.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), offset, clamp, status);
+    float4 val7 = t2.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), 3, clamp, status);
 
 // CHECK:                [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -102,10 +99,10 @@ float4 main(int2 offset : A) : SV_Target {
 // CHECK:          {{%\d+}} = OpCompositeExtract %float [[v4result]] 0
     float val9  = t5.SampleGrad(gSampler, 1, 2, 3);
 
-// CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Grad|Offset|MinLod {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}}
+// CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Grad|ConstOffset|MinLod {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}}
 // CHECK:     [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK:              {{%\d+}} = OpVectorShuffle %v2float [[v4result]] [[v4result]] 0 1
-    float2 val10 = t6.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), offset, clamp, status);
+    float2 val10 = t6.SampleGrad(gSampler, float2(1, 1), float2(2, 2), float2(3, 3), 3, clamp, status);
 
     return 1.0;
 }

+ 0 - 10
tools/clang/test/CodeGenSPIRV/texture.sample-invalid-implicit-lod.hlsl

@@ -13,26 +13,16 @@ float4 main(int2 offset: A) : SV_Position {
 // CHECK: sampling with implicit lod is only allowed in fragment shaders
     float4 val1 = t1.Sample(gSampler, 0.5);
 
-// CHECK: sampling with implicit lod is only allowed in fragment shaders
-    float4 val2 = t2.Sample(gSampler, float2(0.5, 0.25), offset);
-
 // CHECK: sampling with implicit lod is only allowed in fragment shaders
     float4 val3 = t3.Sample(gSampler, float3(0.5, 0.25, 0.3), 3);
 
 // CHECK: sampling with implicit lod is only allowed in fragment shaders
     float4 val4 = t4.Sample(gSampler, float3(0.5, 0.25, 0.3));
 
-    float clamp;
-// CHECK: sampling with implicit lod is only allowed in fragment shaders
-    float4 val5 = t2.Sample(gSampler, float2(0.5, 0.25), offset, clamp);
-
 // CHECK: sampling with implicit lod is only allowed in fragment shaders
     float4 val6 = t4.Sample(gSampler, float3(0.5, 0.25, 0.3), /*clamp*/ 2.0f);
 
     uint status;
-// CHECK: sampling with implicit lod is only allowed in fragment shaders
-    float4 val7 = t2.Sample(gSampler, float2(0.5, 0.25), offset, clamp, status);
-
 // CHECK: sampling with implicit lod is only allowed in fragment shaders
     float4 val8 = t4.Sample(gSampler, float3(0.5, 0.25, 0.3), /*clamp*/ 2.0f, status);
 

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

@@ -0,0 +1,25 @@
+// 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);
+}

+ 7 - 9
tools/clang/test/CodeGenSPIRV/texture.sample-level.hlsl

@@ -11,12 +11,12 @@ TextureCube <float4> t4 : register(t4);
 Texture3D   <float>  t5 : register(t5);
 TextureCube <float2> t6 : register(t6);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_1 %float_2
 // CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_2 %int_2
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_1 %float_2 %float_3
+// CHECK: [[v3ic:%\d+]] = OpConstantComposite %v3int %int_2 %int_2 %int_2
 
 // CHECK: %type_sampled_image = OpTypeSampledImage %type_1d_image
 // CHECK: %type_sampled_image_0 = OpTypeSampledImage %type_2d_image
@@ -39,10 +39,9 @@ float4 main(int3 offset: A) : SV_Target {
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v3int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3fc]] Lod|Offset %float_10 [[offset]]
-    float4 val3 = t3.SampleLevel(gSampler, float3(1, 2, 3), 10, offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleExplicitLod %v4float [[sampledImg]] [[v3fc]] Lod|ConstOffset %float_10 [[v3ic]]
+    float4 val3 = t3.SampleLevel(gSampler, float3(1, 2, 3), 10, 2);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -53,14 +52,13 @@ float4 main(int3 offset: A) : SV_Target {
     uint status;
 // CHECK:                [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v3int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_1 [[t3]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] Lod|Offset %float_10 [[offset]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct [[sampledImg]] [[v3fc]] Lod|ConstOffset %float_10 [[v3ic]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val5 [[result]]
-    float4 val5 = t3.SampleLevel(gSampler, float3(1, 2, 3), 10, offset, status);
+    float4 val5 = t3.SampleLevel(gSampler, float3(1, 2, 3), 10, 2, status);
 
 // CHECK:                [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -77,9 +75,9 @@ float4 main(int3 offset: A) : SV_Target {
 // Make sure OpImageSparseSampleExplicitLod returns a struct, in which the second member is a vec4.
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|Offset %float_10 {{%\d+}}
+// CHECK: [[v4result:%\d+]] = OpImageSampleExplicitLod %v4float {{%\d+}} {{%\d+}} Lod|ConstOffset %float_10 {{%\d+}}
 // CHECK:          {{%\d+}} = OpCompositeExtract %float [[v4result]] 0
-    float  val7 = t5.SampleLevel(gSampler, float3(1, 2, 3), 10, offset);
+    float  val7 = t5.SampleLevel(gSampler, float3(1, 2, 3), 10, 2);
 
 // CHECK: [[structResult:%\d+]] = OpImageSparseSampleExplicitLod %SparseResidencyStruct {{%\d+}} {{%\d+}} Lod %float_10
 // CHECK:     [[v4result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1

+ 7 - 10
tools/clang/test/CodeGenSPIRV/texture.sample.hlsl

@@ -11,11 +11,11 @@ TextureCube <float4> t4 : register(t4);
 Texture1D   <float>  t5 : register(t5);
 TextureCube <float3> t6 : register(t6);
 
-// CHECK: OpCapability ImageGatherExtended
 // CHECK: OpCapability MinLod
 // CHECK: OpCapability SparseResidency
 
 // CHECK: [[v2fc:%\d+]] = OpConstantComposite %v2float %float_0_5 %float_0_25
+// CHECK: [[v2ic:%\d+]] = OpConstantComposite %v2int %int_2 %int_3
 // CHECK: [[v3fc:%\d+]] = OpConstantComposite %v3float %float_0_5 %float_0_25 %float_0_3
 // CHECK: [[v3ic:%\d+]] = OpConstantComposite %v3int %int_3 %int_3 %int_3
 
@@ -34,10 +34,9 @@ float4 main(int2 offset: A) : SV_Target {
 
 // CHECK:              [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] Offset [[offset]]
-    float4 val2 = t2.Sample(gSampler, float2(0.5, 0.25), offset);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] ConstOffset [[v2ic]]
+    float4 val2 = t2.Sample(gSampler, float2(0.5, 0.25), int2(2, 3));
 
 // CHECK:              [[t3:%\d+]] = OpLoad %type_3d_image %t3
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -55,10 +54,9 @@ float4 main(int2 offset: A) : SV_Target {
 // CHECK:           [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:         [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:     [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT: [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] Offset|MinLod [[offset]] [[clamp]]
-    float4 val5 = t2.Sample(gSampler, float2(0.5, 0.25), offset, clamp);
+// CHECK-NEXT:            {{%\d+}} = OpImageSampleImplicitLod %v4float [[sampledImg]] [[v2fc]] ConstOffset|MinLod [[v2ic]] [[clamp]]
+    float4 val5 = t2.Sample(gSampler, float2(0.5, 0.25), int2(2, 3), clamp);
 
 // CHECK:              [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:   [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
@@ -70,14 +68,13 @@ float4 main(int2 offset: A) : SV_Target {
 // CHECK:             [[clamp:%\d+]] = OpLoad %float %clamp
 // CHECK-NEXT:           [[t2:%\d+]] = OpLoad %type_2d_image %t2
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler
-// CHECK-NEXT:       [[offset:%\d+]] = OpLoad %v2int %offset
 // CHECK-NEXT:   [[sampledImg:%\d+]] = OpSampledImage %type_sampled_image_0 [[t2]] [[gSampler]]
-// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct [[sampledImg]] [[v2fc]] Offset|MinLod [[offset]] [[clamp]]
+// CHECK-NEXT: [[structResult:%\d+]] = OpImageSparseSampleImplicitLod %SparseResidencyStruct [[sampledImg]] [[v2fc]] ConstOffset|MinLod [[v2ic]] [[clamp]]
 // CHECK-NEXT:       [[status:%\d+]] = OpCompositeExtract %uint [[structResult]] 0
 // CHECK-NEXT:                         OpStore %status [[status]]
 // CHECK-NEXT:       [[result:%\d+]] = OpCompositeExtract %v4float [[structResult]] 1
 // CHECK-NEXT:                         OpStore %val7 [[result]]
-    float4 val7 = t2.Sample(gSampler, float2(0.5, 0.25), offset, clamp, status);
+    float4 val7 = t2.Sample(gSampler, float2(0.5, 0.25), int2(2, 3), clamp, status);
 
 // CHECK:                [[t4:%\d+]] = OpLoad %type_cube_image %t4
 // CHECK-NEXT:     [[gSampler:%\d+]] = OpLoad %type_sampler %gSampler

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

@@ -865,6 +865,9 @@ 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");
 }
@@ -947,6 +950,9 @@ 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);
 }