-
Notifications
You must be signed in to change notification settings - Fork 360
Emit execution mode of type per entry point once. Emit SPIRV capability once per shader program. #4189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Emit execution mode of type per entry point once. Emit SPIRV capability once per shader program. #4189
Changes from 2 commits
4b4836f
df8279f
66eb23e
ade5a45
c67c354
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2765,14 +2765,14 @@ struct SPIRVEmitContext | |
if (isQuad) | ||
{ | ||
verifyComputeDerivativeGroupModifiers(this->m_sink, inst->sourceLoc, true, false, numThreadsDecor); | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, entryPoint, SpvExecutionModeDerivativeGroupQuadsNV); | ||
emitOpCapability(getSection(SpvLogicalSectionID::Capabilities), nullptr, SpvCapabilityComputeDerivativeGroupQuadsNV); | ||
requireSPIRVExecutionMode(nullptr, getID(ensureInst(entryPoint)), SpvExecutionModeDerivativeGroupQuadsNV); | ||
requireSPIRVCapability(SpvCapabilityComputeDerivativeGroupQuadsNV); | ||
} | ||
else | ||
{ | ||
verifyComputeDerivativeGroupModifiers(this->m_sink, inst->sourceLoc, false, true, numThreadsDecor); | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, entryPoint, SpvExecutionModeDerivativeGroupLinearNV); | ||
emitOpCapability(getSection(SpvLogicalSectionID::Capabilities), nullptr, SpvCapabilityComputeDerivativeGroupLinearNV); | ||
requireSPIRVExecutionMode(nullptr, getID(ensureInst(entryPoint)), SpvExecutionModeDerivativeGroupLinearNV); | ||
requireSPIRVCapability(SpvCapabilityComputeDerivativeGroupLinearNV); | ||
} | ||
} | ||
|
||
|
@@ -2790,7 +2790,7 @@ struct SPIRVEmitContext | |
case kIROp_BeginFragmentShaderInterlock: | ||
ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_fragment_shader_interlock")); | ||
requireSPIRVCapability(SpvCapabilityFragmentShaderPixelInterlockEXT); | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, getParentFunc(inst), SpvExecutionModePixelInterlockOrderedEXT); | ||
requireSPIRVExecutionMode(nullptr, getID(ensureInst(getParentFunc(inst))), SpvExecutionModePixelInterlockOrderedEXT); | ||
result = emitOpBeginInvocationInterlockEXT(parent, inst); | ||
break; | ||
case kIROp_EndFragmentShaderInterlock: | ||
|
@@ -3130,10 +3130,7 @@ struct SPIRVEmitContext | |
if (mode == SpvExecutionModeMax) | ||
return; | ||
|
||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), | ||
nullptr, | ||
entryPoint, | ||
mode); | ||
requireSPIRVExecutionMode(nullptr, getID(ensureInst(entryPoint)), mode); | ||
} | ||
|
||
// Make user type name conform to `SPV_GOOGLE_user_type` spec. | ||
|
@@ -3252,14 +3249,14 @@ struct SPIRVEmitContext | |
{ | ||
case Stage::Fragment: | ||
//OpExecutionMode %main OriginUpperLeft | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, dstID, SpvExecutionModeOriginUpperLeft); | ||
requireSPIRVExecutionMode(nullptr, getID(ensureInst(entryPoint)), SpvExecutionModeOriginUpperLeft); | ||
maybeEmitEntryPointDepthReplacingExecutionMode(entryPoint, referencedBuiltinIRVars); | ||
for (auto decor : entryPoint->getDecorations()) | ||
{ | ||
switch (decor->getOp()) | ||
{ | ||
case kIROp_EarlyDepthStencilDecoration: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, dstID, SpvExecutionModeEarlyFragmentTests); | ||
requireSPIRVExecutionMode(nullptr, getID(ensureInst(entryPoint)), SpvExecutionModeEarlyFragmentTests); | ||
break; | ||
default: | ||
break; | ||
|
@@ -3293,8 +3290,6 @@ struct SPIRVEmitContext | |
// [3.6. Execution Mode]: LocalSize | ||
case kIROp_NumThreadsDecoration: | ||
{ | ||
auto section = getSection(SpvLogicalSectionID::ExecutionModes); | ||
|
||
// TODO: The `LocalSize` execution mode option requires | ||
// literal values for the X,Y,Z thread-group sizes. | ||
// There is a `LocalSizeId` variant that takes `<id>`s | ||
|
@@ -3305,10 +3300,10 @@ struct SPIRVEmitContext | |
// in those positions in the Slang IR). | ||
// | ||
auto numThreads = cast<IRNumThreadsDecoration>(decoration); | ||
emitOpExecutionModeLocalSize( | ||
section, | ||
requireSPIRVExecutionMode( | ||
decoration, | ||
dstID, | ||
SpvExecutionModeLocalSize, | ||
SpvLiteralInteger::from32(int32_t(numThreads->getX()->getValue())), | ||
SpvLiteralInteger::from32(int32_t(numThreads->getY()->getValue())), | ||
SpvLiteralInteger::from32(int32_t(numThreads->getZ()->getValue())) | ||
|
@@ -3324,8 +3319,7 @@ struct SPIRVEmitContext | |
{ | ||
auto decor = as<IRInstanceDecoration>(decoration); | ||
auto count = int32_t(getIntVal(decor->getCount())); | ||
auto section = getSection(SpvLogicalSectionID::ExecutionModes); | ||
emitOpExecutionModeInvocations(section, decoration, dstID, SpvLiteralInteger::from32(count)); | ||
requireSPIRVExecutionMode(decoration, dstID, SpvExecutionModeInvocations, SpvLiteralInteger::from32(count)); | ||
} | ||
break; | ||
case kIROp_TriangleInputPrimitiveTypeDecoration: | ||
|
@@ -3343,31 +3337,30 @@ struct SPIRVEmitContext | |
switch (inputDecor->getOp()) | ||
{ | ||
case kIROp_TriangleInputPrimitiveTypeDecoration: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeTriangles); | ||
requireSPIRVExecutionMode(inputDecor, dstID, SpvExecutionModeTriangles); | ||
break; | ||
case kIROp_LineInputPrimitiveTypeDecoration: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputLines); | ||
requireSPIRVExecutionMode(inputDecor, dstID, SpvExecutionModeInputLines); | ||
break; | ||
case kIROp_LineAdjInputPrimitiveTypeDecoration: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputLinesAdjacency); | ||
requireSPIRVExecutionMode(inputDecor, dstID, SpvExecutionModeInputLinesAdjacency); | ||
break; | ||
case kIROp_PointInputPrimitiveTypeDecoration: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputPoints); | ||
requireSPIRVExecutionMode(inputDecor, dstID, SpvExecutionModeInputPoints); | ||
break; | ||
case kIROp_TriangleAdjInputPrimitiveTypeDecoration: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), inputDecor, dstID, SpvExecutionModeInputTrianglesAdjacency); | ||
requireSPIRVExecutionMode(inputDecor, dstID, SpvExecutionModeInputTrianglesAdjacency); | ||
break; | ||
} | ||
} | ||
// SPIRV requires MaxVertexCount decoration to appear before OutputTopologyDecoration, | ||
// so we emit them here. | ||
if (auto maxVertexCount = decoration->getParent()->findDecoration<IRMaxVertexCountDecoration>()) | ||
{ | ||
auto section = getSection(SpvLogicalSectionID::ExecutionModes); | ||
emitOpExecutionModeOutputVertices( | ||
section, | ||
requireSPIRVExecutionMode( | ||
maxVertexCount, | ||
dstID, | ||
SpvExecutionModeOutputVertices, | ||
SpvLiteralInteger::from32(int32_t(getIntVal(maxVertexCount->getCount()))) | ||
); | ||
} | ||
|
@@ -3378,13 +3371,13 @@ struct SPIRVEmitContext | |
switch (type->getOp()) | ||
{ | ||
case kIROp_HLSLPointStreamType: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeOutputPoints); | ||
requireSPIRVExecutionMode(decoration, dstID, SpvExecutionModeOutputPoints); | ||
break; | ||
case kIROp_HLSLLineStreamType: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeOutputLineStrip); | ||
requireSPIRVExecutionMode(decoration, dstID, SpvExecutionModeOutputLineStrip); | ||
break; | ||
case kIROp_HLSLTriangleStreamType: | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, SpvExecutionModeOutputTriangleStrip); | ||
requireSPIRVExecutionMode(decoration, dstID, SpvExecutionModeOutputTriangleStrip); | ||
break; | ||
default: SLANG_ASSERT(!"Unknown stream out type"); | ||
} | ||
|
@@ -3433,17 +3426,17 @@ struct SPIRVEmitContext | |
: t == "point" ? SpvExecutionModeOutputPoints | ||
: SpvExecutionModeMax; | ||
SLANG_ASSERT(m != SpvExecutionModeMax); | ||
emitOpExecutionMode(getSection(SpvLogicalSectionID::ExecutionModes), decoration, dstID, m); | ||
requireSPIRVExecutionMode(decoration, dstID, m); | ||
} | ||
break; | ||
|
||
case kIROp_VerticesDecoration: | ||
{ | ||
const auto c = cast<IRVerticesDecoration>(decoration); | ||
emitOpExecutionModeOutputVertices( | ||
getSection(SpvLogicalSectionID::ExecutionModes), | ||
requireSPIRVExecutionMode( | ||
decoration, | ||
dstID, | ||
SpvExecutionModeOutputVertices, | ||
SpvLiteralInteger::from32(int32_t(c->getMaxSize()->getValue())) | ||
); | ||
} | ||
|
@@ -3452,10 +3445,10 @@ struct SPIRVEmitContext | |
case kIROp_PrimitivesDecoration: | ||
{ | ||
const auto c = cast<IRPrimitivesDecoration>(decoration); | ||
emitOpExecutionModeOutputPrimitivesEXT( | ||
getSection(SpvLogicalSectionID::ExecutionModes), | ||
requireSPIRVExecutionMode( | ||
decoration, | ||
dstID, | ||
SpvExecutionModeOutputPrimitivesEXT, | ||
SpvLiteralInteger::from32(int32_t(c->getMaxSize()->getValue())) | ||
); | ||
} | ||
|
@@ -6136,7 +6129,6 @@ struct SPIRVEmitContext | |
} | ||
|
||
OrderedHashSet<SpvCapability> m_capabilities; | ||
|
||
void requireSPIRVCapability(SpvCapability capability) | ||
{ | ||
if (m_capabilities.add(capability)) | ||
|
@@ -6149,6 +6141,37 @@ struct SPIRVEmitContext | |
} | ||
} | ||
|
||
Dictionary<SpvWord, OrderedHashSet<SpvExecutionMode>> m_executionModes; | ||
template<typename... Operands> | ||
void requireSPIRVExecutionMode(IRInst* parentInst, SpvWord entryPoint, SpvExecutionMode executionMode, const Operands& ...ops) | ||
{ | ||
if (m_executionModes[entryPoint].add(executionMode)) | ||
{ | ||
emitOpExecutionMode( | ||
getSection(SpvLogicalSectionID::ExecutionModes), | ||
parentInst, | ||
entryPoint, | ||
executionMode, | ||
ops... | ||
); | ||
|
||
} | ||
} | ||
|
||
template<typename T1, typename T2, typename T3> | ||
SpvInst* emitOpExecutionModeLocalSizeId( | ||
IRInst* inst, | ||
SpvWord entryPoint, | ||
const T1& xSize, | ||
const T2& ySize, | ||
const T3& zSize | ||
) | ||
{ | ||
static_assert(isSingular<T1>); | ||
static_assert(isSingular<T2>); | ||
static_assert(isSingular<T3>); | ||
requireSPIRVExecutionMode(inst, entryPoint, SpvExecutionModeLocalSizeId, xSize, ySize, zSize); | ||
} | ||
|
||
SPIRVEmitContext(IRModule* module, TargetProgram* program, DiagnosticSink* sink) | ||
: SPIRVEmitSharedContext(module, program, sink) | ||
, m_irModule(module) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,12 +10,12 @@ | |
// CHECK_GLSL_LINEAR_C: layout(derivative_group_linearNV) | ||
|
||
//TEST:SIMPLE(filecheck=CHECK_SPV_QUAD_C): -allow-glsl -stage compute -entry computeMain -target spirv -DQUAD -DCOMPUTE | ||
// CHECK_SPV_QUAD_C: DerivativeGroupQuadsNV | ||
// CHECK_SPV_QUAD_C: "SPV_NV_compute_shader_derivatives" | ||
// CHECK_SPV_QUAD_C-COUNT-1: DerivativeGroupQuadsNV | ||
// CHECK_SPV_QUAD_C-COUNT-1: "SPV_NV_compute_shader_derivatives" | ||
|
||
|
||
//TEST:SIMPLE(filecheck=CHECK_SPV_LINEAR_C): -allow-glsl -stage compute -entry computeMain -target spirv -DLINEAR -DCOMPUTE | ||
// CHECK_SPV_LINEAR_C: DerivativeGroupLinearNV | ||
// CHECK_SPV_LINEAR_C: "SPV_NV_compute_shader_derivatives" | ||
// CHECK_SPV_LINEAR_C-COUNT-1: DerivativeGroupLinearNV | ||
// CHECK_SPV_LINEAR_C-COUNT-1: "SPV_NV_compute_shader_derivatives" | ||
|
||
//TEST:SIMPLE(filecheck=CHECK_HLSL_C): -allow-glsl -stage compute -entry computeMain -target hlsl -DCOMPUTE | ||
// CHECK_HLSL_C: computeMain( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just do getID(entryPoint)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can make it so
getID(IRInst)
callsgetID(ensureInst(entryPoint))
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use
getIRInstSpvID
.