Skip to content

Commit 39f2bae

Browse files
authored
[HLSL] Add RasterizerOrderedStructuredBuffer definition to HLSLExternalSemaSource (#113648)
Adds `RasterizerOrderedStructuredBuffer` definition to HLSLExternalSemaSource. Adds separate tests for the AST shape and element types. Adds constructor/handle.fromBinding and subscript test cases to shared test file for structured buffers. Additional methods will be added later. Fixes #112776
1 parent 5a6cc50 commit 39f2bae

File tree

5 files changed

+155
-2
lines changed

5 files changed

+155
-2
lines changed

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,18 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
519519
.addArraySubscriptOperators()
520520
.completeDefinition();
521521
});
522+
523+
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
524+
"RasterizerOrderedStructuredBuffer")
525+
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
526+
.Record;
527+
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
528+
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
529+
ResourceKind::TypedBuffer, /*IsROV=*/true,
530+
/*RawBuffer=*/true)
531+
.addArraySubscriptOperators()
532+
.completeDefinition();
533+
});
522534
}
523535

524536
void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY %s | FileCheck -check-prefix=EMPTY %s
2+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s
3+
4+
5+
// This test tests two different AST generations. The "EMPTY" test mode verifies
6+
// the AST generated by forward declaration of the HLSL types which happens on
7+
// initializing the HLSL external AST with an AST Context.
8+
9+
// The non-empty mode has a use that requires the RasterizerOrderedStructuredBuffer type be complete,
10+
// which results in the AST being populated by the external AST source. That
11+
// case covers the full implementation of the template declaration and the
12+
// instantiated specialization.
13+
14+
// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RasterizerOrderedStructuredBuffer
15+
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
16+
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class RasterizerOrderedStructuredBuffer
17+
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
18+
19+
// There should be no more occurrences of RasterizerOrderedStructuredBuffer
20+
// EMPTY-NOT: {{[^[:alnum:]]}}RasterizerOrderedStructuredBuffer
21+
22+
#ifndef EMPTY
23+
24+
RasterizerOrderedStructuredBuffer<int> Buffer;
25+
26+
#endif
27+
28+
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RasterizerOrderedStructuredBuffer
29+
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
30+
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RasterizerOrderedStructuredBuffer definition
31+
32+
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
33+
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
34+
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
35+
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
36+
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
37+
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
38+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
39+
40+
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
41+
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
42+
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
43+
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
44+
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}}
45+
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'const RasterizerOrderedStructuredBuffer<element_type>' lvalue implicit this
46+
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
47+
48+
// CHECK-NEXT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &(unsigned int)'
49+
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
50+
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
51+
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
52+
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}}
53+
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'RasterizerOrderedStructuredBuffer<element_type>' lvalue implicit this
54+
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
55+
56+
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class RasterizerOrderedStructuredBuffer definition
57+
58+
// CHECK: TemplateArgument type 'int'
59+
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
60+
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
61+
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
62+
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
63+
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
64+
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
65+
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]]
66+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL
2+
3+
// NOTE: The number in type name and whether the struct is packed or not will mostly
4+
// likely change once subscript operators are properly implemented (llvm/llvm-project#95956)
5+
// and theinterim field of the contained type is removed.
6+
7+
struct MyStruct {
8+
float4 a;
9+
int2 b;
10+
};
11+
12+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type <{ target("dx.RawBuffer", i16, 1, 1)
13+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.0" = type <{ target("dx.RawBuffer", i16, 1, 1)
14+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 1)
15+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.3" = type { target("dx.RawBuffer", i32, 1, 1)
16+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 1)
17+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.5" = type { target("dx.RawBuffer", i64, 1, 1)
18+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.6" = type <{ target("dx.RawBuffer", half, 1, 1)
19+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.8" = type { target("dx.RawBuffer", float, 1, 1)
20+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.9" = type { target("dx.RawBuffer", double, 1, 1)
21+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.10" = type { target("dx.RawBuffer", <4 x i16>, 1, 1)
22+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x i32>, 1, 1)
23+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.12" = type { target("dx.RawBuffer", <2 x half>, 1, 1)
24+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.13" = type { target("dx.RawBuffer", <3 x float>, 1, 1)
25+
// DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer.14" = type { target("dx.RawBuffer", %struct.MyStruct = type { <4 x float>, <2 x i32>, [8 x i8] }, 1, 1)
26+
27+
RasterizerOrderedStructuredBuffer<int16_t> BufI16;
28+
RasterizerOrderedStructuredBuffer<uint16_t> BufU16;
29+
RasterizerOrderedStructuredBuffer<int> BufI32;
30+
RasterizerOrderedStructuredBuffer<uint> BufU32;
31+
RasterizerOrderedStructuredBuffer<int64_t> BufI64;
32+
RasterizerOrderedStructuredBuffer<uint64_t> BufU64;
33+
RasterizerOrderedStructuredBuffer<half> BufF16;
34+
RasterizerOrderedStructuredBuffer<float> BufF32;
35+
RasterizerOrderedStructuredBuffer<double> BufF64;
36+
RasterizerOrderedStructuredBuffer< vector<int16_t, 4> > BufI16x4;
37+
RasterizerOrderedStructuredBuffer< vector<uint, 3> > BufU32x3;
38+
RasterizerOrderedStructuredBuffer<half2> BufF16x2;
39+
RasterizerOrderedStructuredBuffer<float3> BufF32x3;
40+
// TODO: RasterizerOrderedStructuredBuffer<snorm half> BufSNormF16;
41+
// TODO: RasterizerOrderedStructuredBuffer<unorm half> BufUNormF16;
42+
// TODO: RasterizerOrderedStructuredBuffer<snorm float> BufSNormF32;
43+
// TODO: RasterizerOrderedStructuredBuffer<unorm float> BufUNormF32;
44+
// TODO: RasterizerOrderedStructuredBuffer<snorm double> BufSNormF64;
45+
// TODO: RasterizerOrderedStructuredBuffer<unorm double> BufUNormF64;
46+
RasterizerOrderedStructuredBuffer<MyStruct> BufMyStruct;
47+
48+
[numthreads(1,1,1)]
49+
void main(int GI : SV_GroupIndex) {
50+
BufI16[GI] = 0;
51+
BufU16[GI] = 0;
52+
BufI32[GI] = 0;
53+
BufU32[GI] = 0;
54+
BufI64[GI] = 0;
55+
BufU64[GI] = 0;
56+
BufF16[GI] = 0;
57+
BufF32[GI] = 0;
58+
BufF64[GI] = 0;
59+
BufI16x4[GI] = 0;
60+
BufU32x3[GI] = 0;
61+
BufF16x2[GI] = 0;
62+
BufF32x3[GI] = 0;
63+
BufMyStruct[GI] = {{0,0,0,0},{0,0}};
64+
}

clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@
55

66
StructuredBuffer<float> Buf : register(t10);
77
RWStructuredBuffer<float> Buf2 : register(u5, space1);
8+
RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2);
89

910
// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0), float }
1011
// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0), float }
12+
// CHECK: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1), float }
1113

1214
// CHECK: @Buf = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4
1315
// CHECK: @Buf2 = global %"class.hlsl::RWStructuredBuffer" zeroinitializer, align 4
16+
// CHECK: @Buf5 = global %"class.hlsl::RasterizerOrderedStructuredBuffer" zeroinitializer, align 4
1417

1518
// CHECK: define linkonce_odr void @_ZN4hlsl16StructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this)
1619
// CHECK-NEXT: entry:
1720
// CHECK: define linkonce_odr void @_ZN4hlsl18RWStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this)
1821
// CHECK-NEXT: entry:
22+
// CHECK: define linkonce_odr void @_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(8) %this)
23+
// CHECK-NEXT: entry:
1924

2025
// CHECK: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
2126
// CHECK: entry:
@@ -27,7 +32,11 @@ RWStructuredBuffer<float> Buf2 : register(u5, space1);
2732
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf, align 4
2833
// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false)
2934
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2, align 4
35+
// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false)
36+
// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4
3037
// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false)
3138
// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf", align 4
3239
// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false)
3340
// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2", align 4
41+
// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.handle.fromBinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false)
42+
// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4

clang/test/CodeGenHLSL/builtins/StructuredBuffers-subscripts.hlsl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s
22

33
StructuredBuffer<int> In;
4-
RWStructuredBuffer<int> Out;
4+
RWStructuredBuffer<int> Out1;
5+
RasterizerOrderedStructuredBuffer<int> Out2;
56

67
[numthreads(1,1,1)]
78
void main(unsigned GI : SV_GroupIndex) {
8-
Out[GI] = In[GI];
9+
Out1[GI] = In[GI];
10+
Out2[GI] = In[GI];
911
}
1012

1113
// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy

0 commit comments

Comments
 (0)