Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions tools/clang/lib/SPIRV/DeclResultIdMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
QualType arrayType = astContext.getConstantArrayType(
type, llvm::APInt(32, arraySize), clang::ArrayType::Normal, 0);

stageVarInstructions[cast<DeclaratorDecl>(decl)] =
msOutIndicesBuiltin =
getBuiltinVar(builtinID, arrayType, decl->getLocation());
} else {
// For NV_mesh_shader, the built type is PrimitiveIndicesNV
Expand All @@ -871,7 +871,7 @@ bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
astContext.UnsignedIntTy, llvm::APInt(32, arraySize),
clang::ArrayType::Normal, 0);

stageVarInstructions[cast<DeclaratorDecl>(decl)] =
msOutIndicesBuiltin =
getBuiltinVar(builtinID, arrayType, decl->getLocation());
}

Expand Down
24 changes: 24 additions & 0 deletions tools/clang/lib/SPIRV/DeclResultIdMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,11 @@ class DeclResultIdMapper {
return value;
}

SpirvVariable *getMSOutIndicesBuiltin() {
assert(msOutIndicesBuiltin && "Variable usage before decl parsing.");
return msOutIndicesBuiltin;
}

/// Decorate with spirv intrinsic attributes with lamda function variable
/// check
void decorateWithIntrinsicAttrs(
Expand Down Expand Up @@ -1014,6 +1019,25 @@ class DeclResultIdMapper {
/// creating that stage variable, so that we don't need to query them again
/// for reading and writing.
llvm::DenseMap<const ValueDecl *, SpirvVariable *> stageVarInstructions;

/// Special case for the Indices builtin:
/// - this builtin has a different layout in HLSL & SPIR-V, meaning it
/// requires
/// the same kind of handling as classic stageVarInstructions:
/// -> load into a HLSL compatible tmp
/// -> write back into the SPIR-V compatible layout.
/// - but the builtin is shared across invocations (not only lanes).
/// -> we must only write/read from the indices requested by the user.
/// - the variable can be passed to other functions as a out param
/// -> we cannot copy-in/copy-out because shared across invocations.
/// -> we cannot pass a simple pointer: layout differences between
/// HLSL/SPIR-V.
///
/// All this means we must keep track of the builtin, and each assignment to
/// this will have to handle the layout differences. The easiest solution is
/// to keep this builtin global to the module if present.
SpirvVariable *msOutIndicesBuiltin = nullptr;

/// Vector of all defined resource variables.
llvm::SmallVector<ResourceVar, 8> resourceVars;
/// Mapping from {RW|Append|Consume}StructuredBuffers to their
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/lib/SPIRV/SpirvEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8128,7 +8128,7 @@ void SpirvEmitter::assignToMSOutIndices(
if (indices.size() > 1) {
vecComponent = indices.back();
}
auto *var = declIdMapper.getStageVarInstruction(decl);
auto *var = declIdMapper.getMSOutIndicesBuiltin();
Comment thread
Keenuts marked this conversation as resolved.
Outdated
const auto *varTypeDecl = astContext.getAsConstantArrayType(decl->getType());
Comment thread
s-perron marked this conversation as resolved.
Outdated
QualType varType = varTypeDecl->getElementType();
uint32_t numVertices = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// RUN: %dxc -T ms_6_5 -E outie -fcgl %s -spirv | FileCheck %s
// RUN: %dxc -T ms_6_5 -E innie -fcgl %s -spirv | FileCheck %s

// CHECK-DAG: [[v4_n05_05_0_1:%[0-9]+]] = OpConstantComposite %v4float %float_n0_5 %float_0_5 %float_0 %float_1
// CHECK-DAG: [[v4_05_05_0_1:%[0-9]+]] = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0 %float_1
// CHECK-DAG: [[v4_0_n05_0_1:%[0-9]+]] = OpConstantComposite %v4float %float_0 %float_n0_5 %float_0 %float_1
// CHECK-DAG: [[v3_1_0_0:%[0-9]+]] = OpConstantComposite %v3float %float_1 %float_0 %float_0
// CHECK-DAG: [[v3_0_1_0:%[0-9]+]] = OpConstantComposite %v3float %float_0 %float_1 %float_0
// CHECK-DAG: [[v3_0_0_1:%[0-9]+]] = OpConstantComposite %v3float %float_0 %float_0 %float_1
// CHECK-DAG: [[u3_0_1_2:%[0-9]+]] = OpConstantComposite %v3uint %uint_0 %uint_1 %uint_2

// CHECK-DAG: OpDecorate [[indices:%[0-9]+]] BuiltIn PrimitiveIndicesNV

struct MeshOutput {
float4 position : SV_Position;
float3 color : COLOR0;
};

[outputtopology("triangle")]
[numthreads(1, 1, 1)]
void innie(out indices uint3 triangles[1], out vertices MeshOutput verts[3]) {
SetMeshOutputCounts(3, 2);

triangles[0] = uint3(0, 1, 2);
// CHECK: [[off:%[0-9]+]] = OpIMul %uint %uint_0 %uint_3
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_uint [[indices]] [[off]]
// CHECK: [[tmp:%[0-9]+]] = OpCompositeExtract %uint [[u3_0_1_2]] 0
// CHECK: OpStore [[ptr]] [[tmp]]
// CHECK: [[idx:%[0-9]+]] = OpIAdd %uint [[off]] %uint_1
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_uint [[indices]] [[idx]]
// CHECK: [[tmp:%[0-9]+]] = OpCompositeExtract %uint [[u3_0_1_2]] 1
// CHECK: OpStore [[ptr]] [[tmp]]
// CHECK: [[idx:%[0-9]+]] = OpIAdd %uint [[off]] %uint_2
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_uint [[indices]] [[idx]]
// CHECK: [[tmp:%[0-9]+]] = OpCompositeExtract %uint [[u3_0_1_2]] 2
// CHECK: OpStore [[ptr]] [[tmp]]

verts[0].position = float4(-0.5, 0.5, 0.0, 1.0);
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_v4float %gl_Position %int_0
// CHECK: OpStore [[ptr]] [[v4_n05_05_0_1]]
verts[0].color = float3(1.0, 0.0, 0.0);
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_v3float %out_var_COLOR0 %int_0
// CHECK: OpStore [[ptr]] [[v3_1_0_0]]

verts[1].position = float4(0.5, 0.5, 0.0, 1.0);
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_v4float %gl_Position %int_1
// CHECK: OpStore [[ptr]] [[v4_05_05_0_1]]
verts[1].color = float3(0.0, 1.0, 0.0);
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_v3float %out_var_COLOR0 %int_1
// CHECK: OpStore [[ptr]] [[v3_0_1_0]]

verts[2].position = float4(0.0, -0.5, 0.0, 1.0);
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_v4float %gl_Position %int_2
// CHECK: OpStore [[ptr]] [[v4_0_n05_0_1]]
verts[2].color = float3(0.0, 0.0, 1.0);
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Output_v3float %out_var_COLOR0 %int_2
// CHECK: OpStore [[ptr]] [[v3_0_0_1]]

}

[outputtopology("triangle")]
[numthreads(1, 1, 1)]
void outie(out indices uint3 triangles[1], out vertices MeshOutput verts[3]) {
innie(triangles, verts);
}