Skip to content

Commit bebfc20

Browse files
committed
[hlsl][Sema] Fix Struct Size Calculation containing 16 and 32 bit wide scalars
1 parent 5981335 commit bebfc20

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,26 @@ Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
172172
return Result;
173173
}
174174

175+
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context,
176+
QualType T) {
177+
// Aggregate types are always aligned to new buffer rows
178+
if (T->isAggregateType())
179+
return 16;
180+
181+
assert(Context.getTypeSize(T) <= 64 && "Scalar bit widths larger than 64 not supported");
182+
183+
// 64 bit types such as double and uint64_t align to 8 bytes
184+
if (Context.getTypeSize(T) == 64)
185+
return 8;
186+
187+
// Half types align to 2 bytes only if native half is available
188+
if (T->isHalfType() && Context.getLangOpts().NativeHalfType)
189+
return 2;
190+
191+
// Everything else aligns to 4 bytes
192+
return 4;
193+
}
194+
175195
// Calculate the size of a legacy cbuffer type in bytes based on
176196
// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
177197
static unsigned calculateLegacyCbufferSize(const ASTContext &Context,
@@ -183,11 +203,7 @@ static unsigned calculateLegacyCbufferSize(const ASTContext &Context,
183203
for (const FieldDecl *Field : RD->fields()) {
184204
QualType Ty = Field->getType();
185205
unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty);
186-
// FIXME: This is not the correct alignment, it does not work for 16-bit
187-
// types. See llvm/llvm-project#119641.
188-
unsigned FieldAlign = 4;
189-
if (Ty->isAggregateType())
190-
FieldAlign = CBufferAlign;
206+
unsigned FieldAlign = calculateLegacyCbufferFieldAlign(Context, Ty);
191207
Size = llvm::alignTo(Size, FieldAlign);
192208
Size += FieldSize;
193209
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK-HALF
4+
5+
// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
6+
// RUN: dxil-pc-shadermodel6.3-library %s \
7+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefix=CHECK-FLOAT
8+
9+
10+
struct S1 {
11+
half a; // 2 bytes + 2 bytes pad or 4 bytes
12+
float b; // 4 bytes
13+
half c; // 2 bytes + 2 bytes pad or 4 bytes
14+
float d; // 4 bytes
15+
double e; // 8 bytes
16+
};
17+
18+
struct S2 {
19+
half a; // 2 bytes or 4 bytes
20+
half b; // 2 bytes or 4 bytes
21+
float e; // 4 bytes or 4 bytes + 4 padding
22+
double f; // 8 bytes
23+
};
24+
25+
struct S3 {
26+
half a; // 2 bytes + 6 bytes pad or 4 bytes + 4 bytes pad
27+
uint64_t b; // 8 bytes
28+
};
29+
30+
struct S4 {
31+
float a; // 4 bytes
32+
half b; // 2 bytes or 4 bytes
33+
half c; // 2 bytes or 4 bytes + 4 bytes pad
34+
double d; // 8 bytes
35+
};
36+
37+
38+
cbuffer CB0 {
39+
// CHECK-HALF: @CB0.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB0, 24, 0))
40+
// CHECK-FLOAT: @CB0.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB0, 24, 0))
41+
S1 s1;
42+
}
43+
44+
cbuffer CB1 {
45+
// CHECK-HALF: @CB1.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 16, 0))
46+
// CHECK-FLOAT: @CB1.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB1, 24, 0))
47+
S2 s2;
48+
}
49+
50+
cbuffer CB2 {
51+
// CHECK-HALF: @CB2.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 16, 0))
52+
// CHECK-FLOAT: @CB2.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB2, 16, 0))
53+
S3 s3;
54+
}
55+
56+
cbuffer CB3 {
57+
// CHECK-HALF: @CB3.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 16, 0))
58+
// CHECK-FLOAT: @CB3.cb = external constant target("dx.CBuffer", target("dx.Layout", %__cblayout_CB3, 24, 0))
59+
S4 s4;
60+
}

0 commit comments

Comments
 (0)