diff options
| author | Yong He <yonghe@outlook.com> | 2023-07-21 15:03:42 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-21 15:03:42 -0700 |
| commit | 0e478443815c62c6d6cd042fbbeaeceeb6830478 (patch) | |
| tree | 383a16465feadfd5800ebec547ae86d844853210 | |
| parent | 82508d87e1199a2e299ac21b8b6ac8d192917d1d (diff) | |
Add support for `-fvk-invert-y`. (#3012)
Co-authored-by: Yong He <yhe@nvidia.com>
| -rw-r--r-- | build/visual-studio/slang/slang.vcxproj | 2 | ||||
| -rw-r--r-- | build/visual-studio/slang/slang.vcxproj.filters | 6 | ||||
| -rw-r--r-- | docs/command-line-slangc-reference.md | 5 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-to-vulkan-layout-options.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-to-vulkan-layout-options.h | 8 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 24 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-ir-vk-invert-y.cpp | 59 | ||||
| -rw-r--r-- | source/slang/slang-ir-vk-invert-y.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 8 | ||||
| -rw-r--r-- | tests/cross-compile/vk-invert-y.slang | 21 |
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 <N> <space>' shifts by N the inferred bind Places the $Globals cbuffer at descriptor set <descriptor-set> and binding <N>. +<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; +} |
