summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-emit-spirv.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-06-11 12:31:37 -0700
committerGitHub <noreply@github.com>2024-06-11 12:31:37 -0700
commit6909d65c77bb4e7c9cfb281bd1684a58d5f8b94d (patch)
tree396a628b7fda779dcc6e820e86d44e29d0c7be95 /source/slang/slang-emit-spirv.cpp
parentef20d9309674dc8c25a9798d95138cf739299928 (diff)
SPIRV backend: add support for tessellation stages, (#4336)
Diffstat (limited to 'source/slang/slang-emit-spirv.cpp')
-rw-r--r--source/slang/slang-emit-spirv.cpp102
1 files changed, 97 insertions, 5 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 4f7410f00..fd4b1d491 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -2963,6 +2963,15 @@ struct SPIRVEmitContext
result = emitOpAtomicIDecrement(parent, inst, inst->getFullType(), inst->getOperand(0), memoryScope, memorySemantics);
}
break;
+ case kIROp_ControlBarrier:
+ {
+ IRBuilder builder{ inst };
+ const auto executionScope = emitIntConstant(IRIntegerValue{ SpvScopeWorkgroup }, builder.getUIntType());
+ const auto memoryScope = emitIntConstant(IRIntegerValue{ SpvScopeInvocation }, builder.getUIntType());
+ const auto memorySemantics = emitIntConstant(IRIntegerValue{ SpvMemorySemanticsMaskNone }, builder.getUIntType());
+ emitInst(parent, inst, SpvOpControlBarrier, executionScope, memoryScope, memorySemantics);
+ }
+ break;
}
if (result)
emitDecorations(inst, getID(result));
@@ -3323,6 +3332,29 @@ struct SPIRVEmitContext
requireSPIRVCapability(SpvCapabilityMeshShadingEXT);
ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_mesh_shader"));
break;
+ case Stage::Hull:
+ {
+ requireSPIRVCapability(SpvCapabilityTessellation);
+
+ SpvExecutionMode mode = SpvExecutionModeSpacingEqual;
+ if (auto partitioningDecor = entryPoint->findDecoration<IRPartitioningDecoration>())
+ {
+ auto arg = partitioningDecor->getPartitioning()->getStringSlice();
+ if (arg.caseInsensitiveEquals(toSlice("integer")))
+ mode = SpvExecutionModeSpacingEqual;
+ else if (arg.caseInsensitiveEquals(toSlice("fractional_even")))
+ mode = SpvExecutionModeSpacingFractionalEven;
+ else if (arg.caseInsensitiveEquals(toSlice("fractional_odd")))
+ mode = SpvExecutionModeSpacingFractionalOdd;
+ else
+ m_sink->diagnose(partitioningDecor, Diagnostics::unknownTessPartitioning, arg);
+ }
+ requireSPIRVExecutionMode(nullptr, getIRInstSpvID(entryPoint), mode);
+ break;
+ }
+ case Stage::Domain:
+ requireSPIRVCapability(SpvCapabilityTessellation);
+ break;
default:
break;
}
@@ -3463,13 +3495,36 @@ struct SPIRVEmitContext
case kIROp_OutputTopologyDecoration:
{
+ auto entryPoint = decoration->getParent();
+ IREntryPointDecoration* entryPointDecor = entryPoint ? entryPoint->findDecoration<IREntryPointDecoration>() : nullptr;
+
const auto o = cast<IROutputTopologyDecoration>(decoration);
const auto t = o->getTopology()->getStringSlice();
- const auto m =
- t == "triangle" ? SpvExecutionModeOutputTrianglesEXT
- : t == "line" ? SpvExecutionModeOutputLinesEXT
- : t == "point" ? SpvExecutionModeOutputPoints
- : SpvExecutionModeMax;
+
+ SpvExecutionMode m = SpvExecutionModeMax;
+ if (entryPointDecor)
+ {
+ switch (entryPointDecor->getProfile().getStage())
+ {
+ case Stage::Domain:
+ case Stage::Hull:
+ if (t == "triangle_cw")
+ m = SpvExecutionModeVertexOrderCw;
+ else if (t == "triangle_ccw")
+ m = SpvExecutionModeVertexOrderCcw;
+ break;
+ }
+ }
+ if (m == SpvExecutionModeMax)
+ {
+ if (t == "triangle")
+ m = SpvExecutionModeOutputTrianglesEXT;
+ else if (t == "line")
+ m = SpvExecutionModeOutputTrianglesEXT;
+ else if (t == "point")
+ m = SpvExecutionModeOutputPoints;
+ }
+
SLANG_ASSERT(m != SpvExecutionModeMax);
requireSPIRVExecutionMode(decoration, dstID, m);
}
@@ -3544,6 +3599,31 @@ struct SPIRVEmitContext
dstID,
SpvDecorationPerVertexKHR);
break;
+ case kIROp_OutputControlPointsDecoration:
+ requireSPIRVExecutionMode(
+ decoration,
+ dstID,
+ SpvExecutionModeOutputVertices,
+ SpvLiteralInteger::from32(int32_t(getIntVal(decoration->getOperand(0)))));
+ break;
+ case kIROp_DomainDecoration:
+ {
+ auto domain = cast<IRDomainDecoration>(decoration);
+ SpvExecutionMode mode = SpvExecutionModeMax;
+ auto domainName = as<IRStringLit>(domain->getDomain());
+ if (!domainName)
+ break;
+ auto domainStr = domainName->getStringSlice();
+ if (domainStr.startsWithCaseInsensitive(toSlice("tri")))
+ mode = SpvExecutionModeTriangles;
+ else if (domainStr.caseInsensitiveEquals(toSlice("quad")))
+ mode = SpvExecutionModeQuads;
+ else if (domainStr.caseInsensitiveEquals(toSlice("isoline")))
+ mode = SpvExecutionModeIsolines;
+ if (mode != SpvExecutionModeMax)
+ requireSPIRVExecutionMode(decoration, dstID, mode);
+ }
+ break;
case kIROp_MemoryQualifierSetDecoration:
{
auto collection = as<IRMemoryQualifierSetDecoration>(decoration);
@@ -3941,6 +4021,18 @@ struct SPIRVEmitContext
varInst,
builtinVal
);
+ switch (builtinVal)
+ {
+ case SpvBuiltInTessLevelInner:
+ case SpvBuiltInTessLevelOuter:
+ emitOpDecorate(
+ getSection(SpvLogicalSectionID::Annotations),
+ nullptr,
+ varInst,
+ SpvDecorationPatch
+ );
+ break;
+ }
m_builtinGlobalVars[key] = varInst;
maybeEmitFlatDecorationForBuiltinVar(irInst, varInst);