Skip to content

[HLSL] Implement default constant buffer $Globals #125807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
63c465b
[HLSL] Constant buffer layout struct update
hekota Jan 28, 2025
c80415a
filter groupshared var decls
hekota Jan 29, 2025
cf08adb
[HLSL] Translate cbuffer declarations to target type dx.CBuffer - ini…
hekota Jan 28, 2025
56beb45
remove stride
hekota Jan 29, 2025
749e88e
cleanup, update comments
hekota Jan 29, 2025
a12bcbc
Move skipping of implicit initializer of hlsl_constant decls to a dif…
hekota Feb 4, 2025
6dc3a1a
Merge branch 'users/hekota/pr-124840' of https://github.com/llvm/llvm…
hekota Feb 4, 2025
66ae784
Add LayoutStruct to HLSLBufferDecl; add skipping of implicit initiali…
hekota Feb 5, 2025
e042f72
desugar types and check for resource builtin type
hekota Feb 5, 2025
a8cdd45
Merge branch 'users/hekota/pr-124840' of https://github.com/llvm/llvm…
hekota Feb 5, 2025
42bb34f
[HLSL] Implement default constant buffer `$Globals`
hekota Feb 5, 2025
6485482
clang-format
hekota Feb 5, 2025
991ba1d
whitespace change so I can force-push the branch to unblock stuck PR
hekota Feb 5, 2025
b62863b
Rework cbuffer codegen to use the target("dx.Layout", ...) type
hekota Feb 12, 2025
7499d40
Merge branch 'main' of https://github.com/llvm/llvm-project into cbuf…
hekota Feb 15, 2025
62094b2
code review feedback - add named constant, rename function, remove file
hekota Feb 15, 2025
3a24dcf
Merge branch 'users/hekotas/pr-124886' of https://github.com/llvm/llv…
hekota Feb 15, 2025
43aedd4
fix test after merge
hekota Feb 15, 2025
6aa47e9
Merge branch 'main' into cbuffer-codegen5
hekota Feb 15, 2025
a90b3a1
code review feedback - update comment, add new line
hekota Feb 18, 2025
eaeaf2a
code review feedback - minor changes
hekota Feb 19, 2025
515c25e
Merge branch 'main' of https://github.com/llvm/llvm-project into cbuf…
hekota Feb 19, 2025
d3c8872
code review feedback - move layout calculations into a separate build…
hekota Feb 19, 2025
3cd4d49
Merge branch 'cbuffer-codegen5' of https://github.com/hekota/llvm-pro…
hekota Feb 19, 2025
77987bd
revert clang/lib/CodeGen/CMakeLists.txt whitespace changes
hekota Feb 19, 2025
b934073
clang-format
hekota Feb 19, 2025
ea008fe
Merge branch 'users/hekotas/pr-124886' of https://github.com/llvm/llv…
hekota Feb 19, 2025
c85d08d
Merge branch 'main' of https://github.com/llvm/llvm-project into defa…
hekota Feb 20, 2025
e2f562b
Merge branch 'main' into default-cbuffer
hekota Feb 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5032,6 +5032,16 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
SourceLocation KwLoc;
/// IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
bool IsCBuffer;
/// HasValidPackoffset - Whether the buffer has valid packoffset annotations
// on all declarations
bool HasPackoffset;
// LayoutStruct - Layout struct for the buffer
CXXRecordDecl *LayoutStruct;

// For default (implicit) constant buffer, a lisf of references of global
// decls that belong to the buffer. The decls are already parented by the
// translation unit context.
SmallVector<Decl *> DefaultBufferDecls;

HLSLBufferDecl(DeclContext *DC, bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc,
Expand All @@ -5042,6 +5052,8 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc,
SourceLocation LBrace);
static HLSLBufferDecl *CreateDefaultCBuffer(ASTContext &C,
DeclContext *LexicalParent);
static HLSLBufferDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);

SourceRange getSourceRange() const override LLVM_READONLY {
Expand All @@ -5052,6 +5064,11 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
bool isCBuffer() const { return IsCBuffer; }
void setHasPackoffset(bool PO) { HasPackoffset = PO; }
bool hasPackoffset() const { return HasPackoffset; }
const CXXRecordDecl *getLayoutStruct() const { return LayoutStruct; }
void addLayoutStruct(CXXRecordDecl *LS);
void addDefaultBufferDecl(Decl *D);

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
Expand All @@ -5063,6 +5080,20 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC));
}

// Iterator for the buffer decls. Concatenates the list of decls parented
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just want to clarify what this comment says. The children decls of this hlslbufferdecl are concatenated with the list of default buffer decls? Does the order of this matter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct. We are not depending on the order, but I like to put default buffer decls first and the children decls second because the children decls will include an implicit buffer layout struct decl that is created last. I will update the comment to make it clearer.

// by this HLSLBufferDecl with the list of default buffer decls.
using buffer_decl_iterator =
llvm::concat_iterator<Decl *const, SmallVector<Decl *>::const_iterator,
decl_iterator>;
using buffer_decl_range = llvm::iterator_range<buffer_decl_iterator>;

