From 0e478443815c62c6d6cd042fbbeaeceeb6830478 Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 21 Jul 2023 15:03:42 -0700 Subject: Add support for `-fvk-invert-y`. (#3012) Co-authored-by: Yong He --- build/visual-studio/slang/slang.vcxproj | 2 + build/visual-studio/slang/slang.vcxproj.filters | 6 +++ docs/command-line-slangc-reference.md | 5 ++ source/slang/slang-emit.cpp | 3 ++ .../slang/slang-hlsl-to-vulkan-layout-options.cpp | 2 +- source/slang/slang-hlsl-to-vulkan-layout-options.h | 8 +++ source/slang/slang-ir-glsl-legalize.cpp | 24 +++++++++ source/slang/slang-ir-inst-defs.h | 3 ++ source/slang/slang-ir-insts.h | 10 ++++ source/slang/slang-ir-vk-invert-y.cpp | 59 ++++++++++++++++++++++ source/slang/slang-ir-vk-invert-y.h | 10 ++++ source/slang/slang-options.cpp | 8 +++ tests/cross-compile/vk-invert-y.slang | 21 ++++++++ 13 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 source/slang/slang-ir-vk-invert-y.cpp create mode 100644 source/slang/slang-ir-vk-invert-y.h create mode 100644 tests/cross-compile/vk-invert-y.slang 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 + @@ -661,6 +662,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla + 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 @@ Header Files + + Header Files + Header Files @@ -1067,6 +1070,9 @@ Source Files + + Source Files + Source Files 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 <N> <space>' shifts by N the inferred bind Places the $Globals cbuffer at descriptor set <descriptor-set> and binding <N>. + +## -fvk-invert-y +Negates (additively inverts) SV_Position.y before writing to stage output. + + ## -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 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& 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(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()) + { + // Find all loads and stores to it. + IRBuilder builder(module); + traverseUses(globalInst, [&](IRUse* use) + { + if (auto store = as(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(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 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 ", "Places the $Globals cbuffer at descriptor set and binding ."}, + { 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; +} -- cgit v1.2.3