aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGHLSLRuntime.cpp
diff options
context:
space:
mode:
authorHelena Kotas <hekotas@microsoft.com>2025-03-12 22:35:07 -0700
committerGitHub <noreply@github.com>2025-03-12 22:35:07 -0700
commit73e12de062c17eddfa08f61ba8f44a20fa912f1b (patch)
tree2ab13b4fe02414ec56460de7663b32b6860262fe /clang/lib/CodeGen/CGHLSLRuntime.cpp
parentbc4b2c74fe4eae40652e0f79ee9e0397110c0423 (diff)
downloadllvm-73e12de062c17eddfa08f61ba8f44a20fa912f1b.zip
llvm-73e12de062c17eddfa08f61ba8f44a20fa912f1b.tar.gz
llvm-73e12de062c17eddfa08f61ba8f44a20fa912f1b.tar.bz2
[HLSL] Implement explicit layout for default constant buffer ($Globals) (#128991)
Processes `HLSLResourceBindingAttr` attributes that represent `register(c#)` annotations on default constant buffer declarations and applies its value to the buffer layout. Any default buffer declarations without an explicit `register(c#)` annotation are placed after the elements with explicit layout. This PR also adds a test case for a `cbuffer` that does not have `packoffset` on all declarations. Same layout rules apply here as well. Fixes #126791
Diffstat (limited to 'clang/lib/CodeGen/CGHLSLRuntime.cpp')
-rw-r--r--clang/lib/CodeGen/CGHLSLRuntime.cpp45
1 files changed, 38 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index dc34653..5916fa6 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -40,6 +40,8 @@ using namespace CodeGen;
using namespace clang::hlsl;
using namespace llvm;
+using llvm::hlsl::CBufferRowSizeInBytes;
+
static void createResourceInitFn(CodeGenModule &CGM, llvm::GlobalVariable *GV,
unsigned Slot, unsigned Space);
@@ -70,7 +72,7 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
llvm::Type *
CGHLSLRuntime::convertHLSLSpecificType(const Type *T,
- SmallVector<unsigned> *Packoffsets) {
+ SmallVector<int32_t> *Packoffsets) {
assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
// Check if the target has a specific translation for this type first.
@@ -174,21 +176,50 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) {
return cast<HLSLAttributedResourceType>(QT.getTypePtr());
}
+// Iterates over all declarations in the HLSL buffer and based on the
+// packoffset or register(c#) annotations it fills outs the Layout
+// vector with the user-specified layout offsets.
+// The buffer offsets can be specified 2 ways:
+// 1. declarations in cbuffer {} block can have a packoffset annotation
+// (translates to HLSLPackOffsetAttr)
+// 2. default constant buffer declarations at global scope can have
+// register(c#) annotations (translates to HLSLResourceBindingAttr with
+// RegisterType::C)
+// It is not guaranteed that all declarations in a buffer have an annotation.
+// For those where it is not specified a -1 value is added to the Layout
+// vector. In the final layout these declarations will be placed at the end
+// of the HLSL buffer after all of the elements with specified offset.
static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
- SmallVector<unsigned> &Layout) {
+ SmallVector<int32_t> &Layout) {
assert(Layout.empty() && "expected empty vector for layout");
assert(BufDecl->hasValidPackoffset());
- for (Decl *D : BufDecl->decls()) {
+ for (Decl *D : BufDecl->buffer_decls()) {
if (isa<CXXRecordDecl, EmptyDecl>(D) || isa<FunctionDecl>(D)) {
continue;
}
VarDecl *VD = dyn_cast<VarDecl>(D);
if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant)
continue;
- assert(VD->hasAttr<HLSLPackOffsetAttr>() &&
- "expected packoffset attribute on every declaration");
- size_t Offset = VD->getAttr<HLSLPackOffsetAttr>()->getOffsetInBytes();
+
+ if (!VD->hasAttrs()) {
+ Layout.push_back(-1);
+ continue;
+ }
+
+ int32_t Offset = -1;
+ for (auto *Attr : VD->getAttrs()) {
+ if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
+ Offset = POA->getOffsetInBytes();
+ break;
+ }
+ auto *RBA = dyn_cast<HLSLResourceBindingAttr>(Attr);
+ if (RBA &&
+ RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
+ Offset = RBA->getSlotNumber() * CBufferRowSizeInBytes;
+ break;
+ }
+ }
Layout.push_back(Offset);
}
}
@@ -207,7 +238,7 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
return;
// create global variable for the constant buffer
- SmallVector<unsigned> Layout;
+ SmallVector<int32_t> Layout;
if (BufDecl->hasValidPackoffset())
fillPackoffsetLayout(BufDecl, Layout);