summaryrefslogtreecommitdiff
path: root/source/slang/slang-emit-spirv.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-01-23 19:37:10 -0800
committerGitHub <noreply@github.com>2024-01-23 19:37:10 -0800
commitad45062fcc76cd622aaa1a9cb00515d42f8d3528 (patch)
tree28a54911021d4e3c8cd69dc47f67b8f39cdb310a /source/slang/slang-emit-spirv.cpp
parent1c1d096234d43b2bcb33c2438a6626831bd4e0aa (diff)
SPIRV Legalization fixes. (#3479)
* Fix CFG legalization for SPIRV backend. * Emit DepthReplacing execution mode. * Fix do-while lowering. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-emit-spirv.cpp')
-rw-r--r--source/slang/slang-emit-spirv.cpp100
1 files changed, 99 insertions, 1 deletions
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<IRSystemValueSemanticAttr>())
+ {
+ String semanticName = systemValueAttr->getName();
+ semanticName = semanticName.toLower();
+ if (semanticName == "sv_position")
+ {
+ auto importDecor = builtinVar->findDecoration<IRImportDecoration>();
+ 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<IRDecoration>(user))
+ continue;
+ switch (user->getOp())
+ {
+ case kIROp_SwizzledStore:
+ case kIROp_Store:
+ return result;
+ }
+ }
+ return result;
+ }
+
+ void maybeEmitEntryPointDepthReplacingExecutionMode(
+ IRFunc* entryPoint,
+ const List<IRInst*>& 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 `<id>` of the SPIR-V instruction being decorated,
@@ -2624,6 +2717,7 @@ struct SPIRVEmitContext
auto name = entryPointDecor->getName()->getStringSlice();
List<SpvInst*> params;
HashSet<SpvInst*> paramsSet;
+ List<IRInst*> 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)