Skip to content

Commit 661d444

Browse files
authored
[SPIRV] Cast SV_CULLPRIMITIVE to uint (microsoft#6297)
When SV_CULLPRIMITIVE is the output of a mesh shader, its type is changed to uint because a Vulkan interface variable cannot be a bool. However, we do not change the access to the variable to match. This change will modify stores to the variable to be stores of a uint instead of a bool. Fixes microsoft#6042
1 parent 446da19 commit 661d444

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7677,16 +7677,24 @@ void SpirvEmitter::assignToMSOutAttribute(
76777677
assert(semanticInfo.isValid());
76787678
const auto loc = decl->getLocation();
76797679
// Special handle writes to clip/cull distance attributes.
7680-
if (!declIdMapper.glPerVertex.tryToAccess(
7680+
if (declIdMapper.glPerVertex.tryToAccess(
76817681
hlsl::DXIL::SigPointKind::MSOut, semanticInfo.semantic->GetKind(),
76827682
semanticInfo.index, attrIndex, &value, /*noWriteBack=*/false,
76837683
vecComponent, loc)) {
7684-
// All other attribute writes are handled below.
7685-
auto *varInstr = declIdMapper.getStageVarInstruction(decl);
7686-
QualType valueType = value->getAstResultType();
7687-
varInstr = spvBuilder.createAccessChain(valueType, varInstr, indices, loc);
7688-
spvBuilder.createStore(varInstr, value, loc);
7684+
return;
76897685
}
7686+
7687+
// All other attribute writes are handled below.
7688+
auto *varInstr = declIdMapper.getStageVarInstruction(decl);
7689+
QualType valueType = value->getAstResultType();
7690+
if (valueType->isBooleanType()) {
7691+
// Externally visible variables are changed to uint, so we need to cast the
7692+
// value to uint.
7693+
value = castToInt(value, valueType, astContext.UnsignedIntTy, loc);
7694+
valueType = astContext.UnsignedIntTy;
7695+
}
7696+
varInstr = spvBuilder.createAccessChain(valueType, varInstr, indices, loc);
7697+
spvBuilder.createStore(varInstr, value, loc);
76907698
}
76917699

76927700
void SpirvEmitter::assignToMSOutIndices(
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %dxc -T ms_6_6 -fspv-target-env=vulkan1.1spirv1.4 -E main %s -spirv | FileCheck %s
2+
3+
struct MeshletPrimitiveOut
4+
{
5+
bool m_cullPrimitive : SV_CULLPRIMITIVE;
6+
};
7+
8+
// m_cullPrimitive will have to be turned into a uint because of the Vulkan
9+
// specification says that externally visible variables cannot be bool.
10+
// CHECK: OpDecorate [[var:%[0-9]+]] BuiltIn CullPrimitiveEXT
11+
// CHECK: OpDecorate [[var]] PerPrimitiveNV
12+
// CHECK: [[var]] = OpVariable %_ptr_Output__arr_uint_uint_2 Output
13+
14+
struct VertOut
15+
{
16+
float4 m_svPosition : SV_POSITION;
17+
};
18+
19+
#define SIZE 2
20+
21+
[numthreads(SIZE, 1, 1)] [outputtopology("triangle")]
22+
void main(uint svGroupIndex : SV_GROUPINDEX,
23+
out vertices VertOut verts[SIZE],
24+
out indices uint3 indices[SIZE],
25+
out primitives MeshletPrimitiveOut primitives[SIZE])
26+
{
27+
SetMeshOutputCounts(SIZE, SIZE);
28+
29+
// Make sure that the references to m_cullPrimitive use uints.
30+
// CHECK: [[idx:%[0-9]+]] = OpLoad %uint %gl_LocalInvocationIndex
31+
// CHECK: [[ac:%[0-9]+]] = OpAccessChain %_ptr_Output_uint [[var]] [[idx]]
32+
// CHECK: OpStore [[ac]] %uint_0
33+
primitives[svGroupIndex].m_cullPrimitive = false;
34+
}

0 commit comments

Comments
 (0)