-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[HLSL][SPIRV] Add HLSL type translation for spirv. #114273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Steven Perron (s-perron) ChangesThis commit partially implements SPIRTargetCodeGenInfo::getHLSLType. It can now generate the spirv type for the following HLSL types:
Full diff: https://github.com/llvm/llvm-project/pull/114273.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index 7dd5c518e7149a..e6921d65084701 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,83 @@ 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();
+ }
+
+ if (!ElementType->isIntegerTy() && !ElementType->isFloatingPointTy()) {
+ // TODO: Should there be an error message?
+ ElementType->dump();
+ assert(false && "Bad element type");
+ return nullptr;
+ }
+
+ // For HLSL types, the depth is always 2.
+ SmallVector<unsigned, 6> IntParams = {0, 2, 0, 0, 1, 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 fa81b53fd9bddc..374f600c75534b 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,COMMON
+// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPIRV,COMMON
// 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;
@@ -55,16 +72,16 @@ void main(int GI : SV_GroupIndex) {
BufF32x3[GI] = 0;
}
-// CHECK: !{{[0-9]+}} = !{ptr @BufI16, i32 10, i32 2,
-// CHECK: !{{[0-9]+}} = !{ptr @BufU16, i32 10, i32 3,
-// CHECK: !{{[0-9]+}} = !{ptr @BufI32, i32 10, i32 4,
-// CHECK: !{{[0-9]+}} = !{ptr @BufU32, i32 10, i32 5,
-// CHECK: !{{[0-9]+}} = !{ptr @BufI64, i32 10, i32 6,
-// CHECK: !{{[0-9]+}} = !{ptr @BufU64, i32 10, i32 7,
-// CHECK: !{{[0-9]+}} = !{ptr @BufF16, i32 10, i32 8,
-// CHECK: !{{[0-9]+}} = !{ptr @BufF32, i32 10, i32 9,
-// CHECK: !{{[0-9]+}} = !{ptr @BufF64, i32 10, i32 10,
-// CHECK: !{{[0-9]+}} = !{ptr @BufI16x4, i32 10, i32 2,
-// CHECK: !{{[0-9]+}} = !{ptr @BufU32x3, i32 10, i32 5,
-// CHECK: !{{[0-9]+}} = !{ptr @BufF16x2, i32 10, i32 8,
-// CHECK: !{{[0-9]+}} = !{ptr @BufF32x3, i32 10, i32 9,
+// COMMON: !{{[0-9]+}} = !{ptr @BufI16, i32 10, i32 2,
+// COMMON: !{{[0-9]+}} = !{ptr @BufU16, i32 10, i32 3,
+// COMMON: !{{[0-9]+}} = !{ptr @BufI32, i32 10, i32 4,
+// COMMON: !{{[0-9]+}} = !{ptr @BufU32, i32 10, i32 5,
+// COMMON: !{{[0-9]+}} = !{ptr @BufI64, i32 10, i32 6,
+// COMMON: !{{[0-9]+}} = !{ptr @BufU64, i32 10, i32 7,
+// COMMON: !{{[0-9]+}} = !{ptr @BufF16, i32 10, i32 8,
+// COMMON: !{{[0-9]+}} = !{ptr @BufF32, i32 10, i32 9,
+// COMMON: !{{[0-9]+}} = !{ptr @BufF64, i32 10, i32 10,
+// COMMON: !{{[0-9]+}} = !{ptr @BufI16x4, i32 10, i32 2,
+// COMMON: !{{[0-9]+}} = !{ptr @BufU32x3, i32 10, i32 5,
+// COMMON: !{{[0-9]+}} = !{ptr @BufF16x2, i32 10, i32 8,
+// COMMON: !{{[0-9]+}} = !{ptr @BufF32x3, i32 10, i32 9,
|
916fdfd
to
689f8d6
Compare
This commit partially implements SPIRTargetCodeGenInfo::getHLSLType. It can now generate the spirv type for the following HLSL types: 1. RWBuffer 2. Buffer 3. Sampler # Conflicts: # clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl
281dabb
to
d62b540
Compare
Co-authored-by: Nathan Gauër <github@keenuts.net>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
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 <github@keenuts.net>
This commit partially implements SPIRTargetCodeGenInfo::getHLSLType. It can now generate the spirv type for the following HLSL types: