Skip to content

Commit d6344c1

Browse files
s-perronKeenuts
andauthored
[HLSL][SPIRV] Add HLSL type translation for spirv. (llvm#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 <[email protected]>
1 parent 76c1665 commit d6344c1

File tree

2 files changed

+110
-14
lines changed

2 files changed

+110
-14
lines changed

clang/lib/CodeGen/Targets/SPIR.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
5252

5353
unsigned getOpenCLKernelCallingConv() const override;
5454
llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override;
55+
llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty) const override;
56+
llvm::Type *getSPIRVImageTypeFromHLSLResource(
57+
const HLSLAttributedResourceType::Attributes &attributes,
58+
llvm::Type *ElementType, llvm::LLVMContext &Ctx) const;
5559
};
5660
class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
5761
public:
@@ -323,6 +327,81 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM,
323327
return nullptr;
324328
}
325329

330+
llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM,
331+
const Type *Ty) const {
332+
auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty);
333+
if (!ResType)
334+
return nullptr;
335+
336+
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
337+
const HLSLAttributedResourceType::Attributes &ResAttrs = ResType->getAttrs();
338+
switch (ResAttrs.ResourceClass) {
339+
case llvm::dxil::ResourceClass::UAV:
340+
case llvm::dxil::ResourceClass::SRV: {
341+
// TypedBuffer and RawBuffer both need element type
342+
QualType ContainedTy = ResType->getContainedType();
343+
if (ContainedTy.isNull())
344+
return nullptr;
345+
346+
assert(!ResAttrs.RawBuffer &&
347+
"Raw buffers handles are not implemented for SPIR-V yet");
348+
assert(!ResAttrs.IsROV &&
349+
"Rasterizer order views not implemented for SPIR-V yet");
350+
351+
// convert element type
352+
llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy);
353+
return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx);
354+
}
355+
case llvm::dxil::ResourceClass::CBuffer:
356+
llvm_unreachable("CBuffer handles are not implemented for SPIR-V yet");
357+
break;
358+
case llvm::dxil::ResourceClass::Sampler:
359+
return llvm::TargetExtType::get(Ctx, "spirv.Sampler");
360+
}
361+
return nullptr;
362+
}
363+
364+
llvm::Type *CommonSPIRTargetCodeGenInfo::getSPIRVImageTypeFromHLSLResource(
365+
const HLSLAttributedResourceType::Attributes &attributes,
366+
llvm::Type *ElementType, llvm::LLVMContext &Ctx) const {
367+
368+
if (ElementType->isVectorTy())
369+
ElementType = ElementType->getScalarType();
370+
371+
assert((ElementType->isIntegerTy() || ElementType->isFloatingPointTy()) &&
372+
"The element type for a SPIR-V resource must be a scalar integer or "
373+
"floating point type.");
374+
375+
// These parameters correspond to the operands to the OpTypeImage SPIR-V
376+
// instruction. See
377+
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage.
378+
SmallVector<unsigned, 6> IntParams(6, 0);
379+
380+
// Dim
381+
// For now we assume everything is a buffer.
382+
IntParams[0] = 5;
383+
384+
// Depth
385+
// HLSL does not indicate if it is a depth texture or not, so we use unknown.
386+
IntParams[1] = 2;
387+
388+
// Arrayed
389+
IntParams[2] = 0;
390+
391+
// MS
392+
IntParams[3] = 0;
393+
394+
// Sampled
395+
IntParams[4] =
396+
attributes.ResourceClass == llvm::dxil::ResourceClass::UAV ? 2 : 1;
397+
398+
// Image format.
399+
// Setting to unknown for now.
400+
IntParams[5] = 0;
401+
402+
return llvm::TargetExtType::get(Ctx, "spirv.Image", {ElementType}, IntParams);
403+
}
404+
326405
std::unique_ptr<TargetCodeGenInfo>
327406
CodeGen::createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM) {
328407
return std::make_unique<CommonSPIRTargetCodeGenInfo>(CGM.getTypes());

clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,39 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s
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+
// RUN: %clang_cc1 -triple spirv-pc-vulkan-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s -check-prefixes=SPIRV
23

34
// NOTE: The type name number and whether the struct is packed or not will mostly
45
// likely change once subscript operators are properly implemented (llvm/llvm-project#95956)
56
// and theinterim field of the contained type is removed.
67

7-
// CHECK: %"class.hlsl::RWBuffer" = type <{ target("dx.TypedBuffer", i16, 1, 0, 1)
8-
// CHECK: %"class.hlsl::RWBuffer.0" = type <{ target("dx.TypedBuffer", i16, 1, 0, 0)
9-
// CHECK: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 1)
10-
// CHECK: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 0)
11-
// CHECK: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 1)
12-
// CHECK: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", i64, 1, 0, 0)
13-
// CHECK: %"class.hlsl::RWBuffer.6" = type <{ target("dx.TypedBuffer", half, 1, 0, 0)
14-
// CHECK: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", float, 1, 0, 0)
15-
// CHECK: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", double, 1, 0, 0)
16-
// CHECK: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 0)
17-
// CHECK: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0)
18-
// CHECK: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0)
19-
// CHECK: %"class.hlsl::RWBuffer.13" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0)
8+
// DXIL: %"class.hlsl::RWBuffer" = type <{ target("dx.TypedBuffer", i16, 1, 0, 1)
9+
// DXIL: %"class.hlsl::RWBuffer.0" = type <{ target("dx.TypedBuffer", i16, 1, 0, 0)
10+
// DXIL: %"class.hlsl::RWBuffer.2" = type { target("dx.TypedBuffer", i32, 1, 0, 1)
11+
// DXIL: %"class.hlsl::RWBuffer.3" = type { target("dx.TypedBuffer", i32, 1, 0, 0)
12+
// DXIL: %"class.hlsl::RWBuffer.4" = type { target("dx.TypedBuffer", i64, 1, 0, 1)
13+
// DXIL: %"class.hlsl::RWBuffer.5" = type { target("dx.TypedBuffer", i64, 1, 0, 0)
14+
// DXIL: %"class.hlsl::RWBuffer.6" = type <{ target("dx.TypedBuffer", half, 1, 0, 0)
15+
// DXIL: %"class.hlsl::RWBuffer.8" = type { target("dx.TypedBuffer", float, 1, 0, 0)
16+
// DXIL: %"class.hlsl::RWBuffer.9" = type { target("dx.TypedBuffer", double, 1, 0, 0)
17+
// DXIL: %"class.hlsl::RWBuffer.10" = type { target("dx.TypedBuffer", <4 x i16>, 1, 0, 0)
18+
// DXIL: %"class.hlsl::RWBuffer.11" = type { target("dx.TypedBuffer", <3 x i32>, 1, 0, 0)
19+
// DXIL: %"class.hlsl::RWBuffer.12" = type { target("dx.TypedBuffer", <2 x half>, 1, 0, 0)
20+
// DXIL: %"class.hlsl::RWBuffer.13" = type { target("dx.TypedBuffer", <3 x float>, 1, 0, 0)
21+
22+
// SPIRV: %"class.hlsl::RWBuffer" = type <{ target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), i16, [6 x i8] }>
23+
// SPIRV: %"class.hlsl::RWBuffer.0" = type <{ target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), i16, [6 x i8] }>
24+
// SPIRV: %"class.hlsl::RWBuffer.2" = type <{ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), i32, [4 x i8] }>
25+
// SPIRV: %"class.hlsl::RWBuffer.4" = type <{ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), i32, [4 x i8] }>
26+
// SPIRV: %"class.hlsl::RWBuffer.6" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0), i64 }
27+
// SPIRV: %"class.hlsl::RWBuffer.7" = type { target("spirv.Image", i64, 5, 2, 0, 0, 2, 0), i64 }
28+
// SPIRV: %"class.hlsl::RWBuffer.8" = type <{ target("spirv.Image", half, 5, 2, 0, 0, 2, 0), half, [6 x i8] }>
29+
// SPIRV: %"class.hlsl::RWBuffer.10" = type <{ target("spirv.Image", float, 5, 2, 0, 0, 2, 0), float, [4 x i8] }>
30+
// SPIRV: %"class.hlsl::RWBuffer.12" = type { target("spirv.Image", double, 5, 2, 0, 0, 2, 0), double }
31+
// SPIRV: %"class.hlsl::RWBuffer.13" = type { target("spirv.Image", i16, 5, 2, 0, 0, 2, 0), <4 x i16> }
32+
// SPIRV: %"class.hlsl::RWBuffer.14" = type { target("spirv.Image", i32, 5, 2, 0, 0, 2, 0), <3 x i32> }
33+
// SPIRV: %"class.hlsl::RWBuffer.15" = type <{ target("spirv.Image", half, 5, 2, 0, 0, 2, 0), <2 x half>, [4 x i8] }>
34+
// SPIRV: %"class.hlsl::RWBuffer.17" = type { target("spirv.Image", float, 5, 2, 0, 0, 2, 0), <3 x float> }
35+
36+
2037

2138
RWBuffer<int16_t> BufI16;
2239
RWBuffer<uint16_t> BufU16;

0 commit comments

Comments
 (0)