Skip to content

Commit

Permalink
[HLSL] Add Load(int) method on structured buffers (llvm#120663)
Browse files Browse the repository at this point in the history
Adds `T Load(int)` method on `StructuredBuffer`, `RWStructuredBuffer`
and `RasterizerOrderedStructuredBuffer`.

Uses the existing `addLoadMethods` in HLSLExternalSemalSource so most of
this change is just tests.

Fixes llvm#112977
  • Loading branch information
hekota authored Dec 20, 2024
1 parent df8efbd commit 7a4b3b4
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
3 changes: 3 additions & 0 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
.addArraySubscriptOperators()
.addLoadMethods()
.completeDefinition();
});

Expand All @@ -1037,6 +1038,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
.addArraySubscriptOperators()
.addLoadMethods()
.addIncrementCounterMethod()
.addDecrementCounterMethod()
.completeDefinition();
Expand Down Expand Up @@ -1072,6 +1074,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/true, /*RawBuffer=*/true)
.addArraySubscriptOperators()
.addLoadMethods()
.addIncrementCounterMethod()
.addDecrementCounterMethod()
.completeDefinition();
Expand Down
21 changes: 18 additions & 3 deletions clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=StructuredBuffer %s | FileCheck -DRESOURCE=StructuredBuffer \
// RUN: -check-prefixes=CHECK,CHECK-SRV,CHECK-SUBSCRIPT %s
// RUN: -check-prefixes=CHECK,CHECK-SRV,CHECK-SUBSCRIPT,CHECK-LOAD %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=RWStructuredBuffer %s | FileCheck -DRESOURCE=RWStructuredBuffer \
// RUN: -check-prefix=EMPTY %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=RWStructuredBuffer %s | FileCheck -DRESOURCE=RWStructuredBuffer \
// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-COUNTER %s
// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-COUNTER,CHECK-LOAD %s
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \
// RUN: -DRESOURCE=AppendStructuredBuffer %s | FileCheck -DRESOURCE=AppendStructuredBuffer \
Expand All @@ -36,7 +36,7 @@
//
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \
// RUN: -DRESOURCE=RasterizerOrderedStructuredBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedStructuredBuffer \
// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-ROV,CHECK-SUBSCRIPT %s
// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-ROV,CHECK-SUBSCRIPT,CHECK-LOAD %s

// This test tests two different AST generations for each structured buffer.
// The "EMPTY" test mode verifies the AST generated by forward declaration
Expand Down Expand Up @@ -125,6 +125,21 @@ RESOURCE<float> Buffer;
// 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)'

// CHECK-LOAD: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Load 'element_type (unsigned int)'
// CHECK-LOAD-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Index 'unsigned int'
// CHECK-LOAD-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
// CHECK-LOAD-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
// CHECK-LOAD-NEXT: UnaryOperator 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' prefix '*' cannot overflow
// CHECK-LOAD-NEXT: CallExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type *'
// CHECK-LOAD-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '<builtin fn type>' Function 0x{{[0-9A-Fa-f]+}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept'
// CHECK-LOAD-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '__hlsl_resource_t
// CHECK-LOAD-SAME{LITERAL}: [[hlsl::resource_class(
// CHECK-LOAD-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
// CHECK-LOAD-SAME: ' lvalue .__handle 0x{{[0-9A-Fa-f]+}}
// CHECK-LOAD-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> '[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-LOAD-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'unsigned int' ParmVar 0x{{[0-9A-Fa-f]+}} 'Index' 'unsigned int'
// CHECK-LOAD-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline

// CHECK-COUNTER: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> IncrementCounter 'unsigned int ()'
// CHECK-COUNTER-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
// CHECK-COUNTER-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
Expand Down
15 changes: 15 additions & 0 deletions clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-lib.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@

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

StructuredBuffer<float> SB1 : register(t0);
RWStructuredBuffer<float> RWSB1 : register(u0);
RWStructuredBuffer<float> RWSB2 : register(u1);
AppendStructuredBuffer<float> ASB : register(u2);
ConsumeStructuredBuffer<float> CSB : register(u3);

// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
// CHECK: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
// CHECK: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }

export int TestIncrementCounter() {
return RWSB1.IncrementCounter();
Expand Down Expand Up @@ -45,5 +49,16 @@ export float TestConsume() {
// CHECK-DXIL: %[[VALUE:.*]] = load float, ptr %[[RESPTR]], align 4
// CHECK-DXIL: ret float %[[VALUE]]

export float TestLoad() {
return RWSB1.Load(1) + SB1.Load(2);
}

// CHECK: define noundef float @_Z8TestLoadv()
// CHECK: %[[PTR1:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %{{[0-9]+}}, i32 %{{[0-9]+}})
// CHECK: %[[VALUE1:.*]] = load float, ptr %[[PTR1]]
// CHECK: %[[PTR2:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %{{[0-9]+}}, i32 %{{[0-9]+}})
// CHECK: %[[VALUE2:.*]] = load float, ptr %[[PTR2]]

// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32)
// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0), i32)
13 changes: 11 additions & 2 deletions clang/test/CodeGenHLSL/builtins/StructuredBuffers-methods-ps.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,14 @@ export void TestDecrementCounter() {
ROSB2.DecrementCounter();
}

// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8)
// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8)
export float TestLoad() {
return ROSB1.Load(10);
}

// CHECK: define noundef float @_Z8TestLoadv()
// CHECK: %[[PTR1:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %{{[0-9]+}}, i32 %{{[0-9]+}})
// CHECK: %[[VALUE1:.*]] = load float, ptr %[[PTR1]]

// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i8) #3
// CHECK: declare i32 @llvm.dx.resource.updatecounter.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i8) #3
// CHECK: declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1), i32) #4

0 comments on commit 7a4b3b4

Please sign in to comment.