Author: Steven Perron Date: 2024-11-04T12:32:23-05:00 New Revision: d6344c1cd0d099f8d99ee320f33fc9254dbe8288
URL: https://github.com/llvm/llvm-project/commit/d6344c1cd0d099f8d99ee320f33fc9254dbe8288 DIFF: https://github.com/llvm/llvm-project/commit/d6344c1cd0d099f8d99ee320f33fc9254dbe8288.diff LOG: [HLSL][SPIRV] Add HLSL type translation for spirv. (#114273) This commit partially implements SPIRTargetCodeGenInfo::getHLSLType. It can now generate the spirv type for the following HLSL types: 1. RWBuffer 2. Buffer 3. Sampler --------- Co-authored-by: Nathan Gauër <git...@keenuts.net> Added: Modified: clang/lib/CodeGen/Targets/SPIR.cpp clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl Removed: ################################################################################ diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index 7dd5c518e7149a..a48fe9d5f1ee9c 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -52,6 +52,10 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo { unsigned getOpenCLKernelCallingConv() const override; llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override; + llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty) const override; + llvm::Type *getSPIRVImageTypeFromHLSLResource( + const HLSLAttributedResourceType::Attributes &attributes, + llvm::Type *ElementType, llvm::LLVMContext &Ctx) const; }; class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo { public: @@ -323,6 +327,81 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM, return nullptr; } +llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM, + const Type *Ty) const { + auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty); + if (!ResType) + return nullptr; + + llvm::LLVMContext &Ctx = CGM.getLLVMContext(); + const HLSLAttributedResourceType::Attributes &ResAttrs = ResType->getAttrs(); + switch (ResAttrs.ResourceClass) { + case llvm::dxil::ResourceClass::UAV: + case llvm::dxil::ResourceClass::SRV: { + // TypedBuffer and RawBuffer both need element type + QualType ContainedTy = ResType->getContainedType(); + 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); + } + case llvm::dxil::ResourceClass::CBuffer: + llvm_unreachable("CBuffer handles are not implemented for SPIR-V yet"); + break; + case llvm::dxil::ResourceClass::Sampler: + return llvm::TargetExtType::get(Ctx, "spirv.Sampler"); + } + return nullptr; +} + +llvm::Type *CommonSPIRTargetCodeGenInfo::getSPIRVImageTypeFromHLSLResource( + const HLSLAttributedResourceType::Attributes &attributes, + llvm::Type *ElementType, llvm::LLVMContext &Ctx) const { + + if (ElementType->isVectorTy()) + ElementType = ElementType->getScalarType(); + + assert((ElementType->isIntegerTy() || ElementType->isFloatingPointTy()) && + "The element type for a SPIR-V resource must be a scalar integer or " + "floating point type."); + + // These parameters correspond to the operands to the OpTypeImage SPIR-V + // instruction. See + // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage. + SmallVector<unsigned, 6> IntParams(6, 0); + + // Dim + // For now we assume everything is a buffer. + IntParams[0] = 5; + + // Depth + // HLSL does not indicate if it is a depth texture or not, so we use unknown. + IntParams[1] = 2; + + // Arrayed + IntParams[2] = 0; + + // MS + IntParams[3] = 0; + + // Sampled + IntParams[4] = + attributes.ResourceClass == llvm::dxil::ResourceClass::UAV ? 2 : 1; + + // Image format. + // Setting to unknown for now. + IntParams[5] = 0; + + return llvm::TargetExtType::get(Ctx, "spirv.Image", {ElementType}, IntParams); +} + std::unique_ptr<TargetCodeGenInfo> CodeGen::createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM) { return std::make_unique<CommonSPIRTargetCodeGenInfo>(CGM.getTypes()); diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl index 16120a44a9e4d2..d737d76a9d8d97 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl @@ -1,22 +1,39 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=DXIL +// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPIRV // NOTE: The type name number and whether the struct is packed or not will mostly // likely change once subscript operators are properly implemented (llvm/llvm-project#95956) // and theinterim field of the contained type is removed. -// CHECK: %"class.hlsl::RWBuffer" = type <{ target("dx.TypedBuffer", i16, 1, 0, 1) -// CHECK: %"class.hlsl::RWBuffer.0" = type <{ target("dx.TypedBuffer", i16, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 1) -// CHECK: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 1) -// CHECK: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", i64, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.6" = type <{ target("dx.TypedBuffer", half, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", float, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", double, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0) -// CHECK: %"class.hlsl::RWBuffer.13" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer" = type <{ target("dx.TypedBuffer", i16, 1, 0, 1) +// DXIL: %"class.hlsl::RWBuffer.0" = type <{ target("dx.TypedBuffer", i16, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 1) +// DXIL: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 1) +// DXIL: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", i64, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.6" = type <{ target("dx.TypedBuffer", half, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", float, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", double, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0) +// DXIL: %"class.hlsl::RWBuffer.13" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0) + +// SPIRV: %"class.hlsl::RWBuffer" = type <{ target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), i16, [6 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.0" = type <{ target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), i16, [6 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.2" = type <{ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), i32, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.4" = type <{ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), i32, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0), i64 } +// SPIRV: %"class.hlsl::RWBuffer.7" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0), i64 } +// SPIRV: %"class.hlsl::RWBuffer.8" = type <{ target("spirv.Image", half, 5, 2, 0, 0, 2, 0), half, [6 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.10" = type <{ target("spirv.Image", float, 5, 2, 0, 0, 2, 0), float, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.12" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0), double } +// SPIRV: %"class.hlsl::RWBuffer.13" = type { target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), <4 x i16> } +// SPIRV: %"class.hlsl::RWBuffer.14" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), <3 x i32> } +// SPIRV: %"class.hlsl::RWBuffer.15" = type <{ target("spirv.Image", half, 5, 2, 0, 0, 2, 0), <2 x half>, [4 x i8] }> +// SPIRV: %"class.hlsl::RWBuffer.17" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0), <3 x float> } + + RWBuffer<int16_t> BufI16; RWBuffer<uint16_t> BufU16; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits