Browse Source

[spirv] Avoid writing unused stage output variable back (#1373)

Some workflow relies on trimming off unused stage output variables.
But we created a wrapper around the source code entry function to
satisfy Vulkan's requirement over entry function signature.
Previously we just blindly write back all stage output variables
in the wrapper function no matter whether the corresponding stage
output variable is used or not in the source code entry function.
Now we can be a little bit clever based on the usedness info
from the AST.
Lei Zhang 7 years ago
parent
commit
ad55bca496
23 changed files with 91 additions and 32 deletions
  1. 9 5
      tools/clang/lib/SPIRV/DeclResultIdMapper.cpp
  2. 9 3
      tools/clang/lib/SPIRV/SPIRVEmitter.cpp
  3. 0 3
      tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv
  4. 0 3
      tools/clang/test/CodeGenSPIRV/bezier.hull.hlsl2spv
  5. 0 1
      tools/clang/test/CodeGenSPIRV/empty-struct-interface.vs.hlsl2spv
  6. 1 1
      tools/clang/test/CodeGenSPIRV/hs.pcf.primitive-id.1.hlsl
  7. 1 1
      tools/clang/test/CodeGenSPIRV/hs.pcf.view-id.1.hlsl
  8. 6 2
      tools/clang/test/CodeGenSPIRV/semantic.dispatch-thread-id.int2.cs.hlsl
  9. 6 2
      tools/clang/test/CodeGenSPIRV/semantic.dispatch-thread-id.uint.cs.hlsl
  10. 1 0
      tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl
  11. 6 2
      tools/clang/test/CodeGenSPIRV/semantic.group-id.int2.cs.hlsl
  12. 6 1
      tools/clang/test/CodeGenSPIRV/semantic.group-id.uint.cs.hlsl
  13. 6 2
      tools/clang/test/CodeGenSPIRV/semantic.group-thread-id.int2.cs.hlsl
  14. 6 2
      tools/clang/test/CodeGenSPIRV/semantic.group-thread-id.uint.cs.hlsl
  15. 1 1
      tools/clang/test/CodeGenSPIRV/semantic.inner-coverage.ps.hlsl
  16. 1 0
      tools/clang/test/CodeGenSPIRV/spirv.entry-function.inout.hlsl
  17. 23 0
      tools/clang/test/CodeGenSPIRV/spirv.entry-function.unused-param.hlsl
  18. 2 0
      tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl
  19. 1 0
      tools/clang/test/CodeGenSPIRV/spirv.interface.gs.hlsl
  20. 1 0
      tools/clang/test/CodeGenSPIRV/spirv.interface.hs.hlsl
  21. 1 1
      tools/clang/test/CodeGenSPIRV/spirv.interface.ps.hlsl
  22. 1 2
      tools/clang/test/CodeGenSPIRV/spirv.interface.vs.hlsl
  23. 3 0
      tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

+ 9 - 5
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -214,13 +214,17 @@ bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
 
 
   SemanticInfo inheritSemantic = {};
   SemanticInfo inheritSemantic = {};
 
 
+  // If storedValue is 0, it means this parameter in the original source code is
+  // not used at all. Avoid writing back.
+  //
+  // Write back of stage output variables in GS is manually controlled by
+  // .Append() intrinsic method, implemented in writeBackOutputStream(). So
+  // ignoreValue should be set to true for GS.
+  const bool noWriteBack = storedValue == 0 || shaderModel.IsGS();
+
   return createStageVars(sigPoint, decl, /*asInput=*/false, type,
   return createStageVars(sigPoint, decl, /*asInput=*/false, type,
                          /*arraySize=*/0, "out.var", llvm::None, &storedValue,
                          /*arraySize=*/0, "out.var", llvm::None, &storedValue,
-                         // Write back of stage output variables in GS is
-                         // manually controlled by .Append() intrinsic method,
-                         // implemented in writeBackOutputStream(). So
-                         // noWriteBack should be set to true for GS.
-                         shaderModel.IsGS(), &inheritSemantic);
+                         noWriteBack, &inheritSemantic);
 }
 }
 
 
 bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
 bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,