buffer_decl_range buffer_decls() const {
return buffer_decl_range(buffer_decls_begin(), buffer_decls_end());
}
buffer_decl_iterator buffer_decls_begin() const;
buffer_decl_iterator buffer_decls_end() const;
bool buffer_decls_empty();

friend class ASTDeclReader;
friend class ASTDeclWriter;
};
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -6266,8 +6266,8 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
LLVM_PREFERRED_TYPE(bool)
uint8_t RawBuffer : 1;

Attributes(llvm::dxil::ResourceClass ResourceClass, bool IsROV,
bool RawBuffer)
Attributes(llvm::dxil::ResourceClass ResourceClass, bool IsROV = false,
bool RawBuffer = false)
: ResourceClass(ResourceClass), IsROV(IsROV), RawBuffer(RawBuffer) {}

Attributes() : Attributes(llvm::dxil::ResourceClass::UAV, false, false) {}
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ class SemaHLSL : public SemaBase {
HLSLParamModifierAttr::Spelling Spelling);
void ActOnTopLevelFunction(FunctionDecl *FD);
void ActOnVariableDeclarator(VarDecl *VD);
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU);
void CheckEntryPoint(FunctionDecl *FD);
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
const HLSLAnnotationAttr *AnnotationAttr);
void DiagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);

QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS,
QualType LHSType, QualType RHSType,
Expand Down Expand Up @@ -159,11 +159,16 @@ class SemaHLSL : public SemaBase {
// List of all resource bindings
ResourceBindings Bindings;

// default constant buffer $Globals
HLSLBufferDecl *DefaultCBuffer;

private:
void collectResourcesOnVarDecl(VarDecl *D);
void collectResourcesOnUserRecordDecl(const VarDecl *VD,
const RecordType *RT);
void processExplicitBindingsOnDecl(VarDecl *D);

void diagnoseAvailabilityViolations(TranslationUnitDecl *TU);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you want this to be private now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It used to be called directly from clang Sema. Now clang Sema calls HLSL Sema's ActOnEndOfTranslationUnit because we need to do more work at the end of translation unit. The diagnoseAvailabilityViolations is called from SemaHLSL::ActOnEndOfTranslationUnit so it can be private now.

};

} // namespace clang
Expand Down
48 changes: 47 additions & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -1747,6 +1748,10 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
}
}

// Suppress transparent contexts like export or HLSLBufferDecl context
if (Ctx->isTransparentContext())
continue;

// Skip non-named contexts such as linkage specifications and ExportDecls.
const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
if (!ND)
Expand Down Expand Up @@ -5713,7 +5718,7 @@ HLSLBufferDecl::HLSLBufferDecl(DeclContext *DC, bool CBuffer,
SourceLocation IDLoc, SourceLocation LBrace)
: NamedDecl(Decl::Kind::HLSLBuffer, DC, IDLoc, DeclarationName(ID)),
DeclContext(Decl::Kind::HLSLBuffer), LBraceLoc(LBrace), KwLoc(KwLoc),
IsCBuffer(CBuffer) {}
IsCBuffer(CBuffer), HasPackoffset(false), LayoutStruct(nullptr) {}

HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
DeclContext *LexicalParent, bool CBuffer,
Expand All @@ -5737,12 +5742,53 @@ HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
return Result;
}

HLSLBufferDecl *
HLSLBufferDecl::CreateDefaultCBuffer(ASTContext &C,
DeclContext *LexicalParent) {
DeclContext *DC = LexicalParent;
IdentifierInfo *II = &C.Idents.get("$Globals", tok::TokenKind::identifier);
HLSLBufferDecl *Result = new (C, DC) HLSLBufferDecl(
DC, true, SourceLocation(), II, SourceLocation(), SourceLocation());
Result->setImplicit(true);
return Result;
}

HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C,
GlobalDeclID ID) {
return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
SourceLocation(), SourceLocation());
}

void HLSLBufferDecl::addLayoutStruct(CXXRecordDecl *LS) {
assert(LayoutStruct == nullptr && "layout struct has already been set");
LayoutStruct = LS;
addDecl(LS);
}

void HLSLBufferDecl::addDefaultBufferDecl(Decl *D) {
assert(isImplicit() &&
"default decls can only be added to the implicit/default constant "
"buffer $Globals");
DefaultBufferDecls.push_back(D);
}

HLSLBufferDecl::buffer_decl_iterator
HLSLBufferDecl::buffer_decls_begin() const {
return buffer_decl_iterator(llvm::iterator_range(DefaultBufferDecls.begin(),
DefaultBufferDecls.end()),
decl_range(decls_begin(), decls_end()));
}

HLSLBufferDecl::buffer_decl_iterator HLSLBufferDecl::buffer_decls_end() const {
return buffer_decl_iterator(
llvm::iterator_range(DefaultBufferDecls.end(), DefaultBufferDecls.end()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is supposed to say end, end?

Copy link
Member Author

@hekota hekota Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it signifies the end of the list. buffer_decl_iterator is a llvm::concat_iterator and it takes a list of ranges.

decl_range(decls_end(), decls_end()));
}

bool HLSLBufferDecl::buffer_decls_empty() {
return DefaultBufferDecls.empty() && decls_empty();
}

//===----------------------------------------------------------------------===//
// ImportDecl Implementation
//===----------------------------------------------------------------------===//
Expand Down
Loading