From 04d225ec0ff04e744cc3559966aa8260ce7f1a68 Mon Sep 17 00:00:00 2001 From: Dolkar <1105712+Dolkar@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:42:51 +0000 Subject: [PATCH 1/2] Layout fix and tests --- .../lib/SPIRV/AlignmentSizeCalculator.cpp | 3 ++ ...r.layout.hlsl => scalar.layout.array.hlsl} | 12 +++---- .../scalar.layout.struct.aligned.size.hlsl | 33 +++++++++++++++++++ .../scalar.layout.struct.array.hlsl | 29 ++++++++++++++++ .../vk.layout.cbuffer.scalar.hlsl | 20 +++++------ 5 files changed, 81 insertions(+), 16 deletions(-) rename tools/clang/test/CodeGenSPIRV/{array.scalar.layout.hlsl => scalar.layout.array.hlsl} (77%) create mode 100644 tools/clang/test/CodeGenSPIRV/scalar.layout.struct.aligned.size.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl diff --git a/tools/clang/lib/SPIRV/AlignmentSizeCalculator.cpp b/tools/clang/lib/SPIRV/AlignmentSizeCalculator.cpp index 9bb2f1b1fa..7f5914acd5 100644 --- a/tools/clang/lib/SPIRV/AlignmentSizeCalculator.cpp +++ b/tools/clang/lib/SPIRV/AlignmentSizeCalculator.cpp @@ -170,6 +170,9 @@ std::pair AlignmentSizeCalculator::getAlignmentAndSize( if (rule == SpirvLayoutRule::Scalar) { // A structure has a scalar alignment equal to the largest scalar // alignment of any of its members in VK_EXT_scalar_block_layout. + // Its size is rounded up to its final alignment for compatibility with + // C structure layout, even if not strictly necessary. + structSize = roundToPow2(structSize, maxAlignment); return {maxAlignment, structSize}; } diff --git a/tools/clang/test/CodeGenSPIRV/array.scalar.layout.hlsl b/tools/clang/test/CodeGenSPIRV/scalar.layout.array.hlsl similarity index 77% rename from tools/clang/test/CodeGenSPIRV/array.scalar.layout.hlsl rename to tools/clang/test/CodeGenSPIRV/scalar.layout.array.hlsl index 44c05bf6c1..251d55c48b 100644 --- a/tools/clang/test/CodeGenSPIRV/array.scalar.layout.hlsl +++ b/tools/clang/test/CodeGenSPIRV/scalar.layout.array.hlsl @@ -1,6 +1,6 @@ // RUN: %dxc -T cs_6_2 -E main %s -fvk-use-scalar-layout -spirv | FileCheck %s -// Check that the array stride and offsets are corrects. The uint64_t has alignment +// Check that the array stride and offsets are correct. The uint64_t has alignment // 8 and the struct has size 12. So the stride should be the smallest multiple of 8 // greater than or equal to 12, which is 16. @@ -9,13 +9,13 @@ // CHECK-DAG: OpDecorate %_runtimearr_Data ArrayStride 16 // CHECK-DAG: OpMemberDecorate %type_RWStructuredBuffer_Data 0 Offset 0 struct Data { - uint64_t y; - uint x; + uint64_t y; + uint x; }; + RWStructuredBuffer buffer; [numthreads(1, 1, 1)] -void main() -{ - buffer[0].x = 5; +void main() { + buffer[0].x = 5; } diff --git a/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.aligned.size.hlsl b/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.aligned.size.hlsl new file mode 100644 index 0000000000..40baa6361f --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.aligned.size.hlsl @@ -0,0 +1,33 @@ +// RUN: %dxc -T cs_6_2 -E main %s -fvk-use-scalar-layout -spirv | FileCheck %s + +// Check that the size of Foo and Bar gets rounded up to its alignment to follow +// C-style layout rules. See #7894 + +// CHECK-DAG: OpMemberDecorate %Foo 0 Offset 0 +// CHECK-DAG: OpMemberDecorate %Foo 1 Offset 8 +// CHECK-DAG: OpMemberDecorate %Bar 0 Offset 0 +// CHECK-DAG: OpMemberDecorate %Bar 1 Offset 16 +// CHECK-DAG: OpDecorate %_runtimearr_Bar ArrayStride 24 +// CHECK-DAG: OpMemberDecorate %type_RWStructuredBuffer_Bar 0 Offset 0 + +struct Foo { + uint64_t a; + int b; +}; + +struct Bar { + Foo foo; + int c; +}; + +RWStructuredBuffer buffer; + +[numthreads(1, 1, 1)] +void main(in uint3 threadId : SV_DispatchThreadID) { + // CHECK: [[buf_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_int %buffer %int_0 %uint_0 %int_1 + // CHECK-NEXT: OpStore [[buf_0]] %int_16 + buffer[0].c = sizeof(Foo); + // CHECK: [[buf_1:%[0-9]+]] = OpAccessChain %_ptr_Uniform_int %buffer %int_0 %uint_1 %int_1 + // CHECK-NEXT: OpStore [[buf_1]] %int_24 + buffer[1].c = sizeof(Bar); +} diff --git a/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl b/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl new file mode 100644 index 0000000000..6b53df4399 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl @@ -0,0 +1,29 @@ +// RUN: %dxc -T cs_6_2 -E main %s -fvk-use-scalar-layout -spirv | FileCheck %s + +// Check that arrays of structs respect alignment requirements. Note that this +// test does not distinguish between C-style and "strict" scalar layout. + +// CHECK-DAG: OpMemberDecorate %Foo 0 Offset 0 +// CHECK-DAG: OpMemberDecorate %Foo 1 Offset 8 +// CHECK-DAG: OpDecorate %_arr_Foo_uint_3 ArrayStride 16 +// CHECK-DAG: OpMemberDecorate %Bar 0 Offset 0 +// CHECK-DAG: OpDecorate %_runtimearr_Bar ArrayStride 56 +// CHECK-DAG: OpMemberDecorate %type_RWStructuredBuffer_Bar 0 Offset 0 + +struct Foo { + uint64_t a; + int b; +}; + +struct Bar { + Foo foo[3]; + uint64_t c; +}; + +RWStructuredBuffer buffer; + +[numthreads(1, 1, 1)] void main() { + // CHECK: [[buf_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_ulong %buffer %int_0 %uint_0 %int_1 + // CHECK-NEXT: OpStore [[buf_0]] %ulong_56 + buffer[0].c = sizeof(Bar); +} \ No newline at end of file diff --git a/tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.scalar.hlsl b/tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.scalar.hlsl index 0de791fbd4..82a15569c3 100644 --- a/tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.scalar.hlsl +++ b/tools/clang/test/CodeGenSPIRV/vk.layout.cbuffer.scalar.hlsl @@ -9,16 +9,16 @@ struct S { // Alignment Offset Size float sf2; // 4 -> 8 + 4 = 12 float3 sf3; // 4 -> 12 + 4 * 3 = 24 float sf4; // 4 -> 24 + 4 = 28 -}; // 8(max) 28 +}; // 8(max) 32 (size rounded up to alignment) struct T { // Alignment Offset Size = Next int tf1; // 4 -> 0 + 4 = 4 R tf2[3]; // 8 -> 8 (4 round up to R alignment) + 3 * stride(8) = 32 float3x2 tf3; // 4 -> 32 + 4 * 3 * 2 = 56 - S tf4; // 8 -> 56 + 28 = 84 - float16_t tf5; // 2 -> 84 + 2 = 86 - float tf6; // 4 -> 88 (86 round up to float align) + 4 = 92 -}; // 8(max) 92 + S tf4; // 8 -> 56 + 32 = 88 + float16_t tf5; // 2 -> 88 + 2 = 90 + float tf6; // 4 -> 92 (90 round up to float align) + 4 = 96 +}; // 8(max) 96 cbuffer MyCBuffer { // Alignment Offset Size Next bool a; // 4 -> 0 + 4 = 4 @@ -29,8 +29,8 @@ cbuffer MyCBuffer { // Alignment Offset float2x1 f; // 4 -> 68 + 4 * 2 = 76 row_major float2x3 g[3]; // 4 -> 76 + 4 * 2 * 3 * 3 = 148 column_major float2x2 h[4]; // 4 -> 148 + 4 * 2 * 2 * 4 = 212 - T t; // 8 -> 216 (212 round up to T alignment) + 92 = 308 - float z; // 4 -> 308 + T t; // 8 -> 216 (212 round up to T alignment) + 96 = 312 + float z; // 4 -> 312 }; // CHECK: OpDecorate %_arr_mat2v3float_uint_3 ArrayStride 24 @@ -51,8 +51,8 @@ cbuffer MyCBuffer { // Alignment Offset // CHECK-NEXT: OpMemberDecorate %T 2 MatrixStride 12 // CHECK-NEXT: OpMemberDecorate %T 2 RowMajor // CHECK-NEXT: OpMemberDecorate %T 3 Offset 56 -// CHECK-NEXT: OpMemberDecorate %T 4 Offset 84 -// CHECK-NEXT: OpMemberDecorate %T 5 Offset 88 +// CHECK-NEXT: OpMemberDecorate %T 4 Offset 88 +// CHECK-NEXT: OpMemberDecorate %T 5 Offset 92 // CHECK: OpMemberDecorate %type_MyCBuffer 0 Offset 0 // CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 1 Offset 4 @@ -71,7 +71,7 @@ cbuffer MyCBuffer { // Alignment Offset // CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 7 MatrixStride 8 // CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 7 RowMajor // CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 8 Offset 216 -// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 9 Offset 308 +// CHECK-NEXT: OpMemberDecorate %type_MyCBuffer 9 Offset 312 // CHECK-NEXT: OpDecorate %type_MyCBuffer Block float main() : A { From e642c97acb9f16a4e3f8835ee2a6c3f328c68498 Mon Sep 17 00:00:00 2001 From: Dolkar <1105712+Dolkar@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:39:33 +0000 Subject: [PATCH 2/2] Added trailing newline to scalar.layout.struct.array.hlsl --- tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl b/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl index 6b53df4399..892534f150 100644 --- a/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl +++ b/tools/clang/test/CodeGenSPIRV/scalar.layout.struct.array.hlsl @@ -26,4 +26,4 @@ RWStructuredBuffer buffer; // CHECK: [[buf_0:%[0-9]+]] = OpAccessChain %_ptr_Uniform_ulong %buffer %int_0 %uint_0 %int_1 // CHECK-NEXT: OpStore [[buf_0]] %ulong_56 buffer[0].c = sizeof(Bar); -} \ No newline at end of file +}