+ 9 - 3
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -5630,7 +5630,7 @@ SPIRVEmitter::tryToAssignToVectorElements(const Expr *lhs,
       const auto result = tryToAssignToRWBufferRWTexture(base, newVec);
       const auto result = tryToAssignToRWBufferRWTexture(base, newVec);
       assert(result); // Definitely RWBuffer/RWTexture assignment
       assert(result); // Definitely RWBuffer/RWTexture assignment
       (void)result;
       (void)result;
-      return rhs;     // TODO: incorrect for compound assignments
+      return rhs; // TODO: incorrect for compound assignments
     } else {
     } else {
       // Assigning to one normal vector component. Nothing special, just fall
       // Assigning to one normal vector component. Nothing special, just fall
       // back to the normal CodeGen path.
       // back to the normal CodeGen path.
@@ -9378,7 +9378,10 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
       if (!declIdMapper.createStageInputVar(param, &loadedValue, false))
       if (!declIdMapper.createStageInputVar(param, &loadedValue, false))
         return false;
         return false;
 
 
-      theBuilder.createStore(tempVar, loadedValue);
+      // Only initialize the temporary variable if the parameter is indeed used.
+      if (param->isUsed()) {
+        theBuilder.createStore(tempVar, loadedValue);
+      }
 
 
       // Record the temporary variable holding SV_OutputControlPointID,
       // Record the temporary variable holding SV_OutputControlPointID,
       // SV_PrimitiveID, and SV_ViewID. It may be used later in the patch
       // SV_PrimitiveID, and SV_ViewID. It may be used later in the patch
@@ -9427,10 +9430,13 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
       const uint32_t typeId = typeTranslator.translateType(param->getType());
       const uint32_t typeId = typeTranslator.translateType(param->getType());
       uint32_t loadedParam = 0;
       uint32_t loadedParam = 0;
 
 
+      // No need to write back the value if the parameter is not used at all in
+      // the original entry function.
+      //
       // Write back of stage output variables in GS is manually controlled by
       // Write back of stage output variables in GS is manually controlled by
       // .Append() intrinsic method. No need to load the parameter since we
       // .Append() intrinsic method. No need to load the parameter since we
       // won't need to write back here.
       // won't need to write back here.
-      if (!shaderModel.IsGS())
+      if (param->isUsed() && !shaderModel.IsGS())
         loadedParam = theBuilder.createLoad(typeId, params[i]);
         loadedParam = theBuilder.createLoad(typeId, params[i]);
 
 
       if (!declIdMapper.createStageOutputVar(param, loadedParam, false))
       if (!declIdMapper.createStageOutputVar(param, loadedParam, false))

+ 0 - 3
tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv

@@ -167,10 +167,8 @@ DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input,
 // %35 = OpLoad %_arr_v3float_uint_4 %in_var_TANVCORNER
 // %35 = OpLoad %_arr_v3float_uint_4 %in_var_TANVCORNER
 // %38 = OpLoad %v4float %in_var_TANWEIGHTS
 // %38 = OpLoad %v4float %in_var_TANWEIGHTS
 // %39 = OpCompositeConstruct %HS_CONSTANT_DATA_OUTPUT %22 %25 %28 %31 %33 %35 %38
 // %39 = OpCompositeConstruct %HS_CONSTANT_DATA_OUTPUT %22 %25 %28 %31 %33 %35 %38
-// OpStore %param_var_input %39
 // %44 = OpLoad %v3float %gl_TessCoord
 // %44 = OpLoad %v3float %gl_TessCoord
 // %45 = OpVectorShuffle %v2float %44 %44 0 1
 // %45 = OpVectorShuffle %v2float %44 %44 0 1
-// OpStore %param_var_UV %45
 // %51 = OpLoad %_arr_v3float_uint_4 %in_var_BEZIERPOS
 // %51 = OpLoad %_arr_v3float_uint_4 %in_var_BEZIERPOS
 // %52 = OpCompositeExtract %v3float %51 0
 // %52 = OpCompositeExtract %v3float %51 0
 // %53 = OpCompositeConstruct %BEZIER_CONTROL_POINT %52
 // %53 = OpCompositeConstruct %BEZIER_CONTROL_POINT %52
@@ -181,7 +179,6 @@ DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input,
 // %58 = OpCompositeExtract %v3float %51 3
 // %58 = OpCompositeExtract %v3float %51 3
 // %59 = OpCompositeConstruct %BEZIER_CONTROL_POINT %58
 // %59 = OpCompositeConstruct %BEZIER_CONTROL_POINT %58
 // %60 = OpCompositeConstruct %_arr_BEZIER_CONTROL_POINT_uint_4 %53 %55 %57 %59
 // %60 = OpCompositeConstruct %_arr_BEZIER_CONTROL_POINT_uint_4 %53 %55 %57 %59
-// OpStore %param_var_bezpatch %60
 // %62 = OpFunctionCall %DS_OUTPUT %src_BezierEvalDS %param_var_input %param_var_UV %param_var_bezpatch
 // %62 = OpFunctionCall %DS_OUTPUT %src_BezierEvalDS %param_var_input %param_var_UV %param_var_bezpatch
 // %63 = OpCompositeExtract %v3float %62 0
 // %63 = OpCompositeExtract %v3float %62 0
 // OpStore %out_var_NORMAL %63
 // OpStore %out_var_NORMAL %63

+ 0 - 3
tools/clang/test/CodeGenSPIRV/bezier.hull.hlsl2spv

@@ -212,11 +212,8 @@ BEZIER_CONTROL_POINT SubDToBezierHS(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POIN
 // %35 = OpCompositeExtract %v3float %24 2
 // %35 = OpCompositeExtract %v3float %24 2
 // %36 = OpCompositeConstruct %VS_CONTROL_POINT_OUTPUT %33 %34 %35
 // %36 = OpCompositeConstruct %VS_CONTROL_POINT_OUTPUT %33 %34 %35
 // %37 = OpCompositeConstruct %_arr_VS_CONTROL_POINT_OUTPUT_uint_3 %28 %32 %36
 // %37 = OpCompositeConstruct %_arr_VS_CONTROL_POINT_OUTPUT_uint_3 %28 %32 %36
-// OpStore %param_var_ip %37
 // %42 = OpLoad %uint %gl_InvocationID
 // %42 = OpLoad %uint %gl_InvocationID
-// OpStore %param_var_cpid %42
 // %45 = OpLoad %uint %gl_PrimitiveID
 // %45 = OpLoad %uint %gl_PrimitiveID
-// OpStore %param_var_PatchID %45
 // %47 = OpFunctionCall %BEZIER_CONTROL_POINT %src_SubDToBezierHS %param_var_ip %param_var_cpid %param_var_PatchID
 // %47 = OpFunctionCall %BEZIER_CONTROL_POINT %src_SubDToBezierHS %param_var_ip %param_var_cpid %param_var_PatchID
 // %48 = OpCompositeExtract %v3float %47 0
 // %48 = OpCompositeExtract %v3float %47 0
 // %52 = OpAccessChain %_ptr_Output_v3float %out_var_BEZIERPOS %42
 // %52 = OpAccessChain %_ptr_Output_v3float %out_var_BEZIERPOS %42

+ 0 - 1
tools/clang/test/CodeGenSPIRV/empty-struct-interface.vs.hlsl2spv

@@ -36,7 +36,6 @@ VSOut main(VSIn input)
 // %5 = OpLabel
 // %5 = OpLabel
 // %param_var_input = OpVariable %_ptr_Function_VSIn Function
 // %param_var_input = OpVariable %_ptr_Function_VSIn Function
 // %9 = OpCompositeConstruct %VSIn
 // %9 = OpCompositeConstruct %VSIn
-// OpStore %param_var_input %9
 // %11 = OpFunctionCall %VSOut %src_main %param_var_input
 // %11 = OpFunctionCall %VSOut %src_main %param_var_input
 // OpReturn
 // OpReturn
 // OpFunctionEnd
 // OpFunctionEnd

+ 1 - 1
tools/clang/test/CodeGenSPIRV/hs.pcf.primitive-id.1.hlsl

@@ -45,6 +45,6 @@ HS_CONSTANT_DATA_OUTPUT PCF(uint PatchID : SV_PrimitiveID) {
 BEZIER_CONTROL_POINT main(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID) {
 BEZIER_CONTROL_POINT main(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID) {
   VS_CONTROL_POINT_OUTPUT vsOutput;
   VS_CONTROL_POINT_OUTPUT vsOutput;
   BEZIER_CONTROL_POINT result;
   BEZIER_CONTROL_POINT result;
-  result.vPosition = vsOutput.vPosition;
+  result.vPosition = vsOutput.vPosition + PatchID;
   return result;
   return result;
 }
 }

+ 1 - 1
tools/clang/test/CodeGenSPIRV/hs.pcf.view-id.1.hlsl

@@ -44,7 +44,7 @@ HsCpOut main(InputPatch<HsCpIn, NumOutPoints> patch,
              uint id : SV_OutputControlPointID,
              uint id : SV_OutputControlPointID,
              uint viewid : SV_ViewID) {
              uint viewid : SV_ViewID) {
     HsCpOut output;
     HsCpOut output;
-    output = (HsCpOut)0;
+    output.bar = viewid;
     return output;
     return output;
 // CHECK:             %main = OpFunction %void None {{%\d+}}
 // CHECK:             %main = OpFunction %void None {{%\d+}}
 // CHECK: %param_var_viewid = OpVariable %_ptr_Function_uint Function
 // CHECK: %param_var_viewid = OpVariable %_ptr_Function_uint Function

+ 6 - 2
tools/clang/test/CodeGenSPIRV/semantic.dispatch-thread-id.int2.cs.hlsl

@@ -9,5 +9,9 @@
 // CHECK:  [[int2_DispatchThreadID:%\d+]] = OpVectorShuffle %v2int [[gl_GlobalInvocationID]] [[gl_GlobalInvocationID]] 0 1
 // CHECK:  [[int2_DispatchThreadID:%\d+]] = OpVectorShuffle %v2int [[gl_GlobalInvocationID]] [[gl_GlobalInvocationID]] 0 1
 // CHECK:                                   OpStore %param_var_tid [[int2_DispatchThreadID]]
 // CHECK:                                   OpStore %param_var_tid [[int2_DispatchThreadID]]
 
 
-[numthreads(8, 8, 8)]
-void main(int2 tid : SV_DispatchThreadId) {}
+RWBuffer<int2> MyBuffer;
+
+[numthreads(1, 1, 1)]
+void main(int2 tid : SV_DispatchThreadId) {
+    MyBuffer[0] = tid;
+}

+ 6 - 2
tools/clang/test/CodeGenSPIRV/semantic.dispatch-thread-id.uint.cs.hlsl

@@ -8,5 +8,9 @@
 // CHECK: [[uint_DispatchThreadID:%\d+]] = OpCompositeExtract %uint [[gl_GlobalInvocationID]] 0
 // CHECK: [[uint_DispatchThreadID:%\d+]] = OpCompositeExtract %uint [[gl_GlobalInvocationID]] 0
 // CHECK:                                  OpStore %param_var_tid [[uint_DispatchThreadID]]
 // CHECK:                                  OpStore %param_var_tid [[uint_DispatchThreadID]]
 
 
-[numthreads(8, 8, 8)]
-void main(uint tid : SV_DispatchThreadId) {}
+RWBuffer<uint> MyBuffer;
+
+[numthreads(1, 1, 1)]
+void main(uint tid : SV_DispatchThreadId) {
+    MyBuffer[0] = tid;
+}

+ 1 - 0
tools/clang/test/CodeGenSPIRV/semantic.domain-location.ds.hlsl

@@ -42,5 +42,6 @@ DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input,
                         const OutputPatch<BEZIER_CONTROL_POINT, 16> bezpatch )
                         const OutputPatch<BEZIER_CONTROL_POINT, 16> bezpatch )
 {
 {
   DS_OUTPUT Output;
   DS_OUTPUT Output;
+  Output.vPosition = float4(UV, UV);
   return Output;
   return Output;
 }
 }

+ 6 - 2
tools/clang/test/CodeGenSPIRV/semantic.group-id.int2.cs.hlsl

@@ -9,5 +9,9 @@
 // CHECK:  [[int2_GroupID:%\d+]] = OpVectorShuffle %v2int [[gl_WorkGrouID]] [[gl_WorkGrouID]] 0 1
 // CHECK:  [[int2_GroupID:%\d+]] = OpVectorShuffle %v2int [[gl_WorkGrouID]] [[gl_WorkGrouID]] 0 1
 // CHECK:                          OpStore %param_var_tid [[int2_GroupID]]
 // CHECK:                          OpStore %param_var_tid [[int2_GroupID]]
 
 
-[numthreads(8, 8, 8)]
-void main(int2 tid : SV_GroupID) {}
+RWBuffer<int2> MyBuffer;
+
+[numthreads(1, 1, 1)]
+void main(int2 tid : SV_GroupID) {
+    MyBuffer[0] = tid;
+}

+ 6 - 1
tools/clang/test/CodeGenSPIRV/semantic.group-id.uint.cs.hlsl

@@ -7,5 +7,10 @@
 // CHECK: [[gl_WorkGroupID:%\d+]] = OpLoad %v3uint %gl_WorkGroupID
 // CHECK: [[gl_WorkGroupID:%\d+]] = OpLoad %v3uint %gl_WorkGroupID
 // CHECK:   [[uint_GroupID:%\d+]] = OpCompositeExtract %uint [[gl_WorkGroupID]] 0
 // CHECK:   [[uint_GroupID:%\d+]] = OpCompositeExtract %uint [[gl_WorkGroupID]] 0
 // CHECK:                           OpStore %param_var_tid [[uint_GroupID]]
 // CHECK:                           OpStore %param_var_tid [[uint_GroupID]]
+
+RWBuffer<uint> MyBuffer;
+
 [numthreads(8, 8, 8)]
 [numthreads(8, 8, 8)]
-void main(uint tid : SV_GroupID) {}
+void main(uint tid : SV_GroupID) {
+    MyBuffer[0] = tid;
+}

+ 6 - 2
tools/clang/test/CodeGenSPIRV/semantic.group-thread-id.int2.cs.hlsl

@@ -9,5 +9,9 @@
 // CHECK:   [[int2_GroupThreadID:%\d+]] = OpVectorShuffle %v2int [[gl_LocalInvocationID]] [[gl_LocalInvocationID]] 0 1
 // CHECK:   [[int2_GroupThreadID:%\d+]] = OpVectorShuffle %v2int [[gl_LocalInvocationID]] [[gl_LocalInvocationID]] 0 1
 // CHECK:                                 OpStore %param_var_gtid [[int2_GroupThreadID]]
 // CHECK:                                 OpStore %param_var_gtid [[int2_GroupThreadID]]
 
 
-[numthreads(8, 8, 8)]
-void main(int2 gtid : SV_GroupThreadID) {}
+RWBuffer<int2> MyBuffer;
+
+[numthreads(1, 1, 1)]
+void main(int2 gtid : SV_GroupThreadID) {
+    MyBuffer[0] = gtid;
+}

+ 6 - 2
tools/clang/test/CodeGenSPIRV/semantic.group-thread-id.uint.cs.hlsl

@@ -8,5 +8,9 @@
 // CHECK:   [[uint_GroupThreadID:%\d+]] = OpCompositeExtract %uint [[gl_LocalInvocationID]] 0
 // CHECK:   [[uint_GroupThreadID:%\d+]] = OpCompositeExtract %uint [[gl_LocalInvocationID]] 0
 // CHECK:                                 OpStore %param_var_gtid [[uint_GroupThreadID]]
 // CHECK:                                 OpStore %param_var_gtid [[uint_GroupThreadID]]
 
 
-[numthreads(8, 8, 8)]
-void main(uint gtid : SV_GroupThreadID) {}
+RWBuffer<uint> MyBuffer;
+
+[numthreads(1, 1, 1)]
+void main(uint gtid : SV_GroupThreadID) {
+    MyBuffer[0] = gtid;
+}

+ 1 - 1
tools/clang/test/CodeGenSPIRV/semantic.inner-coverage.ps.hlsl

@@ -12,5 +12,5 @@ float4 main(uint inCov : SV_InnerCoverage) : SV_Target {
 // CHECK:      [[boolv:%\d+]] = OpLoad %bool [[coverage]]
 // CHECK:      [[boolv:%\d+]] = OpLoad %bool [[coverage]]
 // CHECK-NEXT:  [[intv:%\d+]] = OpSelect %uint [[boolv]] %uint_1 %uint_0
 // CHECK-NEXT:  [[intv:%\d+]] = OpSelect %uint [[boolv]] %uint_1 %uint_0
 // CHECK-NEXT:                  OpStore %param_var_inCov [[intv]]
 // CHECK-NEXT:                  OpStore %param_var_inCov [[intv]]
-    return 1.0;
+    return inCov;
 }
 }

+ 1 - 0
tools/clang/test/CodeGenSPIRV/spirv.entry-function.inout.hlsl

@@ -95,6 +95,7 @@ void main(in      int4  param1: O,
     param3 = param1;
     param3 = param1;
 
 
     param5 = param4;
     param5 = param4;
+    param5.b = param7 + param8.e;
     param6.c = param4.a;
     param6.c = param4.a;
     param6.d = param4.b;
     param6.d = param4.b;
 }
 }

