summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-07-21 15:03:42 -0700
committerGitHub <noreply@github.com>2023-07-21 15:03:42 -0700
commit0e478443815c62c6d6cd042fbbeaeceeb6830478 (patch)
tree383a16465feadfd5800ebec547ae86d844853210 /source
parent82508d87e1199a2e299ac21b8b6ac8d192917d1d (diff)
Add support for `-fvk-invert-y`. (#3012)
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source')
-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
9 files changed, 126 insertions, 1 deletions
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:
{