summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPankaj Mistry <63069047+pmistryNV@users.noreply.github.com>2024-04-05 14:52:50 -0700
committerGitHub <noreply@github.com>2024-04-05 14:52:50 -0700
commitd61f81374272c2abc34eecab19e916b979b08a55 (patch)
tree268b99642f3674a9d35a54bc8a9ff05bfa8a0c4b
parentcb87a8f1665198660636188e0861cd41bdaef16c (diff)
Add decoration PerPrimitiveEXT when a mesh output variable is decorated with PrimitiveID (#3895)
Fixes bug 3872
-rw-r--r--source/slang/slang-emit-spirv.cpp16
-rw-r--r--tests/pipeline/rasterization/mesh/mesh-PerPrimitiveEXT.slang44
2 files changed, 58 insertions, 2 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index 942e089db..9f116a1e2 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -3827,6 +3827,7 @@ struct SPIRVEmitContext
// non-tessellation shader stages, and if so include a declaration of
// Geometry capability.
bool needGeometryCapability = true;
+ bool needPerPrimitiveEXTDecoration = false;
if (entryPoints)
{
for (auto entryPoint : *entryPoints)
@@ -3835,9 +3836,13 @@ struct SPIRVEmitContext
{
switch (entryPointDecor->getProfile().getStage())
{
+ case Stage::Mesh:
+ // For outputs decorated with PrimitiveID it must be decorated
+ // with PerPrimitiveEXT to comply with Vulkan validation rules
+ if (m_capabilities.contains(SpvCapabilityMeshShadingEXT))
+ needPerPrimitiveEXTDecoration = true;
case Stage::Geometry:
case Stage::Intersection:
- case Stage::Mesh:
case Stage::Amplification:
case Stage::AnyHit:
case Stage::ClosestHit:
@@ -3851,7 +3856,14 @@ struct SPIRVEmitContext
}
if (needGeometryCapability)
requireSPIRVCapability(SpvCapabilityGeometry);
- return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInPrimitiveId);
+ auto varInst = getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInPrimitiveId);
+ if (needPerPrimitiveEXTDecoration)
+ emitOpDecorate(
+ getSection(SpvLogicalSectionID::Annotations),
+ nullptr,
+ varInst,
+ SpvDecorationPerPrimitiveEXT);
+ return varInst;
}
else if (semanticName == "sv_rendertargetarrayindex")
{
diff --git a/tests/pipeline/rasterization/mesh/mesh-PerPrimitiveEXT.slang b/tests/pipeline/rasterization/mesh/mesh-PerPrimitiveEXT.slang
new file mode 100644
index 000000000..bf46cce63
--- /dev/null
+++ b/tests/pipeline/rasterization/mesh/mesh-PerPrimitiveEXT.slang
@@ -0,0 +1,44 @@
+// Test that a mesh shader generates PerPrimitiveNV decoration for OutputPrimitives
+//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage mesh -emit-spirv-directly
+
+// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
+// CHECK: OpDecorate %gl_PrimitiveID PerPrimitiveNV
+
+const static let color: float3[] = {
+ float3(1.0, 0.0, 0.0),
+ float3(0.0, 1.0, 0.0),
+ float3(0.0, 0.0, 1.0),
+};
+
+const static let position: float3[] = {
+ float3( 0.5, 0.5, 0.0),
+ float3( 0.0, -0.5, 0.0),
+ float3(-0.5, 0.5, 0.0),
+};
+
+struct SVertexOutput {
+ float4 Position: SV_Position;
+ float3 Color;
+};
+
+struct SPrimitiveOutput {
+ uint PrimitiveId: SV_PrimitiveID;
+};
+
+[shader("mesh")]
+[numthreads(1, 1, 1)]
+[outputtopology("triangle")]
+func main(
+ OutputVertices<SVertexOutput, 3> outputVertices,
+ OutputPrimitives<SPrimitiveOutput, 1> outputPrimitives,
+ OutputIndices<uint3, 1> outputIndices,
+) -> void {
+ SetMeshOutputCounts(3, 1);
+ outputVertices[0] = { float4(position[0], 1.0), color[0] };
+ outputVertices[1] = { float4(position[1], 1.0), color[1] };
+ outputVertices[2] = { float4(position[2], 1.0), color[2] };
+ outputIndices[0] = uint3(0, 1, 2);
+
+ outputPrimitives[0] = { 0 };
+}
+