From ad45062fcc76cd622aaa1a9cb00515d42f8d3528 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 23 Jan 2024 19:37:10 -0800 Subject: SPIRV Legalization fixes. (#3479) * Fix CFG legalization for SPIRV backend. * Emit DepthReplacing execution mode. * Fix do-while lowering. --------- Co-authored-by: Yong He --- source/slang/slang-emit-spirv.cpp | 100 +++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) (limited to 'source/slang/slang-emit-spirv.cpp') diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 46ce1d0b5..a2a0bff58 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -2557,6 +2557,99 @@ struct SPIRVEmitContext } } + + SpvExecutionMode isDepthOutput(IRInst* builtinVar) + { + SpvExecutionMode result = SpvExecutionModeMax; + bool isDepthVar = false; + if (auto layout = getVarLayout(builtinVar)) + { + if (auto systemValueAttr = layout->findAttr()) + { + String semanticName = systemValueAttr->getName(); + semanticName = semanticName.toLower(); + if (semanticName == "sv_position") + { + auto importDecor = builtinVar->findDecoration(); + if (importDecor->getMangledName() == "gl_FragCoord") + { + isDepthVar = true; + result = SpvExecutionModeDepthReplacing; + } + } + else if (semanticName == "sv_depth") + { + isDepthVar = true; + result = SpvExecutionModeDepthReplacing; + } + else if (semanticName == "sv_depthgreaterequal") + { + isDepthVar = true; + result = SpvExecutionModeDepthGreater; + } + else if (semanticName == "sv_depthlessequal") + { + isDepthVar = true; + result = SpvExecutionModeDepthLess; + } + } + } + if (!isDepthVar) + return result; + for (auto use = builtinVar->firstUse; use; use = use->nextUse) + { + auto user = use->getUser(); + if (user->getOp() == kIROp_Load) + continue; + if (as(user)) + continue; + switch (user->getOp()) + { + case kIROp_SwizzledStore: + case kIROp_Store: + return result; + } + } + return result; + } + + void maybeEmitEntryPointDepthReplacingExecutionMode( + IRFunc* entryPoint, + const List& referencedBuiltinIRVars) + { + // Check if the entrypoint uses any depth output builtin variables, + // if so, we need to emit a DepthReplacing execution mode for the + // fragment entrypoint. + bool needDepthReplacingMode = false; + SpvExecutionMode mode = SpvExecutionModeMax; + for (auto globalInst : referencedBuiltinIRVars) + { + if (auto thisMode = isDepthOutput(globalInst)) + { + needDepthReplacingMode = true; + if (mode == SpvExecutionModeMax) + mode = thisMode; + else if (mode != thisMode) + mode = SpvExecutionModeDepthReplacing; + break; + } + } + if (!needDepthReplacingMode) + return; + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), + nullptr, + entryPoint, + SpvExecutionModeDepthReplacing); + if (mode != SpvExecutionModeDepthReplacing && + mode != SpvExecutionModeMax) + { + emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), + nullptr, + entryPoint, + mode); + } + } + /// Emit an appropriate SPIR-V decoration for the given IR `decoration`, if necessary and possible. /// /// The given `dstID` should be the `` of the SPIR-V instruction being decorated, @@ -2624,6 +2717,7 @@ struct SPIRVEmitContext auto name = entryPointDecor->getName()->getStringSlice(); List params; HashSet paramsSet; + List referencedBuiltinIRVars; // `interface` part: reference all global variables that are used by this entrypoint. for (auto globalInst : m_irModule->getModuleInst()->getChildren()) { @@ -2641,6 +2735,7 @@ struct SPIRVEmitContext { paramsSet.add(spvGlobalInst); params.add(spvGlobalInst); + referencedBuiltinIRVars.add(globalInst); } } break; @@ -2648,8 +2743,11 @@ struct SPIRVEmitContext default: break; } + if (entryPointDecor->getProfile().getStage() == Stage::Fragment) + { + maybeEmitEntryPointDepthReplacingExecutionMode(entryPoint, referencedBuiltinIRVars); + } } - // Add remaining builtin variables that does not have a corresponding IR global var/param. // These variables could be added from SPIRV ASM blocks. for (auto builtinVar : m_builtinGlobalVars) -- cgit v1.2.3