summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/visual-studio/slang/slang.vcxproj2
-rw-r--r--build/visual-studio/slang/slang.vcxproj.filters6
-rw-r--r--docs/command-line-slangc-reference.md5
-rw-r--r--source/slang/slang-emit.cpp3
-rw-r--r--source/slang/slang-hlsl-to-vulkan-layout-options.cpp2
-rw-r--r--source/slang/slang-hlsl-to-vulkan-layout-options.h8
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp24
-rw-r--r--source/slang/slang-ir-inst-defs.h3
-rw-r--r--source/slang/slang-ir-insts.h10
-rw-r--r--source/slang/slang-ir-vk-invert-y.cpp59
-rw-r--r--source/slang/slang-ir-vk-invert-y.h10
-rw-r--r--source/slang/slang-options.cpp8
-rw-r--r--tests/cross-compile/vk-invert-y.slang21
13 files changed, 160 insertions, 1 deletions
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj
index 310fb6f64..74d008c9e 100644
--- a/build/visual-studio/slang/slang.vcxproj
+++ b/build/visual-studio/slang/slang.vcxproj
@@ -458,6 +458,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla
<ClInclude Include="..\..\..\source\slang\slang-ir-use-uninitialized-out-param.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-util.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-validate.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-ir-vk-invert-y.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-witness-table-wrapper.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-wrap-structured-buffers.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir.h" />
@@ -661,6 +662,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla
<ClCompile Include="..\..\..\source\slang\slang-ir-use-uninitialized-out-param.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-util.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-validate.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-ir-vk-invert-y.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-witness-table-wrapper.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-wrap-structured-buffers.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters
index edb561c1c..c2689b17d 100644
--- a/build/visual-studio/slang/slang.vcxproj.filters
+++ b/build/visual-studio/slang/slang.vcxproj.filters
@@ -462,6 +462,9 @@
<ClInclude Include="..\..\..\source\slang\slang-ir-validate.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-ir-vk-invert-y.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-ir-witness-table-wrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -1067,6 +1070,9 @@
<ClCompile Include="..\..\..\source\slang\slang-ir-validate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-ir-vk-invert-y.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ir-witness-table-wrapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/docs/command-line-slangc-reference.md b/docs/command-line-slangc-reference.md
index a1387df5f..8bd15bbee 100644
--- a/docs/command-line-slangc-reference.md
+++ b/docs/command-line-slangc-reference.md
@@ -374,6 +374,11 @@ For example '-fvk-b-shift &lt;N&gt; &lt;space&gt;' shifts by N the inferred bind
Places the $Globals cbuffer at descriptor set &lt;descriptor-set&gt; and binding &lt;N&gt;.
+<a id="fvk-invert-y"></a>
+## -fvk-invert-y
+Negates (additively inverts) SV_Position.y before writing to stage output.
+
+
<a id="enable-effect-annotations"></a>
## -enable-effect-annotations
Enables support for legacy effect annotation syntax.
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 6a43ff8c2..8f4d68a75 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -63,6 +63,7 @@
#include "slang-ir-string-hash.h"
#include "slang-ir-simplify-for-emit.h"
#include "slang-ir-pytorch-cpp-binding.h"
+#include "slang-ir-vk-invert-y.h"
#include "slang-legalize-types.h"
#include "slang-lower-to-ir.h"
#include "slang-mangle.h"
@@ -864,6 +865,8 @@ Result linkAndOptimizeIR(
if (isKhronosTarget(targetRequest) || target == CodeGenTarget::HLSL)
{
legalizeUniformBufferLoad(irModule);
+ if (targetRequest->getHLSLToVulkanLayoutOptions() && targetRequest->getHLSLToVulkanLayoutOptions()->shouldInvertY())
+ invertYOfPositionOutput(irModule);
}
// Lower sizeof/alignof
diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.cpp b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp
index 74a3313da..1c0e0858b 100644
--- a/source/slang/slang-hlsl-to-vulkan-layout-options.cpp
+++ b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp
@@ -91,7 +91,7 @@ Index HLSLToVulkanLayoutOptions::getShift(Kind kind, Index set) const
bool HLSLToVulkanLayoutOptions::hasState() const
{
- return canInferBindings() || hasGlobalsBinding();
+ return canInferBindings() || hasGlobalsBinding() || shouldInvertY();
}
HLSLToVulkanLayoutOptions::Binding HLSLToVulkanLayoutOptions::inferBinding(Kind kind, const Binding& inBinding) const
diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.h b/source/slang/slang-hlsl-to-vulkan-layout-options.h
index e16989810..4ae169d90 100644
--- a/source/slang/slang-hlsl-to-vulkan-layout-options.h
+++ b/source/slang/slang-hlsl-to-vulkan-layout-options.h
@@ -116,6 +116,9 @@ public:
/// True if can infer a binding for a kind
bool canInferBindingForKind(Kind kind) const { return (m_kindShiftEnabledFlags & getKindFlag(kind)) != 0; }
+ /// True if the compiler should invert the Y coordinate of any SV_Position output.
+ bool shouldInvertY() const { return m_invertY; }
+
/// Given an kind and a binding infer the vulkan binding.
/// Will return an invalid binding if one is not found
Binding inferBinding(Kind kind, const Binding& inBinding) const;
@@ -140,6 +143,8 @@ public:
/// Get the globals binding
const Binding& getGlobalsBinding() const { return m_globalsBinding; }
+ void setInvertY(bool value) { m_invertY = value; }
+
/// Ctor
HLSLToVulkanLayoutOptions();
@@ -163,6 +168,9 @@ protected:
/// Maps a key to the amount of shift
Dictionary<Key, Index> m_shifts;
+
+ /// Whether to invert the Y coordinate of SV_Position output.
+ bool m_invertY = false;
};
} // namespace Slang
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp
index 54eaa67a5..dfe370d2b 100644
--- a/source/slang/slang-ir-glsl-legalize.cpp
+++ b/source/slang/slang-ir-glsl-legalize.cpp
@@ -319,6 +319,12 @@ struct GlobalVaryingDeclarator
GlobalVaryingDeclarator* next;
};
+enum GLSLSystemValueKind
+{
+ General,
+ PositionOutput,
+};
+
struct GLSLSystemValueInfo
{
// The name of the built-in GLSL variable
@@ -334,6 +340,9 @@ struct GLSLSystemValueInfo
// If the built in GLSL variable is an array, holds the index into the array.
// If < 0, then there is no array indexing
Index arrayIndex;
+
+ // The kind of the system value that requires special treatment.
+ GLSLSystemValueKind kind = GLSLSystemValueKind::General;
};
static void leafAddressesImpl(List<IRInst*>& ret, const ScalarizedVal& v)
@@ -511,6 +520,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
char const* name = nullptr;
char const* outerArrayName = nullptr;
int arrayIndex = -1;
+ GLSLSystemValueKind systemValueKind = GLSLSystemValueKind::General;
auto semanticInst = varLayout->findSystemValueSemanticAttr();
if(!semanticInst)
@@ -558,6 +568,10 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
else
{
name = "gl_Position";
+ if (kind == LayoutResourceKind::VaryingOutput)
+ {
+ systemValueKind = GLSLSystemValueKind::PositionOutput;
+ }
}
requiredType = builder->getVectorType(builder->getBasicType(BaseType::Float), builder->getIntValue(builder->getIntType(), 4));
@@ -918,6 +932,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo(
inStorage->outerArrayName = outerArrayName;
inStorage->requiredType = requiredType;
inStorage->arrayIndex = arrayIndex;
+ inStorage->kind = systemValueKind;
return inStorage;
}
@@ -1160,6 +1175,15 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
{
builder->addGLSLOuterArrayDecoration(globalParam, UnownedTerminatedStringSlice(outerArrayName));
}
+
+ switch (systemValueInfo->kind)
+ {
+ case GLSLSystemValueKind::PositionOutput:
+ builder->addGLPositionOutputDecoration(globalParam);
+ break;
+ default:
+ break;
+ }
}
if(declarator && declarator->flavor == GlobalVaryingDeclarator::Flavor::meshOutputPrimitives)
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 231ae6dbe..4716ed427 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -795,6 +795,9 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST_RANGE(MeshOutputDecoration, VerticesDecoration, PrimitivesDecoration)
INST(GLSLPrimitivesRateDecoration, perprimitive, 0, 0)
+ // Marks an inst that represents the gl_Position output.
+ INST(GLPositionOutputDecoration, PositionOutput, 0, 0)
+
/* StageAccessDecoration */
INST(StageReadAccessDecoration, stageReadAccess, 0, 0)
INST(StageWriteAccessDecoration, stageWriteAccess, 0, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 417b39da3..2312cc4f2 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1213,6 +1213,11 @@ struct IRGLSLPrimitivesRateDecoration : public IRDecoration
IR_LEAF_ISA(GLSLPrimitivesRateDecoration)
};
+struct IRGLPositionOutputDecoration : public IRDecoration
+{
+ IR_LEAF_ISA(GLPositionOutputDecoration)
+};
+
struct IRMeshOutputRef : public IRInst
{
enum { kOp = kIROp_MeshOutputRef };
@@ -3815,6 +3820,11 @@ public:
addDecoration(value, kIROp_GLSLOuterArrayDecoration, getStringValue(text));
}
+ void addGLPositionOutputDecoration(IRInst* value)
+ {
+ addDecoration(value, kIROp_GLPositionOutputDecoration);
+ }
+
void addInterpolationModeDecoration(IRInst* value, IRInterpolationMode mode)
{
addDecoration(value, kIROp_InterpolationModeDecoration, getIntValue(getIntType(), IRIntegerValue(mode)));
diff --git a/source/slang/slang-ir-vk-invert-y.cpp b/source/slang/slang-ir-vk-invert-y.cpp
new file mode 100644
index 000000000..5c21fee95
--- /dev/null
+++ b/source/slang/slang-ir-vk-invert-y.cpp
@@ -0,0 +1,59 @@
+#include "slang-ir-vk-invert-y.h"
+#include "slang-ir.h"
+#include "slang-ir-insts.h"
+
+namespace Slang
+{
+
+static IRInst* _invertYOfVector(IRBuilder& builder, IRInst* originalVector)
+{
+ auto vectorType = as<IRVectorType>(originalVector->getDataType());
+ SLANG_ASSERT(vectorType);
+ UInt elementIndexY = 1;
+ auto originalY = builder.emitSwizzle(vectorType->getElementType(), originalVector, 1, &elementIndexY);
+ auto negY = builder.emitNeg(originalY->getDataType(), originalY);
+ auto newVal = builder.emitSwizzleSet(originalVector->getDataType(), originalVector, negY, 1, &elementIndexY);
+ return newVal;
+}
+// Find outputs to SV_Position and invert the y coordinates of it right before the write.
+void invertYOfPositionOutput(IRModule* module)
+{
+ for (auto globalInst : module->getGlobalInsts())
+ {
+ if (globalInst->findDecoration<IRGLPositionOutputDecoration>())
+ {
+ // Find all loads and stores to it.
+ IRBuilder builder(module);
+ traverseUses(globalInst, [&](IRUse* use)
+ {
+ if (auto store = as<IRStore>(use->getUser()))
+ {
+ if (store->getPtr() != globalInst)
+ return;
+
+ builder.setInsertBefore(store);
+ auto originalVal = store->getVal();
+ auto invertedVal = _invertYOfVector(builder, originalVal);
+ builder.replaceOperand(&store->val, invertedVal);
+ }
+ else if (auto load = as<IRLoad>(use->getUser()))
+ {
+ // Since we negate the y coordinate before writing
+ // to gl_Position, we also need to negate the value after reading from it.
+ builder.setInsertAfter(load);
+ // Store existing uses of the load that we are going to replace with inverted val later.
+ List<IRUse*> oldUses;
+ for (auto loadUse = load->firstUse; loadUse; loadUse = loadUse->nextUse)
+ oldUses.add(loadUse);
+ // Get the inverted vector.
+ auto invertedVal = _invertYOfVector(builder, load);
+ // Replace original uses with the invertex vector.
+ for (auto loadUse : oldUses)
+ builder.replaceOperand(loadUse, invertedVal);
+ }
+ });
+ }
+ }
+}
+
+}
diff --git a/source/slang/slang-ir-vk-invert-y.h b/source/slang/slang-ir-vk-invert-y.h
new file mode 100644
index 000000000..b6b1e4a4c
--- /dev/null
+++ b/source/slang/slang-ir-vk-invert-y.h
@@ -0,0 +1,10 @@
+#ifndef SLANG_IR_VK_INVERT_Y_H
+#define SLANG_IR_VK_INVERT_Y_H
+
+namespace Slang
+{
+ struct IRModule;
+ void invertYOfPositionOutput(IRModule* module);
+}
+
+#endif
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index dd4473497..e59109b37 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -92,6 +92,7 @@ enum class OptionKind
VulkanBindShift,
VulkanBindGlobals,
+ VulkanInvertY,
GLSLForceScalarLayout,
EnableEffectAnnotations,
@@ -496,6 +497,7 @@ void initCommandOptions(CommandOptions& options)
"* [GLSL wiki](https://github.com/KhronosGroup/glslang/wiki/HLSL-FAQ#auto-mapped-binding-numbers)\n" },
{ OptionKind::VulkanBindGlobals, "-fvk-bind-globals", "-fvk-bind-globals <N> <descriptor-set>",
"Places the $Globals cbuffer at descriptor set <descriptor-set> and binding <N>."},
+ { OptionKind::VulkanInvertY, "-fvk-invert-y", nullptr, "Negates (additively inverts) SV_Position.y before writing to stage output."},
{ OptionKind::EnableEffectAnnotations,
"-enable-effect-annotations", nullptr,
"Enables support for legacy effect annotation syntax."},
@@ -2008,6 +2010,12 @@ SlangResult OptionsParser::_parse(
m_hlslToVulkanLayoutOptions->setGlobalsBinding(Index(bindingSet), Index(binding));
break;
}
+ case OptionKind::VulkanInvertY:
+ {
+ // -fvk-invert-y
+ m_hlslToVulkanLayoutOptions->setInvertY(true);
+ break;
+ }
case OptionKind::Profile: SLANG_RETURN_ON_FAIL(_parseProfile(arg)); break;
case OptionKind::Capability:
{
diff --git a/tests/cross-compile/vk-invert-y.slang b/tests/cross-compile/vk-invert-y.slang
new file mode 100644
index 000000000..3ebedb594
--- /dev/null
+++ b/tests/cross-compile/vk-invert-y.slang
@@ -0,0 +1,21 @@
+// vk-invert-y.slang
+
+// Test to confirm that '-f-vk-invert-y' option works as expected.
+
+//TEST:SIMPLE(filecheck=CHECK):-target glsl -entry main -stage vertex -profile vs_5_1 -fvk-invert-y
+
+struct VOutput
+{
+ float4 v : SV_Position;
+}
+
+
+VOutput main()
+{
+ VOutput output;
+ output.v = float4(1, 2, 3, 4);
+
+ // CHECK: [[TMP:[_A-Za-z0-9]+]].y = - output_0.v_0.y;
+ // CHECK: gl_Position = [[TMP]];
+ return output;
+}