summaryrefslogtreecommitdiff
path: root/source/slang/slang-emit-spirv.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-emit-spirv.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-emit-spirv.cpp')
-rw-r--r--source/slang/slang-emit-spirv.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 06e5f0766..106248ef8 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -4,6 +4,7 @@
#include "slang-emit-base.h"
#include "slang-ir-util.h"
+#include "slang-ir-call-graph.h"
#include "slang-ir.h"
#include "slang-ir-insts.h"
#include "slang-ir-layout.h"
@@ -437,6 +438,7 @@ constexpr bool isPlural<IRUse*> = true;
template<typename T>
constexpr bool isSingular = !isPlural<T>;
+
// Now that we've defined the intermediate data structures we will
// use to represent SPIR-V code during emission, we will move on
// to defining the main context type that will drive SPIR-V
@@ -1278,6 +1280,11 @@ struct SPIRVEmitContext
return result;
}
+ bool hasExtensionDeclaration(const UnownedStringSlice& name)
+ {
+ return m_extensionInsts.containsKey(name);
+ }
+
struct SpvTypeInstKey
{
List<SpvWord> words;
@@ -2732,6 +2739,43 @@ struct SPIRVEmitContext
result = inner;
break;
}
+ case kIROp_RequireComputeDerivative:
+ {
+ auto parentFunc = getParentFunc(inst);
+
+ HashSet<IRFunc*>* entryPointsUsingInst = getReferencingEntryPoints(m_referencingEntryPoints, parentFunc);
+ for (IRFunc* entryPoint : *entryPointsUsingInst)
+ {
+ bool isQuad = true;
+ IREntryPointDecoration* entryPointDecor = nullptr;
+ for(auto dec : entryPoint->getDecorations())
+ {
+ if(auto maybeEntryPointDecor = as<IREntryPointDecoration>(dec))
+ entryPointDecor = maybeEntryPointDecor;
+ if(as<IRDerivativeGroupLinearDecoration>(dec))
+ isQuad = false;
+ }
+ if (!entryPointDecor || entryPointDecor->getProfile().getStage() != Stage::Compute)
+ continue;
+
+ ensureExtensionDeclaration(UnownedStringSlice("SPV_NV_compute_shader_derivatives"));
+ auto numThreadsDecor = entryPointDecor->findDecoration<IRNumThreadsDecoration>();
+ if (isQuad)
+ {
+ verifyComputeDerivativeGroupModifiers(this->m_sink, inst->sourceLoc, true, false, numThreadsDecor);
+ emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, entryPoint, SpvExecutionModeDerivativeGroupQuadsNV);
+ emitOpCapability(getSection(SpvLogicalSectionID::Capabilities), nullptr, SpvCapabilityComputeDerivativeGroupQuadsNV);
+ }
+ else
+ {
+ verifyComputeDerivativeGroupModifiers(this->m_sink, inst->sourceLoc, false, true, numThreadsDecor);
+ emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, entryPoint, SpvExecutionModeDerivativeGroupLinearNV);
+ emitOpCapability(getSection(SpvLogicalSectionID::Capabilities), nullptr, SpvCapabilityComputeDerivativeGroupLinearNV);
+ }
+ }
+
+ break;
+ }
case kIROp_Return:
if (as<IRReturn>(inst)->getVal()->getOp() == kIROp_VoidLit)
result = emitOpReturn(parent, inst);