Skip to content

Commit d413335

Browse files
authored
[HLSL] Add Append/ConsumeStructuredBuffer definitions to HLSLExternalSemaSource (#113643)
Adds `AppendStructuredBuffer` and `ConsumeStructuredBuffer` definition to HLSLExternalSemaSource. Adds separate tests for the AST shape and element types, and adds constructor/handle.fromBinding test case to shared test file for structured buffers. These buffers do not have any subscript operators. Append and Consume methods will be added later in #112968. Fixes #112777
1 parent 6548b63 commit d413335

8 files changed

+243
-10
lines changed

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,8 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
502502
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
503503
.Record;
504504
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
505-
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV,
506-
ResourceKind::TypedBuffer, /*IsROV=*/false,
505+
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
506+
/*IsROV=*/false,
507507
/*RawBuffer=*/true)
508508
.addArraySubscriptOperators()
509509
.completeDefinition();
@@ -513,13 +513,35 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
513513
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
514514
.Record;
515515
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
516-
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
517-
ResourceKind::TypedBuffer, /*IsROV=*/false,
516+
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
517+
/*IsROV=*/false,
518518
/*RawBuffer=*/true)
519519
.addArraySubscriptOperators()
520520
.completeDefinition();
521521
});
522522

523+
Decl =
524+
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer")
525+
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
526+
.Record;
527+
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
528+
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
529+
/*IsROV=*/false,
530+
/*RawBuffer=*/true)
531+
.completeDefinition();
532+
});
533+
534+
Decl =
535+
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer")
536+
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
537+
.Record;
538+
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
539+
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
540+
/*IsROV=*/false,
541+
/*RawBuffer=*/true)
542+
.completeDefinition();
543+
});
544+
523545
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
524546
"RasterizerOrderedStructuredBuffer")
525547
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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 AppendStructuredBuffer 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 AppendStructuredBuffer
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 AppendStructuredBuffer
17+
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
18+
19+
// There should be no more occurrences of AppendStructuredBuffer
20+
// EMPTY-NOT: {{[^[:alnum:]]}}AppendStructuredBuffer
21+
22+
#ifndef EMPTY
23+
24+
AppendStructuredBuffer<int> Buffer;
25+
26+
#endif
27+
28+
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit AppendStructuredBuffer
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 AppendStructuredBuffer 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::raw_buffer]]
36+
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
37+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer
38+
39+
// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
40+
// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &(unsigned int)'
41+
42+
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class AppendStructuredBuffer definition
43+
// CHECK: TemplateArgument type 'int'
44+
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
45+
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
46+
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
47+
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
48+
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
49+
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]]
50+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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 ConsumeStructuredBuffer 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 ConsumeStructuredBuffer
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 ConsumeStructuredBuffer
17+
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
18+
19+
// There should be no more occurrences of ConsumeStructuredBuffer
20+
// EMPTY-NOT: {{[^[:alnum:]]}}ConsumeStructuredBuffer
21+
22+
#ifndef EMPTY
23+
24+
ConsumeStructuredBuffer<int> Buffer;
25+
26+
#endif
27+
28+
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit ConsumeStructuredBuffer
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 ConsumeStructuredBuffer 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::raw_buffer]]
36+
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
37+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer
38+
39+
// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
40+
// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &(unsigned int)'
41+
42+
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class ConsumeStructuredBuffer definition
43+
44+
// CHECK: TemplateArgument type 'int'
45+
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
46+
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
47+
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
48+
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
49+
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
50+
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]]
51+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer

clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ RWStructuredBuffer<int> Buffer;
3434
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
3535
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
3636
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
37-
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
37+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer
3838

3939
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
4040
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
@@ -61,4 +61,4 @@ RWStructuredBuffer<int> Buffer;
6161
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
6262
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
6363
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]]
64-
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
64+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer

clang/test/AST/HLSL/StructuredBuffer-AST.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ StructuredBuffer<float> Buffer;
3434
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
3535
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
3636
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
37-
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
37+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer
3838

