diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-11 14:52:16 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-11 14:52:16 -0700 |
| commit | 7c7fbd572874bdbb3e6f965da3abb918013e1ac8 (patch) | |
| tree | 47b09522ec72b4ab651127d67e7ebc6020bac376 /source | |
| parent | 1bbcf25af514a9ae24f7006747177f2d1b3b7c0d (diff) | |
Add `-fvk-use-dx-position-w` and fix ExecutionMode ordering for geometry shaders. (#3731)
* Add `-fvk-use-dx-position-w`.
* Fix ordering of OutputVertices and output primitive type decoration in spirv.
* Fix.
* fix
* Fix.
* Move test around.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-compiler-options.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 58 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-to-vulkan-layout-options.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-hlsl-to-vulkan-layout-options.h | 8 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 5 | ||||
| -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 | 32 | ||||
| -rw-r--r-- | source/slang/slang-ir-vk-invert-y.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 2 |
11 files changed, 96 insertions, 29 deletions
diff --git a/source/slang/slang-compiler-options.cpp b/source/slang/slang-compiler-options.cpp index 100a5719f..974fbaaaa 100644 --- a/source/slang/slang-compiler-options.cpp +++ b/source/slang/slang-compiler-options.cpp @@ -113,6 +113,7 @@ namespace Slang case CompilerOptionName::MatrixLayoutRow: case CompilerOptionName::MatrixLayoutColumn: case CompilerOptionName::VulkanInvertY: + case CompilerOptionName::VulkanUseDxPositionW: case CompilerOptionName::VulkanUseEntryPointName: case CompilerOptionName::VulkanUseGLLayout: case CompilerOptionName::VulkanEmitReflection: diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 2f318c464..8063975e2 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -3074,16 +3074,9 @@ struct SPIRVEmitContext } break; case kIROp_MaxVertexCountDecoration: - { - auto section = getSection(SpvLogicalSectionID::ExecutionModes); - auto maxVertexCount = cast<IRMaxVertexCountDecoration>(decoration); - emitOpExecutionModeOutputVertices( - section, - decoration, - dstID, - SpvLiteralInteger::from32(int32_t(getIntVal(maxVertexCount->getCount()))) - ); - } + // Don't do anything here, instead wait until we see OutputTopologyDecoration + // and emit them together to ensure MaxVertexCount always appears before OutputTopology, + // which seemed to be required by SPIRV. break; case kIROp_InstanceDecoration: { @@ -3094,22 +3087,49 @@ struct SPIRVEmitContext } break; case kIROp_TriangleInputPrimitiveTypeDecoration: - emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeTriangles); - break; case kIROp_LineInputPrimitiveTypeDecoration: - emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeInputLines); - break; case kIROp_LineAdjInputPrimitiveTypeDecoration: - emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeInputLinesAdjacency); - break; case kIROp_PointInputPrimitiveTypeDecoration: - emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeInputPoints); - break; case kIROp_TriangleAdjInputPrimitiveTypeDecoration: - emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeInputTrianglesAdjacency); + // Defer this until we see kIROp_StreamOutputTypeDecoration because the driver wants to see + // them before the output. break; case kIROp_StreamOutputTypeDecoration: { + for (auto inputDecor : decoration->getParent()->getDecorations()) + { + switch (inputDecor->getOp()) + { + case kIROp_TriangleInputPrimitiveTypeDecoration: + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeTriangles); + break; + case kIROp_LineInputPrimitiveTypeDecoration: + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputLines); + break; + case kIROp_LineAdjInputPrimitiveTypeDecoration: + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputLinesAdjacency); + break; + case kIROp_PointInputPrimitiveTypeDecoration: + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputPoints); + break; + case kIROp_TriangleAdjInputPrimitiveTypeDecoration: + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputTrianglesAdjacency); + break; + } + } + // SPIRV requires MaxVertexCount decoration to appear before OutputTopologyDecoration, + // so we emit them here. + if (auto maxVertexCount = decoration->getParent()->findDecoration<IRMaxVertexCountDecoration>()) + { + auto section = getSection(SpvLogicalSectionID::ExecutionModes); + emitOpExecutionModeOutputVertices( + section, + maxVertexCount, + dstID, + SpvLiteralInteger::from32(int32_t(getIntVal(maxVertexCount->getCount()))) + ); + } + auto decor = as<IRStreamOutputTypeDecoration>(decoration); IRType* type = decor->getStreamType(); diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 5ec6fa62a..0ec9b0c1a 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -934,6 +934,8 @@ Result linkAndOptimizeIR( legalizeUniformBufferLoad(irModule); if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::VulkanInvertY)) invertYOfPositionOutput(irModule); + if (targetProgram->getOptionSet().getBoolOption(CompilerOptionName::VulkanUseDxPositionW)) + rcpWOfPositionInput(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 0e6f70294..4246b7b39 100644 --- a/source/slang/slang-hlsl-to-vulkan-layout-options.cpp +++ b/source/slang/slang-hlsl-to-vulkan-layout-options.cpp @@ -53,7 +53,6 @@ void HLSLToVulkanLayoutOptions::loadFromOptionSet(CompilerOptionSet& optionSet) m_globalsBinding.set = (*bindGlobals)[0].intValue2; } } - m_invertY = optionSet.getBoolOption(CompilerOptionName::VulkanInvertY); m_useGLLayout = optionSet.getBoolOption(CompilerOptionName::VulkanUseGLLayout); m_useOriginalEntryPointName = optionSet.getBoolOption(CompilerOptionName::VulkanUseEntryPointName); @@ -123,7 +122,7 @@ Index HLSLToVulkanLayoutOptions::getShift(Kind kind, Index set) const bool HLSLToVulkanLayoutOptions::hasState() const { - return canInferBindings() || hasGlobalsBinding() || shouldInvertY() || getUseOriginalEntryPointName() + return canInferBindings() || hasGlobalsBinding() || getUseOriginalEntryPointName() || shouldUseGLLayout() || shouldEmitSPIRVReflectionInfo(); } diff --git a/source/slang/slang-hlsl-to-vulkan-layout-options.h b/source/slang/slang-hlsl-to-vulkan-layout-options.h index 2b8ec973c..1b7daf330 100644 --- a/source/slang/slang-hlsl-to-vulkan-layout-options.h +++ b/source/slang/slang-hlsl-to-vulkan-layout-options.h @@ -119,9 +119,6 @@ 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; } - bool shouldUseGLLayout() const { return m_useGLLayout; } bool shouldEmitSPIRVReflectionInfo() const { return m_emitSPIRVReflectionInfo; } @@ -152,8 +149,6 @@ public: /// Get the globals binding const Binding& getGlobalsBinding() const { return m_globalsBinding; } - void setInvertY(bool value) { m_invertY = value; } - void setUseOriginalEntryPointName(bool value) { m_useOriginalEntryPointName = value; } void setUseGLLayout(bool value) { m_useGLLayout = value; } @@ -186,9 +181,6 @@ 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; - /// If set, will use the original entry point name in the generated SPIRV instead of "main". bool m_useOriginalEntryPointName = false; diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index d2d09f45a..e40dc33ff 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -335,6 +335,7 @@ enum GLSLSystemValueKind { General, PositionOutput, + PositionInput, }; struct GLSLSystemValueInfo @@ -569,6 +570,7 @@ GLSLSystemValueInfo* getGLSLSystemValueInfo( && kind == LayoutResourceKind::VaryingInput ) { name = "gl_FragCoord"; + systemValueKind = GLSLSystemValueKind::PositionInput; } else if( stage == Stage::Geometry && kind == LayoutResourceKind::VaryingInput ) @@ -1008,6 +1010,9 @@ void createVarLayoutForLegalizedGlobalParam( case GLSLSystemValueKind::PositionOutput: builder->addGLPositionOutputDecoration(globalParam); break; + case GLSLSystemValueKind::PositionInput: + builder->addGLPositionInputDecoration(globalParam); + break; default: break; } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index cd79f05a6..26e0ebd69 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -859,6 +859,9 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) INST(GLSLPrimitivesRateDecoration, perprimitive, 0, 0) // Marks an inst that represents the gl_Position output. INST(GLPositionOutputDecoration, PositionOutput, 0, 0) + // Marks an inst that represents the gl_Position input. + INST(GLPositionInputDecoration, PositionInput, 0, 0) + /* StageAccessDecoration */ INST(StageReadAccessDecoration, stageReadAccess, 0, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 6fbccab5c..0a7f8c33b 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -1366,6 +1366,11 @@ struct IRGLPositionOutputDecoration : public IRDecoration IR_LEAF_ISA(GLPositionOutputDecoration) }; +struct IRGLPositionInputDecoration : public IRDecoration +{ + IR_LEAF_ISA(GLPositionInputDecoration) +}; + struct IRMeshOutputRef : public IRInst { enum { kOp = kIROp_MeshOutputRef }; @@ -4297,6 +4302,11 @@ public: addDecoration(value, kIROp_GLPositionOutputDecoration); } + void addGLPositionInputDecoration(IRInst* value) + { + addDecoration(value, kIROp_GLPositionInputDecoration); + } + 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 index 5c21fee95..5e2dfcf2e 100644 --- a/source/slang/slang-ir-vk-invert-y.cpp +++ b/source/slang/slang-ir-vk-invert-y.cpp @@ -56,4 +56,36 @@ void invertYOfPositionOutput(IRModule* module) } } + +static IRInst* _invertWOfVector(IRBuilder& builder, IRInst* originalVector) +{ + auto vectorType = as<IRVectorType>(originalVector->getDataType()); + SLANG_ASSERT(vectorType); + UInt elementIndexW = 3; + auto originalW = builder.emitSwizzle(vectorType->getElementType(), originalVector, 1, &elementIndexW); + auto rcpW = builder.emitDiv(originalW->getDataType(), builder.getFloatValue(originalW->getDataType(), 1.0), originalW); + auto newVal = builder.emitSwizzleSet(originalVector->getDataType(), originalVector, rcpW, 1, &elementIndexW); + return newVal; +} + +// Find inputs of SV_Position and rcp the w coordinates of it right after the read. +void rcpWOfPositionInput(IRModule* module) +{ + for (auto globalInst : module->getGlobalInsts()) + { + if (globalInst->findDecoration<IRGLPositionInputDecoration>()) + { + // Find all loads and replace them with reciprocals. + IRBuilder builder(module); + traverseUses(globalInst, [&](IRUse* use) + { + // Get the inverted vector. + builder.setInsertBefore(use->getUser()); + auto invertedVal = _invertWOfVector(builder, globalInst); + // Replace original uses with the invertex vector. + builder.replaceOperand(use, invertedVal); + }); + } + } +} } diff --git a/source/slang/slang-ir-vk-invert-y.h b/source/slang/slang-ir-vk-invert-y.h index b6b1e4a4c..4fc007169 100644 --- a/source/slang/slang-ir-vk-invert-y.h +++ b/source/slang/slang-ir-vk-invert-y.h @@ -5,6 +5,7 @@ namespace Slang { struct IRModule; void invertYOfPositionOutput(IRModule* module); + void rcpWOfPositionInput(IRModule* module); } #endif diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index 42eb66517..3d0b22edd 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -399,6 +399,7 @@ void initCommandOptions(CommandOptions& options) { 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::VulkanUseDxPositionW, "-fvk-use-dx-position-w", nullptr, "Reciprocates (multiplicatively inverts) SV_Position.w after reading from stage input. For use in fragment shaders only."}, { OptionKind::VulkanUseEntryPointName, "-fvk-use-entrypoint-name", nullptr, "Uses the entrypoint name from the source instead of 'main' in the spirv output."}, { OptionKind::VulkanUseGLLayout, "-fvk-use-gl-layout", nullptr, "Use std430 layout instead of D3D buffer layout for raw buffer load/stores."}, { OptionKind::VulkanEmitReflection, "-fspv-reflect", nullptr, "Include reflection decorations in the resulting SPIRV for shader parameters."}, @@ -1681,6 +1682,7 @@ SlangResult OptionsParser::_parse( case OptionKind::ValidateIr: case OptionKind::DumpIr: case OptionKind::VulkanInvertY: + case OptionKind::VulkanUseDxPositionW: case OptionKind::VulkanUseEntryPointName: case OptionKind::VulkanUseGLLayout: case OptionKind::VulkanEmitReflection: |
