Author: Steven Perron Date: 2025-04-01T16:59:46-04:00 New Revision: 16603d838c0dfa6881f9b8118c5a0b5ac2789752
URL: https://github.com/llvm/llvm-project/commit/16603d838c0dfa6881f9b8118c5a0b5ac2789752 DIFF: https://github.com/llvm/llvm-project/commit/16603d838c0dfa6881f9b8118c5a0b5ac2789752.diff LOG: [HLSL] Add SPIR-V target type for RWStructuredBuffers (#133468) This PR adds the target type for main storage for HLSL raw buffer types. It does not handle the counter variables that are associated with those buffers. This is implementing part of https://github.com/llvm/wg-hlsl/blob/main/proposals/0018-spirv-resource-representation.md. We do not handle other HLSL raw buffer types. Added: Modified: clang/lib/CodeGen/Targets/SPIR.cpp clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl Removed: ################################################################################ diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index 43f511e572d37..225d9dfbd980b 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -386,14 +386,21 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType( if (ContainedTy.isNull()) return nullptr; - assert(!ResAttrs.RawBuffer && - "Raw buffers handles are not implemented for SPIR-V yet"); assert(!ResAttrs.IsROV && "Rasterizer order views not implemented for SPIR-V yet"); - // convert element type llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy); - return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx); + if (!ResAttrs.RawBuffer) { + // convert element type + return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx); + } + + llvm::ArrayType *RuntimeArrayType = llvm::ArrayType::get(ElemType, 0); + uint32_t StorageClass = /* StorageBuffer storage class */ 12; + bool IsWritable = ResAttrs.ResourceClass == llvm::dxil::ResourceClass::UAV; + return llvm::TargetExtType::get(Ctx, "spirv.VulkanBuffer", + {RuntimeArrayType}, + {StorageClass, IsWritable}); } case llvm::dxil::ResourceClass::CBuffer: llvm_unreachable("CBuffer handles are not implemented for SPIR-V yet"); diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl index 04534c5550252..8a1429fd1a6fc 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl @@ -1,59 +1,70 @@ // 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 +// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -DSPIRV -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -// NOTE: SPIRV codegen for resource types is not yet implemented StructuredBuffer<float> Buf : register(t10); RWStructuredBuffer<float> Buf2 : register(u5, space1); + +#ifndef SPIRV +// NOTE: SPIRV codegen for these resource types is not implemented yet. AppendStructuredBuffer<float> Buf3 : register(u3); ConsumeStructuredBuffer<float> Buf4 : register(u4); RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2); +#endif + +// CHECK-DXIL: %"class.hlsl::StructuredBuffer" = type { target("dx.RawBuffer", float, 0, 0) } +// CHECK-DXIL: %"class.hlsl::RWStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } +// CHECK-DXIL: %"class.hlsl::AppendStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } +// CHECK-DXIL: %"class.hlsl::ConsumeStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 0) } +// CHECK-DXIL: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1) } + +// CHECK-SPIRV: %"class.hlsl::StructuredBuffer" = type { target("spirv.VulkanBuffer", [0 x float], 12, 0) } +// CHECK-SPIRV: %"class.hlsl::RWStructuredBuffer" = type { target("spirv.VulkanBuffer", [0 x float], 12, 1) } -// 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) } -// CHECK: %"class.hlsl::RasterizerOrderedStructuredBuffer" = type { target("dx.RawBuffer", float, 1, 1) } -// CHECK: @_ZL3Buf = internal global %"class.hlsl::StructuredBuffer" poison, align 4 -// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison, align 4 -// CHECK: @_ZL4Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" poison, align 4 -// CHECK: @_ZL4Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" poison, align 4 -// CHECK: @_ZL4Buf5 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4 +// CHECK: @_ZL3Buf = internal global %"class.hlsl::StructuredBuffer" poison +// CHECK: @_ZL4Buf2 = internal global %"class.hlsl::RWStructuredBuffer" poison +// CHECK-DXIL: @_ZL4Buf3 = internal global %"class.hlsl::AppendStructuredBuffer" poison, align 4 +// CHECK-DXIL: @_ZL4Buf4 = internal global %"class.hlsl::ConsumeStructuredBuffer" poison, align 4 +// CHECK-DXIL: @_ZL4Buf5 = internal global %"class.hlsl::RasterizerOrderedStructuredBuffer" poison, align 4 // CHECK: define internal void @_init_resource__ZL3Buf() // 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) // CHECK-DXIL: store target("dx.RawBuffer", float, 0, 0) [[H]], ptr @_ZL3Buf, align 4 +// CHECK-SPIRV: [[H:%.*]] = call target("spirv.VulkanBuffer", [0 x float], 12, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0f32_12_0t(i32 0, i32 10, i32 1, i32 0, i1 false) +// CHECK-SPIRV: store target("spirv.VulkanBuffer", [0 x float], 12, 0) [[H]], ptr @_ZL3Buf, align 8 // CHECK: define internal void @_init_resource__ZL4Buf2() // 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) // CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) [[H]], ptr @_ZL4Buf2, align 4 +// CHECK-SPIRV: [[H:%.*]] = call target("spirv.VulkanBuffer", [0 x float], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0f32_12_1t(i32 1, i32 5, i32 1, i32 0, i1 false) +// CHECK-SPIRV: store target("spirv.VulkanBuffer", [0 x float], 12, 1) [[H]], ptr @_ZL4Buf2, align 8 -// CHECK: define internal void @_init_resource__ZL4Buf3() +// CHECK-DXIL: define internal void @_init_resource__ZL4Buf3() // 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) // CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) [[H]], ptr @_ZL4Buf3, align 4 -// CHECK: define internal void @_init_resource__ZL4Buf4() +// CHECK-DXIL: define internal void @_init_resource__ZL4Buf4() // 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) // CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) [[H]], ptr @_ZL4Buf4, align 4 -// CHECK: define internal void @_init_resource__ZL4Buf5() +// CHECK-DXIL: define internal void @_init_resource__ZL4Buf5() // 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) // CHECK-DXIL: store target("dx.RawBuffer", float, 1, 1) [[H]], ptr @_ZL4Buf5, align 4 -// CHECK: define linkonce_odr void @_ZN4hlsl16StructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK-NEXT: entry: -// CHECK: define linkonce_odr void @_ZN4hlsl18RWStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK-NEXT: entry: -// CHECK: define linkonce_odr void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK-NEXT: entry: -// CHECK: define linkonce_odr void @_ZN4hlsl23ConsumeStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) -// CHECK: define linkonce_odr void @_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK: define linkonce_odr void @_ZN4hlsl16StructuredBufferIfEC2Ev(ptr noundef nonnull align {{[48]}} dereferenceable({{[48]}}) %this) // CHECK-NEXT: entry: +// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl18RWStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK-DXIL-NEXT: entry: +// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl22AppendStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK-DXIL-NEXT: entry: +// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl23ConsumeStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK-DXIL: define linkonce_odr void @_ZN4hlsl33RasterizerOrderedStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this) +// CHECK-DXIL-NEXT: entry: -// CHECK: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl() -// CHECK: call void @_init_resource__ZL3Buf() -// CHECK: call void @_init_resource__ZL4Buf2() -// CHECK: call void @_init_resource__ZL4Buf3() -// CHECK: call void @_init_resource__ZL4Buf4() -// CHECK: call void @_init_resource__ZL4Buf5() +// CHECK: define {{.*}} void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl() +// CHECK: call {{.*}} @_init_resource__ZL3Buf() +// CHECK: call {{.*}} @_init_resource__ZL4Buf2() +// CHECK-DXIL: call void @_init_resource__ZL4Buf3() +// CHECK-DXIL: call void @_init_resource__ZL4Buf4() +// CHECK-DXIL: call void @_init_resource__ZL4Buf5() _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits