summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-call-graph.cpp
diff options
context:
space:
mode:
authorArielG-NV <159081215+ArielG-NV@users.noreply.github.com>2024-04-25 09:18:32 -0400
committerGitHub <noreply@github.com>2024-04-25 09:18:32 -0400
commit366a947cdf2e3c6958b7a9e17d561ce76ab0f594 (patch)
treeca305c7315806b51c3922d334b10b5f203a0b219 /source/slang/slang-ir-call-graph.cpp
parent52dcb5bd44aa15f07826062c53fae344d55959e9 (diff)
Support derivative functions in compute & capabilities adjustments (#4014)
* Support derivative functions in compute & capabilities adjustments fixes #4000 PR implements derivative functions in compute shaders properly so we have the functionality for SPIR-V & GLSL. Tests reflect fragment and compute paths. PR also adjusts capabilities to correct wrong SPRI-V target capabilities for when using textures. Remarks: 1. __requireComputeDerivative(); is a intrinsic_op and not modifier since inlining will destroy the modifier. 2. Derivative mode is tied to an entry point decoration `[DerivativeGroupQuad]`/`[DerivativeGroupLinear]` or GLSL syntax ``derivative_group_linearNV`. Default is to set the mode to `[DerivativeGroupQuad]` * remove -emit-spirv-directly * fixes 1. fix minor issue fwidth change where I returned the wrong type 2. fix issue where glslang{glsl->spirv} is wrong, so we don't run that test and just run the glsl test & direct spir-v test for intrinsic-texture.slang * adjust as per review and refine code 1. add test to ensure multi-diverging-in-logic entry points work -- 2 functions which may cause computeDerivatives + 1 that uses, 1 that does not. 2. naming 3. use entry point ref graph for c-like-targets 4. reordered some code to util's and removed `static linline` since that was just for ease of coding on my end (should not have been pushed). * Grammer * split up source file + issolate GLSL emit path change. --------- Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source/slang/slang-ir-call-graph.cpp')
-rw-r--r--source/slang/slang-ir-call-graph.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/source/slang/slang-ir-call-graph.cpp b/source/slang/slang-ir-call-graph.cpp
new file mode 100644
index 000000000..b3de60228
--- /dev/null
+++ b/source/slang/slang-ir-call-graph.cpp
@@ -0,0 +1,112 @@
+#include "slang-ir-call-graph.h"
+#include "slang-ir-insts.h"
+#include "slang-ir-clone.h"
+
+namespace Slang
+{
+
+void buildEntryPointReferenceGraph(Dictionary<IRInst*, HashSet<IRFunc*>>& referencingEntryPoints, IRModule* module)
+{
+ struct WorkItem
+ {
+ IRFunc* entryPoint; IRInst* inst;
+
+ HashCode getHashCode() const
+ {
+ return combineHash(Slang::getHashCode(entryPoint), Slang::getHashCode(inst));
+ }
+ bool operator == (const WorkItem& other) const
+ {
+ return entryPoint == other.entryPoint && inst == other.inst;
+ }
+ };
+ HashSet<WorkItem> workListSet;
+ List<WorkItem> workList;
+ auto addToWorkList = [&](WorkItem item)
+ {
+ if (workListSet.add(item))
+ workList.add(item);
+ };
+
+ auto registerEntryPointReference = [&](IRFunc* entryPoint, IRInst* inst)
+ {
+ if (auto set = referencingEntryPoints.tryGetValue(inst))
+ set->add(entryPoint);
+ else
+ {
+ HashSet<IRFunc*> newSet;
+ newSet.add(entryPoint);
+ referencingEntryPoints.add(inst, _Move(newSet));
+ }
+ };
+ auto visit = [&](IRFunc* entryPoint, IRInst* inst)
+ {
+ if (auto code = as<IRGlobalValueWithCode>(inst))
+ {
+ registerEntryPointReference(entryPoint, inst);
+ for (auto child : code->getChildren())
+ {
+ addToWorkList({ entryPoint, child });
+ }
+ return;
+ }
+ switch (inst->getOp())
+ {
+ case kIROp_GlobalParam:
+ case kIROp_SPIRVAsmOperandBuiltinVar:
+ registerEntryPointReference(entryPoint, inst);
+ break;
+ case kIROp_Block:
+ case kIROp_SPIRVAsm:
+ for (auto child : inst->getChildren())
+ {
+ addToWorkList({ entryPoint, child });
+ }
+ break;
+ case kIROp_Call:
+ {
+ auto call = as<IRCall>(inst);
+ addToWorkList({ entryPoint, call->getCallee() });
+ }
+ break;
+ case kIROp_SPIRVAsmOperandInst:
+ {
+ auto operand = as<IRSPIRVAsmOperandInst>(inst);
+ addToWorkList({ entryPoint, operand->getValue() });
+ }
+ break;
+ }
+ for (UInt i = 0; i < inst->getOperandCount(); i++)
+ {
+ auto operand = inst->getOperand(i);
+ switch (operand->getOp())
+ {
+ case kIROp_GlobalParam:
+ case kIROp_GlobalVar:
+ case kIROp_SPIRVAsmOperandBuiltinVar:
+ addToWorkList({ entryPoint, operand });
+ break;
+ }
+ }
+ };
+
+ for (auto globalInst : module->getGlobalInsts())
+ {
+ if (globalInst->getOp() == kIROp_Func && globalInst->findDecoration<IREntryPointDecoration>())
+ {
+ visit(as<IRFunc>(globalInst), globalInst);
+ }
+ }
+ for (Index i = 0; i < workList.getCount(); i++)
+ visit(workList[i].entryPoint, workList[i].inst);
+}
+
+HashSet<IRFunc*>* getReferencingEntryPoints(Dictionary<IRInst*, HashSet<IRFunc*>>& m_referencingEntryPoints, IRInst* inst)
+{
+ auto* referencingEntryPoints = m_referencingEntryPoints.tryGetValue(inst);
+ if (!referencingEntryPoints)
+ return nullptr;
+ return referencingEntryPoints;
+}
+
+}