Skip to content

Commit 15c8723

Browse files
authored
Generate counter for arrays of RW, consume, and append structured buffers. (#5415)
This commit adds code to generate counters for single dimensional arrays of RW,consume, and append structured buffers. After this commit, the counter can be used if the global resource is used directly.
1 parent af0b809 commit 15c8723

12 files changed

Lines changed: 221 additions & 10 deletions

tools/clang/lib/SPIRV/AstTypeProbe.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,10 @@ bool isRWByteAddressBuffer(QualType type) {
946946
}
947947

948948
bool isAppendStructuredBuffer(QualType type) {
949+
// Strip outer arrayness first
950+
while (type->isArrayType())
951+
type = type->getAsArrayTypeUnsafe()->getElementType();
952+
949953
const auto *recordType = type->getAs<RecordType>();
950954
if (!recordType)
951955
return false;
@@ -954,6 +958,10 @@ bool isAppendStructuredBuffer(QualType type) {
954958
}
955959

956960
bool isConsumeStructuredBuffer(QualType type) {
961+
// Strip outer arrayness first
962+
while (type->isArrayType())
963+
type = type->getAsArrayTypeUnsafe()->getElementType();
964+
957965
const auto *recordType = type->getAs<RecordType>();
958966
if (!recordType)
959967
return false;
@@ -962,6 +970,10 @@ bool isConsumeStructuredBuffer(QualType type) {
962970
}
963971

964972
bool isRWStructuredBuffer(QualType type) {
973+
// Strip outer arrayness first
974+
while (type->isArrayType())
975+
type = type->getAsArrayTypeUnsafe()->getElementType();
976+
965977
if (const RecordType *recordType = type->getAs<RecordType>()) {
966978
StringRef name = recordType->getDecl()->getName();
967979
return name == "RWStructuredBuffer";
@@ -970,12 +982,7 @@ bool isRWStructuredBuffer(QualType type) {
970982
}
971983

972984
bool isRWAppendConsumeSBuffer(QualType type) {
973-
if (const RecordType *recordType = type->getAs<RecordType>()) {
974-
StringRef name = recordType->getDecl()->getName();
975-
return name == "RWStructuredBuffer" || name == "AppendStructuredBuffer" ||
976-
name == "ConsumeStructuredBuffer";
977-
}
978-
return false;
985+
return isRWStructuredBuffer(type) || isConsumeStructuredBuffer(type) || isAppendStructuredBuffer(type);
979986
}
980987

981988
bool isAKindOfStructuredOrByteBuffer(QualType type) {

tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,6 +1687,21 @@ void DeclResultIdMapper::createCounterVar(
16871687
}
16881688

16891689
const SpirvType *counterType = spvContext.getACSBufferCounterType();
1690+
QualType declType = decl->getType();
1691+
if (declType->isArrayType()) {
1692+
// TODO(5440): This codes does not handle multi-dimensional arrays. We need
1693+
// to look at specific example to determine the best way to do it.
1694+
uint32_t arrayStride = 4;
1695+
if (const auto *constArrayType =
1696+
astContext.getAsConstantArrayType(declType)) {
1697+
counterType = spvContext.getArrayType(
1698+
counterType, constArrayType->getSize().getZExtValue(), arrayStride);
1699+
} else {
1700+
assert(declType->isIncompleteArrayType());
1701+
counterType = spvContext.getRuntimeArrayType(counterType, arrayStride);
1702+
}
1703+
}
1704+
16901705
// {RW|Append|Consume}StructuredBuffer are all in Uniform storage class.
16911706
// Alias counter variables should be created into the Private storage class.
16921707
const spv::StorageClass sc =

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ const DeclaratorDecl *getReferencedDef(const Expr *expr) {
323323
return nullptr;
324324

325325
expr = expr->IgnoreParenCasts();
326+
while(const auto *arraySubscriptExpr = dyn_cast<ArraySubscriptExpr>(expr)) {
327+
expr = arraySubscriptExpr->getBase();
328+
expr = expr->IgnoreParenCasts();
329+
}
326330

327331
if (const auto *declRefExpr = dyn_cast<DeclRefExpr>(expr)) {
328332
return dyn_cast_or_null<DeclaratorDecl>(declRefExpr->getDecl());
@@ -4542,8 +4546,18 @@ SpirvEmitter::incDecRWACSBufferCounter(const CXXMemberCallExpr *expr,
45424546
return nullptr;
45434547
}
45444548

4549+
llvm::SmallVector<SpirvInstruction *, 2> indexes;
4550+
if(const auto *arraySubscriptExpr = dyn_cast<ArraySubscriptExpr>(object)) {
4551+
// TODO(5440): This codes does not handle multi-dimensional arrays. We need
4552+
// to look at specific example to determine the best way to do it.
4553+
indexes.push_back(doExpr(arraySubscriptExpr->getIdx()));
4554+
}
4555+
4556+
// Add an extra 0 because the counter is wrapped in a struct.
4557+
indexes.push_back(zero);
4558+
45454559
auto *counterPtr = spvBuilder.createAccessChain(
4546-
astContext.IntTy, counterPair->get(spvBuilder, spvContext), {zero},
4560+
astContext.IntTy, counterPair->get(spvBuilder, spvContext), indexes,
45474561
srcLoc, srcRange);
45484562

45494563
SpirvInstruction *index = nullptr;

tools/clang/test/CodeGenSPIRV/type.append-structured-buffer.array.hlsl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ struct T {
55
float3 b;
66
};
77

8-
// CHECK: %myAppendStructuredBuffer = OpVariable %_ptr_Uniform__runtimearr_type_AppendStructuredBuffer_T Uniform
9-
AppendStructuredBuffer<T> myAppendStructuredBuffer[];
8+
// CHECK: OpDecorate %myAppendStructuredBuffer DescriptorSet 0
9+
// CHECK: OpDecorate %myAppendStructuredBuffer Binding 0
10+
// CHECK: OpDecorate %counter_var_myAppendStructuredBuffer DescriptorSet 0
11+
// CHECK: OpDecorate %counter_var_myAppendStructuredBuffer Binding 1
12+
13+
// CHECK: %myAppendStructuredBuffer = OpVariable %_ptr_Uniform__arr_type_AppendStructuredBuffer_T_uint_5 Uniform
14+
// CHECK: %counter_var_myAppendStructuredBuffer = OpVariable %_ptr_Uniform__arr_type_ACSBuffer_counter_uint_5 Uniform
15+
AppendStructuredBuffer<T> myAppendStructuredBuffer[5];
1016

1117
void main() {}
1218

tools/clang/test/CodeGenSPIRV/type.consume-structured-buffer.array.hlsl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ struct T {
55
float3 b;
66
};
77

8+
// CHECK: OpDecorate %myConsumeStructuredBuffer DescriptorSet 0
9+
// CHECK: OpDecorate %myConsumeStructuredBuffer Binding 0
10+
// CHECK: OpDecorate %counter_var_myConsumeStructuredBuffer DescriptorSet 0
11+
// CHECK: OpDecorate %counter_var_myConsumeStructuredBuffer Binding 1
812

913
// CHECK: %myConsumeStructuredBuffer = OpVariable %_ptr_Uniform__arr_type_ConsumeStructuredBuffer_T_uint_2 Uniform
14+
// CHECK: %counter_var_myConsumeStructuredBuffer = OpVariable %_ptr_Uniform__arr_type_ACSBuffer_counter_uint_2 Uniform
1015
ConsumeStructuredBuffer<T> myConsumeStructuredBuffer[2];
1116

1217
void main() {}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %dxc -T ps_6_6 -E main -fvk-allow-rwstructuredbuffer-arrays
2+
3+
struct PSInput
4+
{
5+
uint idx : COLOR;
6+
};
7+
8+
// CHECK: OpDecorate %g_rwbuffer DescriptorSet 2
9+
// CHECK: OpDecorate %g_rwbuffer Binding 0
10+
// CHECK: OpDecorate %counter_var_g_rwbuffer DescriptorSet 2
11+
// CHECK: OpDecorate %counter_var_g_rwbuffer Binding 1
12+
13+
// CHECK: %g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_RWStructuredBuffer_uint_uint_5 Uniform
14+
// CHECK: %counter_var_g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_ACSBuffer_counter_uint_5 Uniform
15+
RWStructuredBuffer<uint> g_rwbuffer[5] : register(u0, space2);
16+
17+
float4 main(PSInput input) : SV_TARGET
18+
{
19+
// Correctly increment the counter.
20+
// CHECK: [[ac:%\d+]] = OpAccessChain %_ptr_Uniform_int %counter_var_g_rwbuffer %int_3 %uint_0
21+
// CHECK: OpAtomicIAdd %int [[ac]] %uint_1 %uint_0 %int_1
22+
g_rwbuffer[3].IncrementCounter();
23+
24+
// Correctly access the buffer.
25+
// CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer %int_2
26+
// CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_uint [[ac1]] %int_0 %uint_0
27+
// CHECK: OpLoad %uint [[ac2]]
28+
return g_rwbuffer[2][0];
29+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %dxc -T ps_6_6 -E main -fspv-flatten-resource-arrays -fvk-allow-rwstructuredbuffer-arrays
2+
3+
// TODO: This test should add `-O0` to make sure that the resource arrays are correctly flattened.
4+
// DXC is currently generating the correct code, but the spirv-tools passes are failing on the counter
5+
// array.
6+
7+
struct PSInput
8+
{
9+
uint idx : COLOR;
10+
};
11+
12+
// CHECK: OpDecorate %g_rwbuffer DescriptorSet 2
13+
// CHECK: OpDecorate %g_rwbuffer Binding 0
14+
// CHECK: OpDecorate %counter_var_g_rwbuffer DescriptorSet 2
15+
// CHECK: OpDecorate %counter_var_g_rwbuffer Binding 5
16+
17+
// CHECK: %g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_RWStructuredBuffer_uint_uint_5 Uniform
18+
// CHECK: %counter_var_g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_ACSBuffer_counter_uint_5 Uniform
19+
RWStructuredBuffer<uint> g_rwbuffer[5] : register(u0, space2);
20+
21+
float4 main(PSInput input) : SV_TARGET
22+
{
23+
// Correctly increment the counter.
24+
// CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform_int %counter_var_g_rwbuffer {{%\d+}} %uint_0
25+
// CHECK: OpAtomicIAdd %int [[ac]] %uint_1 %uint_0 %int_1
26+
g_rwbuffer[input.idx].IncrementCounter();
27+
28+
// Correctly access the buffer.
29+
// CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer {{%\d+}}
30+
// CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_uint [[ac1]] %int_0 %uint_0
31+
// CHECK: OpLoad %uint [[ac2]]
32+
return g_rwbuffer[input.idx][0];
33+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %dxc -T ps_6_6 -E main -fvk-allow-rwstructuredbuffer-arrays
2+
3+
struct PSInput
4+
{
5+
uint idx : COLOR;
6+
};
7+
8+
// CHECK: OpDecorate %g_rwbuffer DescriptorSet 2
9+
// CHECK: OpDecorate %g_rwbuffer Binding 0
10+
// CHECK: OpDecorate %counter_var_g_rwbuffer DescriptorSet 2
11+
// CHECK: OpDecorate %counter_var_g_rwbuffer Binding 1
12+
13+
// CHECK: %g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_RWStructuredBuffer_uint_uint_5 Uniform
14+
// CHECK: %counter_var_g_rwbuffer = OpVariable %_ptr_Uniform__arr_type_ACSBuffer_counter_uint_5 Uniform
15+
RWStructuredBuffer<uint> g_rwbuffer[5] : register(u0, space2);
16+
17+
float4 main(PSInput input) : SV_TARGET
18+
{
19+
// Correctly increment the counter.
20+
// CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Uniform_int %counter_var_g_rwbuffer {{%\d+}} %uint_0
21+
// CHECK: OpAtomicIAdd %int [[ac]] %uint_1 %uint_0 %int_1
22+
g_rwbuffer[input.idx].IncrementCounter();
23+
24+
// Correctly access the buffer.
25+
// CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer {{%\d+}}
26+
// CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_uint [[ac1]] %int_0 %uint_0
27+
// CHECK: OpLoad %uint [[ac2]]
28+
return g_rwbuffer[input.idx][0];
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %dxc -T ps_6_6 -E main -fspv-flatten-resource-arrays -O0 -fvk-allow-rwstructuredbuffer-arrays
2+
3+
struct PSInput
4+
{
5+
uint idx : COLOR;
6+
};
7+
8+
// CHECK: OpDecorate %g_rwbuffer_0_ DescriptorSet 2
9+
// CHECK: OpDecorate %g_rwbuffer_0_ Binding 0
10+
// CHECK: OpDecorate %g_rwbuffer_1_ DescriptorSet 2
11+
// CHECK: OpDecorate %g_rwbuffer_1_ Binding 1
12+
// CHECK: OpDecorate %g_rwbuffer_2_ DescriptorSet 2
13+
// CHECK: OpDecorate %g_rwbuffer_2_ Binding 2
14+
// CHECK: OpDecorate %g_rwbuffer_3_ DescriptorSet 2
15+
// CHECK: OpDecorate %g_rwbuffer_3_ Binding 3
16+
// CHECK: OpDecorate %g_rwbuffer_4_ DescriptorSet 2
17+
// CHECK: OpDecorate %g_rwbuffer_4_ Binding 4
18+
19+
// CHECK: %g_rwbuffer_0_ = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
20+
// CHECK: %g_rwbuffer_1_ = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
21+
// CHECK: %g_rwbuffer_2_ = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
22+
// CHECK: %g_rwbuffer_3_ = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
23+
// CHECK: %g_rwbuffer_4_ = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform
24+
RWStructuredBuffer<uint> g_rwbuffer[5] : register(u0, space2);
25+
26+
float4 main(PSInput input) : SV_TARGET
27+
{
28+
return g_rwbuffer[input.idx][0];
29+
}

tools/clang/test/CodeGenSPIRV/type.rwstructured-buffer.array.nocounter.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ RWStructuredBuffer<uint> g_rwbuffer[5] : register(u0, space2);
1212

1313
float4 main(PSInput input) : SV_TARGET
1414
{
15-
// CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer %35
15+
// CHECK: [[ac1:%\w+]] = OpAccessChain %_ptr_Uniform_type_RWStructuredBuffer_uint %g_rwbuffer {{%\d+}}
1616
// CHECK: [[ac2:%\w+]] = OpAccessChain %_ptr_Uniform_uint [[ac1]] %int_0 %uint_0
1717
// CHECK: OpLoad %uint [[ac2]]
1818
return g_rwbuffer[input.idx][0];

0 commit comments

Comments
 (0)