Skip to content

[HLSL] Add ByteAddressBuffer, RWByteAddressBuffer and RasterizerOrderedByteAddressBuffer definitions to HLSLExternalSemaSource #113477 #116699

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 21 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 52 additions & 11 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ namespace {

struct TemplateParameterListBuilder;

struct BuiltinTypeDeclBuilder {
Sema &SemaRef;
CXXRecordDecl *Record = nullptr;
class BuiltinTypeDeclBuilder {
ClassTemplateDecl *Template = nullptr;
ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;

public:
Sema &SemaRef;
CXXRecordDecl *Record = nullptr;
friend struct TemplateParameterListBuilder;

BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R)
: SemaRef(SemaRef), Record(R) {
Record->startDefinition();
Expand All @@ -51,7 +54,7 @@ struct BuiltinTypeDeclBuilder {

BuiltinTypeDeclBuilder(Sema &SemaRef, NamespaceDecl *Namespace,
StringRef Name)
: SemaRef(SemaRef), HLSLNamespace(Namespace) {
: HLSLNamespace(Namespace), SemaRef(SemaRef) {
ASTContext &AST = SemaRef.getASTContext();
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);

Expand Down Expand Up @@ -91,6 +94,18 @@ struct BuiltinTypeDeclBuilder {
HLSLNamespace->addDecl(Record);
}

CXXRecordDecl *finalizeForwardDeclaration() {
// Force the QualType to be generated for the record declaration. In most
// cases this will happen naturally when something uses the type the
// QualType gets lazily created. Unfortunately, with our injected types if a
// type isn't used in a translation unit the QualType may not get
// automatically generated before a PCH is generated. To resolve this we
// just force that the QualType is generated after we create a forward
// declaration.
(void)Record->getASTContext().getRecordType(Record);
return Record;
}

BuiltinTypeDeclBuilder &
addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
AccessSpecifier Access = AccessSpecifier::AS_private) {
Expand Down Expand Up @@ -863,7 +878,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
constructTypedBufferConceptDecl(*SemaPtr, HLSLNamespace);
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
.addSimpleTemplateParams({"element_type"}, TypedBufferConcept)
.Record;
.finalizeForwardDeclaration();

onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
Expand All @@ -876,7 +891,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl =
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
ResourceKind::TypedBuffer, /*IsROV=*/true,
Expand All @@ -887,7 +902,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -897,7 +912,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -910,7 +925,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl =
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -920,7 +935,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl =
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -930,7 +945,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"RasterizerOrderedStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/true, /*RawBuffer=*/true)
Expand All @@ -939,6 +954,32 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addDecrementCounterMethod()
.completeDefinition();
});

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ByteAddressBuffer")
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer")
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"RasterizerOrderedByteAddressBuffer")
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/true,
/*RawBuffer=*/true)
.completeDefinition();
});
}

void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
Expand Down
49 changes: 49 additions & 0 deletions clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=ByteAddressBuffer %s | FileCheck -DRESOURCE=ByteAddressBuffer \
// RUN: -check-prefix=EMPTY %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=ByteAddressBuffer %s | FileCheck -DRESOURCE=ByteAddressBuffer \
// RUN: -check-prefixes=CHECK,CHECK-SRV,CHECK-NOSUBSCRIPT %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=RWByteAddressBuffer %s | FileCheck -DRESOURCE=RWByteAddressBuffer \
// RUN: -check-prefix=EMPTY %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=RWByteAddressBuffer %s | FileCheck -DRESOURCE=RWByteAddressBuffer \
// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=RasterizerOrderedByteAddressBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedByteAddressBuffer \
// RUN: -check-prefix=EMPTY %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=RasterizerOrderedByteAddressBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedByteAddressBuffer \
// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-NOSUBSCRIPT %s

// EMPTY: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class [[RESOURCE]]
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final

// There should be no more occurrences of RESOURCE
// EMPTY-NOT: {{[^[:alnum:]]}}[[RESOURCE]]

#ifndef EMPTY

RESOURCE Buffer;

#endif

// CHECK: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit referenced <undeserialized declarations> class [[RESOURCE]] definition


// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit __handle '__hlsl_resource_t
// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
// CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(char8_t)]]
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer

// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'const element_type &(unsigned int) const'
// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &(unsigned int)'
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV

// NOTE: SPIRV codegen for resource types is not yet implemented

ByteAddressBuffer Buffer0: register(t0);
RWByteAddressBuffer Buffer1: register(u1, space2);
RasterizerOrderedByteAddressBuffer Buffer2: register(u3, space4);

// CHECK: "class.hlsl::ByteAddressBuffer" = type { target("dx.RawBuffer", i8, 0, 0) }
// CHECK: "class.hlsl::RWByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 0) }
// CHECK: "class.hlsl::RasterizerOrderedByteAddressBuffer" = type { target("dx.RawBuffer", i8, 1, 1) }

// CHECK: @Buffer0 = global %"class.hlsl::ByteAddressBuffer" zeroinitializer, align 4
// CHECK: @Buffer1 = global %"class.hlsl::RWByteAddressBuffer" zeroinitializer, align 4
// CHECK: @Buffer2 = global %"class.hlsl::RasterizerOrderedByteAddressBuffer" zeroinitializer, align 4

// CHECK: define internal void @_GLOBAL__sub_I_ByteAddressBuffers_constructors.hlsl()
// CHECK: entry:
// CHECK: call void @_init_resource_bindings()

// CHECK: define internal void @_init_resource_bindings() {
// CHECK-NEXT: entry:
// CHECK-DXIL-NEXT: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false)
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %Buffer0_h, ptr @Buffer0, align 4
// CHECK-DXIL-NEXT: %Buffer1_h = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_0t(i32 2, i32 1, i32 1, i32 0, i1 false)
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %Buffer1_h, ptr @Buffer1, align 4
// CHECK-DXIL-NEXT: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, i1 false)
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 1) %Buffer2_h, ptr @Buffer2, align 4
Loading