Browse Source

[spirv] -fvk-invert-w in non-PS stages is no-op (#1441)

Allow using -fvk-invert-w in non-PS stages and make it a no-op.
Lei Zhang 7 years ago
parent
commit
dbc67dc4f4

+ 1 - 1
docs/SPIR-V.rst

@@ -2722,7 +2722,7 @@ codegen for Vulkan:
 - ``-fvk-invert-w``: Reciprocates (multiplicatively inverts) SV_Position.w after
 - ``-fvk-invert-w``: Reciprocates (multiplicatively inverts) SV_Position.w after
   reading from stage input. Used to accommodate the difference between Vulkan
   reading from stage input. Used to accommodate the difference between Vulkan
   DirectX: the w component of SV_Position in PS is stored as 1/w in Vulkan.
   DirectX: the w component of SV_Position in PS is stored as 1/w in Vulkan.
-  Only allowed in PS.
+  Only recognized in PS; applying to other stages is no-op.
 - ``-fvk-stage-io-order={alpha|decl}``: Assigns the stage input/output variable
 - ``-fvk-stage-io-order={alpha|decl}``: Assigns the stage input/output variable
   location number according to alphabetical order or declaration order. See
   location number according to alphabetical order or declaration order. See
   `HLSL semantic and Vulkan Location`_ for more details.
   `HLSL semantic and Vulkan Location`_ for more details.

+ 1 - 1
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -1796,7 +1796,7 @@ uint32_t DeclResultIdMapper::invertYIfRequested(uint32_t position) {
 
 
 uint32_t DeclResultIdMapper::invertWIfRequested(uint32_t position) {
 uint32_t DeclResultIdMapper::invertWIfRequested(uint32_t position) {
   // Reciprocate SV_Position.w if requested
   // Reciprocate SV_Position.w if requested
-  if (spirvOptions.invertW) {
+  if (spirvOptions.invertW && shaderModel.IsPS()) {
     const auto f32Type = theBuilder.getFloat32Type();
     const auto f32Type = theBuilder.getFloat32Type();
     const auto v4f32Type = theBuilder.getVecType(f32Type, 4);
     const auto v4f32Type = theBuilder.getVecType(f32Type, 4);
     const auto oldW = theBuilder.createCompositeExtract(f32Type, position, {3});
     const auto oldW = theBuilder.createCompositeExtract(f32Type, position, {3});

+ 0 - 2
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -597,8 +597,6 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci, EmitSPIRVOptions &options)
   if (options.invertY && !shaderModel.IsVS() && !shaderModel.IsDS() &&
   if (options.invertY && !shaderModel.IsVS() && !shaderModel.IsDS() &&
       !shaderModel.IsGS())
       !shaderModel.IsGS())
     emitError("-fvk-invert-y can only be used in VS/DS/GS", {});
     emitError("-fvk-invert-y can only be used in VS/DS/GS", {});
-  if (options.invertW && !shaderModel.IsPS())
-    emitError("-fvk-invert-w can only be used in PS", {});
 
 
   if (options.useGlLayout && options.useDxLayout)
   if (options.useGlLayout && options.useDxLayout)
     emitError("cannot specify both -fvk-use-dx-layout and -fvk-use-gl-layout",
     emitError("cannot specify both -fvk-use-dx-layout and -fvk-use-gl-layout",

+ 29 - 0
tools/clang/test/CodeGenSPIRV/vk.cloption.invert-w.ds.hlsl

@@ -0,0 +1,29 @@
+// Run: %dxc -T ds_6_0 -E main -fvk-invert-w
+
+// HS PCF output
+struct HsPcfOut {
+  float  outTessFactor[4]   : SV_TessFactor;
+  float  inTessFactor[2]    : SV_InsideTessFactor;
+};
+
+// Per-vertex input structs
+struct DsCpIn {
+    float4 pos : SV_Position;
+};
+
+// Per-vertex output structs
+struct DsCpOut {
+    float4 pos : SV_Position;
+};
+
+[domain("quad")]
+DsCpOut main(OutputPatch<DsCpIn, 3> patch,
+             HsPcfOut pcfData) {
+  DsCpOut dsOut;
+  dsOut = (DsCpOut)0;
+  return dsOut;
+}
+
+// Make sure -fvk-invert-w is ignored for non-PS stages
+// CHECK:     OpLoad %_arr_v4float_uint_3 %gl_Position
+// CHECK-NOT: OpCompositeInsert %v4float {{%\d+}} {{%\d+}} 3

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

@@ -1332,6 +1332,9 @@ TEST_F(FileTest, VulkanCLOptionInvertYGS) {
   runFileTest("vk.cloption.invert-y.gs.hlsl");
   runFileTest("vk.cloption.invert-y.gs.hlsl");
 }
 }
 
 
+TEST_F(FileTest, VulkanCLOptionInvertWDS) {
+  runFileTest("vk.cloption.invert-w.ds.hlsl");
+}
 TEST_F(FileTest, VulkanCLOptionInvertWPS) {
 TEST_F(FileTest, VulkanCLOptionInvertWPS) {
   runFileTest("vk.cloption.invert-w.ps.hlsl");
   runFileTest("vk.cloption.invert-w.ps.hlsl");
 }
 }