+ 23 - 0
tools/clang/test/CodeGenSPIRV/spirv.entry-function.unused-param.hlsl

@@ -0,0 +1,23 @@
+// Run: %dxc -T vs_6_0 -E main
+
+void main (
+// CHECK:  %in_var_A = OpVariable %_ptr_Input_v3float Input
+    in  float3 used_in_var    : A,
+// CHECK:  %in_var_B = OpVariable %_ptr_Input_v3float Input
+    in  float3 unused_in_var  : B,
+// CHECK: %out_var_C = OpVariable %_ptr_Output_v3float Output
+    out float3 used_out_var   : C,
+// CHECK: %out_var_D = OpVariable %_ptr_Output_v3float Output
+    out float3 unused_out_var : D
+) {
+// CHECK:      [[a:%\d+]] = OpLoad %v3float %in_var_A
+// CHECK-NEXT:              OpStore %param_var_used_in_var [[a]]
+// No writing to %param_var_unused_in_var
+// CHECK-NEXT:   {{%\d+}} = OpLoad %v3float %in_var_B
+// CHECK-NEXT:   {{%\d+}} = OpFunctionCall %void %src_main %param_var_used_in_var %param_var_unused_in_var %param_var_used_out_var %param_var_unused_out_var
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %param_var_used_out_var
+// CHECK-NEXT:              OpStore %out_var_C [[c]]
+// No writing to %out_var_D
+// CHECK-NEXT:              OpReturn
+    used_out_var = used_in_var;
+}

