Skip to content

Commit c72be81

Browse files
authored
[SPIRV] Round the stride to be a multiple of the alignment. (microsoft#6967)
We currently pick the size of a struct to be the stride of the array elements when doing scalar layout. This is not correct because this could cause the struct to not be correctly aligned. This is fixed by rounding the size of the struct up to a mutliple of the alignment. Fixes microsoft#6947
1 parent 16e6727 commit c72be81

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

tools/clang/lib/SPIRV/AlignmentSizeCalculator.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ inline uint32_t roundToPow2(uint32_t val, uint32_t pow2) {
2222
return (val + pow2 - 1) & ~(pow2 - 1);
2323
}
2424

25+
/// Returns the smallest value greater than or equal to |val| that is a multiple
26+
/// of |multiple|.
27+
inline uint32_t roundToMultiple(uint32_t val, uint32_t multiple) {
28+
if (val == 0)
29+
return 0;
30+
uint32_t t = (val - 1) / multiple;
31+
return (multiple * (t + 1));
32+
}
33+
2534
/// Returns true if the given vector type (of the given size) crosses the
2635
/// 4-component vector boundary if placed at the given offset.
2736
bool improperStraddle(clang::QualType type, int size, int offset) {
@@ -411,7 +420,7 @@ std::pair<uint32_t, uint32_t> AlignmentSizeCalculator::getAlignmentAndSize(
411420

412421
if (rule == SpirvLayoutRule::FxcSBuffer ||
413422
rule == SpirvLayoutRule::Scalar) {
414-
*stride = size;
423+
*stride = roundToMultiple(size, alignment);
415424
// Use element alignment for fxc structured buffers and
416425
// VK_EXT_scalar_block_layout
417426
return {alignment, size * elemCount};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %dxc -T cs_6_2 -E main %s -fvk-use-scalar-layout -spirv | FileCheck %s
2+
3+
// Check that the array stride and offsets are corrects. The uint64_t has alignment
4+
// 8 and the struct has size 12. So the stride should be the smallest multiple of 8
5+
// greater than or equal to 12, which is 16.
6+
7+
// CHECK-DAG: OpMemberDecorate %Data 0 Offset 0
8+
// CHECK-DAG: OpMemberDecorate %Data 1 Offset 8
9+
// CHECK-DAG: OpDecorate %_runtimearr_Data ArrayStride 16
10+
// CHECK-DAG: OpMemberDecorate %type_RWStructuredBuffer_Data 0 Offset 0
11+
struct Data {
12+
uint64_t y;
13+
uint x;
14+
};
15+
RWStructuredBuffer<Data> buffer;
16+
17+
[numthreads(1, 1, 1)]
18+
void main()
19+
{
20+
buffer[0].x = 5;
21+
}

0 commit comments

Comments
 (0)