Skip to content

Commit d56c416

Browse files
committed
[HLSL] Add SPIR-V target type for RWStructuredBuffers
This PR adds the target type that should be used for RWStructuredBuffers. It does not handle ByteAddressBuffers yet. For now all structs will be laid out using the standard C/C++ layout rules. Other layout rules will be implemented later.
1 parent 58027fa commit d56c416

File tree

2 files changed

+58
-33
lines changed

2 files changed

+58
-33
lines changed

clang/lib/CodeGen/Targets/SPIR.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,13 +386,30 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(
386386
if (ContainedTy.isNull())
387387
return nullptr;
388388

389-
assert(!ResAttrs.RawBuffer &&
390-
"Raw buffers handles are not implemented for SPIR-V yet");
391389
assert(!ResAttrs.IsROV &&
392390
"Rasterizer order views not implemented for SPIR-V yet");
393391

394-
// convert element type
395392
llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy);
393+
if (ResAttrs.RawBuffer) {
394+
// TODO: Handle types with layout information.
395+
assert((ElemType->isIntegerTy() || ElemType->isFloatingPointTy() ||
396+
ElemType->isVectorTy()) &&
397+
"The element type for a SPIR-V resource must be a types that does "
398+
"not require layout information.");
399+
llvm::ArrayType *RuntimeArrayType = llvm::ArrayType::get(ElemType, 0);
400+
401+
uint32_t StorageClass = /* StorageBuffer storage class */ 12;
402+
bool IsWritable =
403+
ResAttrs.ResourceClass == llvm::dxil::ResourceClass::UAV;
404+
assert(!IsWritable && "Writable buffers require a corresponding counter "
405+
"variable. Not implemented yet.");
406+
bool IsRov = ResAttrs.IsROV;
407+
return llvm::TargetExtType::get(Ctx, "spirv.VulkanBuffer",
408+
{RuntimeArrayType},
409+
{StorageClass, IsWritable, IsRov});
410+
}
411+
412+
// convert element type
396413
return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx);
397414
}
398415
case llvm::dxil::ResourceClass::CBuffer:
Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,67 @@
11
// 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
2-
// RUN-DISABLED: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
2+
// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -DSPIRV -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
33

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

65
StructuredBuffer<float> Buf : register(t10);
6+
7+
#ifndef SPIRV
8+
// NOTE: SPIRV codegen for resource types with counter variable is not yet implemented
79
RWStructuredBuffer<float> Buf2 : register(u5, space1);
810
AppendStructuredBuffer<float> Buf3 : register(u3);
911
ConsumeStructuredBuffer<float> Buf4 : register(u4);
1012
RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2);
13+
#endif
14+
15+
// CHECK-DXIL: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
16+
// CHECK-DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
17+
// CHECK-DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
18+
// CHECK-DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
19+
// CHECK-DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1) }
20+
21+
// CHECK-SPIRV: %"class.hlsl::StructuredBuffer" = type { target("spirv.VulkanBuffer", [0 x float], 12, 0, 0) }
1122

12-
// CHECK: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) }
13-
// CHECK: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
14-
// CHECK: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
15-
// CHECK: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) }
16-
// CHECK: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1) }
1723

18-
// CHECK: @_ZL3Buf = internal global %"class.hlsl::StructuredBuffer" poison, align 4
19-
// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
20-
// CHECK: @_ZL4Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" poison, align 4
21-
// CHECK: @_ZL4Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" poison, align 4
22-
// CHECK: @_ZL4Buf5 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4
24+
// CHECK: @_ZL3Buf = internal global %"class.hlsl::StructuredBuffer" poison
25+
// CHECK-DXIL: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4
26+
// CHECK-DXIL: @_ZL4Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" poison, align 4
27+
// CHECK-DXIL: @_ZL4Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" poison, align 4
28+
// CHECK-DXIL: @_ZL4Buf5 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4
2329

2430
// CHECK: define internal void @_init_resource__ZL3Buf()
2531
// CHECK-DXIL: [[H:%.*]] = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false)
2632
// CHECK-DXIL: store target("dx.RawBuffer", float, 0, 0) [[H]], ptr @_ZL3Buf, align 4
33+
// CHECK-SPIRV: [[H:%.*]] = call target("spirv.VulkanBuffer", [0 x float], 12, 0, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0f32_12_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false)
34+
// CHECK-SPIRV: store target("spirv.VulkanBuffer", [0 x float], 12, 0, 0) [[H]], ptr @_ZL3Buf, align 8
2735

28-
// CHECK: define internal void @_init_resource__ZL4Buf2()
36+
// CHECK-DXIL: define internal void @_init_resource__ZL4Buf2()
2937
// CHECK-DXIL: [[H:%.*]] = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false)
3038
// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) [[H]], ptr @_ZL4Buf2, align 4
3139

32-
// CHECK: define internal void @_init_resource__ZL4Buf3()
40+
// CHECK-DXIL: define internal void @_init_resource__ZL4Buf3()
3341
// CHECK-DXIL: [[H:%.*]] = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false)
3442
// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) [[H]], ptr @_ZL4Buf3, align 4
3543

36-
// CHECK: define internal void @_init_resource__ZL4Buf4()
44+
// CHECK-DXIL: define internal void @_init_resource__ZL4Buf4()
3745
// CHECK-DXIL: [[H:%.*]] = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false)
3846
// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) [[H]], ptr @_ZL4Buf4, align 4
3947

40-
// CHECK: define internal void @_init_resource__ZL4Buf5()
48+
// CHECK-DXIL: define internal void @_init_resource__ZL4Buf5()
4149
// CHECK-DXIL: [[H:%.*]] = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false)
4250
// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 1) [[H]], ptr @_ZL4Buf5, align 4
4351

44-
// CHECK: define linkonce_odr void @_ZN4hlsl16StructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
45-
// CHECK-NEXT: entry:
46-
// CHECK: define linkonce_odr void @_ZN4hlsl18RWStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
47-
// CHECK-NEXT: entry:
48-
// CHECK: define linkonce_odr void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
49-
// CHECK-NEXT: entry:
50-
// CHECK: define linkonce_odr void @_ZN4hlsl23ConsumeStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
51-
// CHECK: define linkonce_odr void @_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
52+
// CHECK: define linkonce_odr void @_ZN4hlsl16StructuredBufferIfEC2Ev(ptr noundef nonnull align {{[48]}} dereferenceable({{[48]}}) %this)
5253
// CHECK-NEXT: entry:
54+
// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl18RWStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
55+
// CHECK-DXIL-NEXT: entry:
56+
// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
57+
// CHECK-DXIL-NEXT: entry:
58+
// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl23ConsumeStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
59+
// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
60+
// CHECK-DXIL-NEXT: entry:
5361

54-
// CHECK: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
55-
// CHECK: call void @_init_resource__ZL3Buf()
56-
// CHECK: call void @_init_resource__ZL4Buf2()
57-
// CHECK: call void @_init_resource__ZL4Buf3()
58-
// CHECK: call void @_init_resource__ZL4Buf4()
59-
// CHECK: call void @_init_resource__ZL4Buf5()
62+
// CHECK: define {{.*}} void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
63+
// CHECK: call {{.*}} @_init_resource__ZL3Buf()
64+
// CHECK-DXIL: call void @_init_resource__ZL4Buf2()
65+
// CHECK-DXIL: call void @_init_resource__ZL4Buf3()
66+
// CHECK-DXIL: call void @_init_resource__ZL4Buf4()
67+
// CHECK-DXIL: call void @_init_resource__ZL4Buf5()

0 commit comments

Comments
 (0)