+ 2 - 0
tools/clang/test/CodeGenSPIRV/spirv.interface.ds.hlsl

@@ -140,6 +140,8 @@ DsOut main(    const OutputPatch<PerVertexIn, 3> patch,
 {
 {
   DsOut dsOut;
   DsOut dsOut;
   dsOut = (DsOut)0;
   dsOut = (DsOut)0;
+  dsOut.pos = patch[0].ptSize;
+  clip5 = pcfData.foo + float3(loc, 1);
   return dsOut;
   return dsOut;
 // Layout of input ClipDistance array:
 // Layout of input ClipDistance array:
 //   clip0: 1 floats, offset 0
 //   clip0: 1 floats, offset 0

+ 1 - 0
tools/clang/test/CodeGenSPIRV/spirv.interface.gs.hlsl

@@ -105,6 +105,7 @@ void main(in    line float2                     bar   [2] : BAR,
     GsPerVertexOut vertex;
     GsPerVertexOut vertex;
 
 
     vertex = (GsPerVertexOut)0;
     vertex = (GsPerVertexOut)0;
+    vertex.bar = float4(bar[0], bar[1]) + inData[0].pos;
 
 
     outData.Append(vertex);
     outData.Append(vertex);
 
 

+ 1 - 0
tools/clang/test/CodeGenSPIRV/spirv.interface.hs.hlsl

@@ -167,6 +167,7 @@ HsPcfOut pcf(InputPatch<HsCpIn, NumOutPoints> patch, uint patchId : SV_Primitive
 HsCpOut main(InputPatch<HsCpIn, NumOutPoints> patch, uint cpId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID) {
 HsCpOut main(InputPatch<HsCpIn, NumOutPoints> patch, uint cpId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID) {
     HsCpOut output;
     HsCpOut output;
     output = (HsCpOut)0;
     output = (HsCpOut)0;
+    output.clip7 = patch[0].pos.x + cpId + patchId;
     return output;
     return output;
 
 
 // Read gl_Postion for HsCpIn::pos
 // Read gl_Postion for HsCpIn::pos

+ 1 - 1
tools/clang/test/CodeGenSPIRV/spirv.interface.ps.hlsl

@@ -45,7 +45,7 @@ float4 main(   PsIn   psIn,
                float3 cull1 : SV_CullDistance1, // Builtin CullDistance
                float3 cull1 : SV_CullDistance1, // Builtin CullDistance
             in float  bar   : BAR               // Input variable
             in float  bar   : BAR               // Input variable
            ) : SV_Target {                      // Output variable
            ) : SV_Target {                      // Output variable
-    return 1.0;
+    return psIn.pos + float4(clip1 + bar, cull1);
 // Layout of input ClipDistance array:
 // Layout of input ClipDistance array:
 //   clip0: 2 floats, offset 0
 //   clip0: 2 floats, offset 0
 //   clip1: 1 floats, offset 2
 //   clip1: 1 floats, offset 2

+ 1 - 2
tools/clang/test/CodeGenSPIRV/spirv.interface.vs.hlsl

@@ -83,9 +83,8 @@ float main(out VSOut  vsOut,
     culldis5 = 3.;
     culldis5 = 3.;
     culldis3 = 4.;
     culldis3 = 4.;
     culldis6 = 5.;
     culldis6 = 5.;
-    inPos    = 6.;
 
 
-    return 7.;
+    return inPos.x + inClip.x + inCull.x;
 
 
 // Layout of ClipDistance array:
 // Layout of ClipDistance array:
 //   clipdis0: 3 floats, offset 0
 //   clipdis0: 3 floats, offset 0

+ 3 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -1188,6 +1188,9 @@ TEST_F(FileTest, SpirvEntryFunctionWrapper) {
 TEST_F(FileTest, SpirvEntryFunctionInOut) {
 TEST_F(FileTest, SpirvEntryFunctionInOut) {
   runFileTest("spirv.entry-function.inout.hlsl");
   runFileTest("spirv.entry-function.inout.hlsl");
 }
 }
+TEST_F(FileTest, SpirvEntryFunctionUnusedParameter) {
+  runFileTest("spirv.entry-function.unused-param.hlsl");
+}
 
 
 TEST_F(FileTest, SpirvBuiltInHelperInvocation) {
 TEST_F(FileTest, SpirvBuiltInHelperInvocation) {
   runFileTest("spirv.builtin.helper-invocation.hlsl");
   runFileTest("spirv.builtin.helper-invocation.hlsl");