3939
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
4040
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
@@ -61,4 +61,4 @@ StructuredBuffer<float> Buffer;
6161
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
6262
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
6363
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]]
64-
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
64+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit RawBuffer
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
struct MyStruct {
4+
float4 a;
5+
int2 b;
6+
};
7+
8+
// DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0)
9+
// DXIL: %"class.hlsl::AppendStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0)
10+
// DXIL: %"class.hlsl::AppendStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0)
11+
// DXIL: %"class.hlsl::AppendStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0)
12+
// DXIL: %"class.hlsl::AppendStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0)
13+
// DXIL: %"class.hlsl::AppendStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0)
14+
// DXIL: %"class.hlsl::AppendStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0)
15+
// DXIL: %"class.hlsl::AppendStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0)
16+
// DXIL: %"class.hlsl::AppendStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0)
17+
// DXIL: %"class.hlsl::AppendStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0)
18+
// DXIL: %"class.hlsl::AppendStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0)
19+
// DXIL: %"class.hlsl::AppendStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0)
20+
// DXIL: %"class.hlsl::AppendStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0)
21+
// DXIL: %"class.hlsl::AppendStructuredBuffer.12" = type { target("dx.RawBuffer", %struct.MyStruct = type { <4 x float>, <2 x i32>, [8 x i8] }, 1, 0)
22+
23+
AppendStructuredBuffer<int16_t> BufI16;
24+
AppendStructuredBuffer<uint16_t> BufU16;
25+
AppendStructuredBuffer<int> BufI32;
26+
AppendStructuredBuffer<uint> BufU32;
27+
AppendStructuredBuffer<int64_t> BufI64;
28+
AppendStructuredBuffer<uint64_t> BufU64;
29+
AppendStructuredBuffer<half> BufF16;
30+
AppendStructuredBuffer<float> BufF32;
31+
AppendStructuredBuffer<double> BufF64;
32+
AppendStructuredBuffer< vector<int16_t, 4> > BufI16x4;
33+
AppendStructuredBuffer< vector<uint, 3> > BufU32x3;
34+
AppendStructuredBuffer<half2> BufF16x2;
35+
AppendStructuredBuffer<float3> BufF32x3;
36+
// TODO: AppendStructuredBuffer<snorm half> BufSNormF16;
37+
// TODO: AppendStructuredBuffer<unorm half> BufUNormF16;
38+
// TODO: AppendStructuredBuffer<snorm float> BufSNormF32;
39+
// TODO: AppendStructuredBuffer<unorm float> BufUNormF32;
40+
// TODO: AppendStructuredBuffer<snorm double> BufSNormF64;
41+
// TODO: AppendStructuredBuffer<unorm double> BufUNormF64;
42+
AppendStructuredBuffer<MyStruct> BufMyStruct;
43+
44+
[numthreads(1,1,1)]
45+
void main(int GI : SV_GroupIndex) {
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
struct MyStruct {
4+
float4 a;
5+
int2 b;
6+
};
7+
8+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", i16, 1, 0)
9+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.0" = type { target("dx.RawBuffer", i16, 1, 0)
10+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.1" = type { target("dx.RawBuffer", i32, 1, 0)
11+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0)
12+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.3" = type { target("dx.RawBuffer", i64, 1, 0)
13+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0)
14+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.5" = type { target("dx.RawBuffer", half, 1, 0)
15+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.6" = type { target("dx.RawBuffer", float, 1, 0)
16+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.7" = type { target("dx.RawBuffer", double, 1, 0)
17+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.8" = type { target("dx.RawBuffer", <4 x i16>, 1, 0)
18+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.9" = type { target("dx.RawBuffer", <3 x i32>, 1, 0)
19+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.10" = type { target("dx.RawBuffer", <2 x half>, 1, 0)
20+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.11" = type { target("dx.RawBuffer", <3 x float>, 1, 0)
21+
// DXIL: %"class.hlsl::ConsumeStructuredBuffer.12" = type { target("dx.RawBuffer", %struct.MyStruct = type { <4 x float>, <2 x i32>, [8 x i8] }, 1, 0)
22+
23+
ConsumeStructuredBuffer<int16_t> BufI16;
24+
ConsumeStructuredBuffer<uint16_t> BufU16;
25+
ConsumeStructuredBuffer<int> BufI32;
26+
ConsumeStructuredBuffer<uint> BufU32;
27+
ConsumeStructuredBuffer<int64_t> BufI64;
28+
ConsumeStructuredBuffer<uint64_t> BufU64;
29+
ConsumeStructuredBuffer<half> BufF16;
30+
ConsumeStructuredBuffer<float> BufF32;
31+
ConsumeStructuredBuffer<double> BufF64;
32+
ConsumeStructuredBuffer< vector<int16_t, 4> > BufI16x4;
33+
ConsumeStructuredBuffer< vector<uint, 3> > BufU32x3;
34+
ConsumeStructuredBuffer<half2> BufF16x2;
35+
ConsumeStructuredBuffer<float3> BufF32x3;
36+
// TODO: ConsumeStructuredBuffer<snorm half> BufSNormF16;
37+
// TODO: ConsumeStructuredBuffer<unorm half> BufUNormF16;
38+
// TODO: ConsumeStructuredBuffer<snorm float> BufSNormF32;
39+
// TODO: ConsumeStructuredBuffer<unorm float> BufUNormF32;
40+
// TODO: ConsumeStructuredBuffer<snorm double> BufSNormF64;
41+
// TODO: ConsumeStructuredBuffer<unorm double> BufUNormF64;
42+
ConsumeStructuredBuffer<MyStruct> BufMyStruct;
43+
44+
[numthreads(1,1,1)]
45+
void main(int GI : SV_GroupIndex) {
46+
}

0 commit comments

Comments
 (0)