[clang] [HLSL] Define CBuffer field alignment for matrix types (PR #179836)
Farzon Lotfi via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 18 08:51:23 PST 2026
https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/179836
>From 46f3ad099657bd1e8724c3e03a0cfe4945586624 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 4 Feb 2026 20:48:35 -0500
Subject: [PATCH 1/2] [HLSL] Define CBuffer field alignment for matrix types
fixes https://github.com/llvm/llvm-project/issues/179834
Change defines Matrix alignment as buffer row length (16).
Same as arrays and structs.
Change also adds tests for matrix, matrix in structs, & arrays.
---
clang/lib/Sema/SemaHLSL.cpp | 4 +-
.../resources/cbuffer_matrix_align.hlsl | 71 +++++++++++++++++++
2 files changed, 73 insertions(+), 2 deletions(-)
create mode 100644 clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 4823bb4265789..802a1bdbccfdd 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -218,8 +218,8 @@ Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context,
QualType T) {
- // Arrays and Structs are always aligned to new buffer rows
- if (T->isArrayType() || T->isStructureType())
+ // Arrays, Matrices, and Structs are always aligned to new buffer rows
+ if (T->isArrayType() || T->isStructureType() || T->isConstantMatrixType())
return 16;
// Vectors are aligned to the type they contain
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl
new file mode 100644
index 0000000000000..ff4ce0f104f44
--- /dev/null
+++ b/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -fsyntax-only -verify -verify-ignore-unexpected=warning
+
+cbuffer MatArr0Pass {
+ float2x4 A0p[2] : packoffset(c0.x);
+ float a0tail : packoffset(c4.x);
+}
+
+cbuffer MatArr0Fail {
+ float2x4 A0f[2] : packoffset(c0.x);
+ float a0bad : packoffset(c1.w);
+ // expected-error at -1 {{packoffset overlap between 'a0bad', 'A0f'}}
+}
+
+// Struct containing a matrix.
+
+struct MS0 {
+ float2x4 M;
+ float2 V;
+};
+
+cbuffer MatStruct0Pass {
+ MS0 s0p : packoffset(c0.x);
+ float s0tail: packoffset(c5.x);
+}
+
+cbuffer MatStruct0Fail {
+ MS0 s0f : packoffset(c0.x);
+ float s0bad : packoffset(c0.y);
+ // expected-error at -1 {{packoffset overlap between 's0bad', 's0f'}}
+}
+
+// Nested struct containing a matrix.
+struct Inner0 {
+ float2x4 M;
+ float F;
+};
+
+struct Outer0 {
+ float2 Head;
+ Inner0 I;
+ float2 Tail;
+};
+
+cbuffer MatNested0Pass {
+ Outer0 o0p : packoffset(c0.x);
+ float o0tail: packoffset(c8.x);
+}
+
+cbuffer MatNested0Fail {
+ Outer0 o0f : packoffset(c0.x);
+ float o0bad: packoffset(c3.y);
+ // expected-error at -1 {{packoffset overlap between 'o0bad', 'o0f'}}
+}
+
+// Array-of-struct where struct contains a matrix.
+
+struct AMS0 {
+ float2x4 M;
+ float2 V;
+};
+
+cbuffer MatArrStruct0Pass {
+ AMS0 as0p[2] : packoffset(c0.x);
+ float as0tail : packoffset(c10.x);
+}
+
+cbuffer MatArrStruct0Fail {
+ AMS0 as0f[2] : packoffset(c0.x);
+ float as0bad : packoffset(c4.z);
+ // expected-error at -1 {{packoffset overlap between 'as0bad', 'as0f'}}
+}
>From 03f2ea7bc156cce2c29b61662c39e589cd5591cc Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 18 Feb 2026 11:51:04 -0500
Subject: [PATCH 2/2] update tests to have tighter boundaries
---
.../resources/cbuffer_matrix_align.hlsl | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl b/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl
index ff4ce0f104f44..70b2732372691 100644
--- a/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl
+++ b/clang/test/CodeGenHLSL/resources/cbuffer_matrix_align.hlsl
@@ -7,7 +7,7 @@ cbuffer MatArr0Pass {
cbuffer MatArr0Fail {
float2x4 A0f[2] : packoffset(c0.x);
- float a0bad : packoffset(c1.w);
+ float a0bad : packoffset(c3.z);
// expected-error at -1 {{packoffset overlap between 'a0bad', 'A0f'}}
}
@@ -20,12 +20,12 @@ struct MS0 {
cbuffer MatStruct0Pass {
MS0 s0p : packoffset(c0.x);
- float s0tail: packoffset(c5.x);
+ float s0tail: packoffset(c2.z);
}
cbuffer MatStruct0Fail {
MS0 s0f : packoffset(c0.x);
- float s0bad : packoffset(c0.y);
+ float s0bad : packoffset(c2.y);
// expected-error at -1 {{packoffset overlap between 's0bad', 's0f'}}
}
@@ -43,12 +43,12 @@ struct Outer0 {
cbuffer MatNested0Pass {
Outer0 o0p : packoffset(c0.x);
- float o0tail: packoffset(c8.x);
+ float o0tail: packoffset(c4.x);
}
cbuffer MatNested0Fail {
Outer0 o0f : packoffset(c0.x);
- float o0bad: packoffset(c3.y);
+ float o0bad: packoffset(c3.z);
// expected-error at -1 {{packoffset overlap between 'o0bad', 'o0f'}}
}
@@ -61,11 +61,11 @@ struct AMS0 {
cbuffer MatArrStruct0Pass {
AMS0 as0p[2] : packoffset(c0.x);
- float as0tail : packoffset(c10.x);
+ float as0tail : packoffset(c5.z);
}
cbuffer MatArrStruct0Fail {
AMS0 as0f[2] : packoffset(c0.x);
- float as0bad : packoffset(c4.z);
+ float as0bad : packoffset(c5.y);
// expected-error at -1 {{packoffset overlap between 'as0bad', 'as0f'}}
}
More information about the cfe-commits
mailing list