Skip to content

[DirectX] Update resource type names in DXIL metadata to include element type #140937

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

Open
wants to merge 4 commits into
base: users/hekota/pr140635-resource-names-to-metadata
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/DXILResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class ResourceTypeInfo {
: ResourceTypeInfo(HandleTy, {}, dxil::ResourceKind::Invalid) {}

TargetExtType *getHandleTy() const { return HandleTy; }
StructType *createElementStruct();
StructType *createElementStruct(StringRef CBufferName = "");

// Conditions to check before accessing specific views.
bool isUAV() const;
Expand Down
122 changes: 101 additions & 21 deletions llvm/lib/Analysis/DXILResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ static StringRef getResourceKindName(ResourceKind RK) {
case ResourceKind::TextureCubeArray:
return "TextureCubeArray";
case ResourceKind::TypedBuffer:
return "TypedBuffer";
return "Buffer";
case ResourceKind::RawBuffer:
return "RawBuffer";
case ResourceKind::StructuredBuffer:
Expand Down Expand Up @@ -132,6 +132,44 @@ static StringRef getElementTypeName(ElementType ET) {
llvm_unreachable("Unhandled ElementType");
}

static StringRef getElementTypeNameForTemplate(ElementType ET) {
switch (ET) {
case ElementType::I1:
return "bool";
case ElementType::I16:
return "int16_t";
case ElementType::U16:
return "uint16_t";
case ElementType::I32:
return "int32_t";
case ElementType::U32:
return "uint32_t";
case ElementType::I64:
return "int64_t";
case ElementType::U64:
return "uint32_t";
case ElementType::F16:
case ElementType::SNormF16:
case ElementType::UNormF16:
return "half";
case ElementType::F32:
case ElementType::SNormF32:
case ElementType::UNormF32:
return "float";
case ElementType::F64:
case ElementType::SNormF64:
case ElementType::UNormF64:
return "double";
case ElementType::PackedS8x32:
return "int8_t4_packed";
case ElementType::PackedU8x32:
return "uint8_t4_packed";
case ElementType::Invalid:
return "<invalid>";
}
llvm_unreachable("Unhandled ElementType");
}

static StringRef getSamplerTypeName(SamplerType ST) {
switch (ST) {
case SamplerType::Default:
Expand Down Expand Up @@ -219,12 +257,44 @@ ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy,
}

static void formatTypeName(SmallString<64> &Dest, StringRef Name,
bool isWriteable, bool isROV) {
Dest = isWriteable ? (isROV ? "RasterizerOrdered" : "RW") : "";
Dest += Name;
bool IsWriteable, bool IsROV,
Type *ContainedType = nullptr,
bool IsSigned = true) {
raw_svector_ostream DestStream(Dest);
if (IsWriteable)
DestStream << (IsROV ? "RasterizerOrdered" : "RW");
DestStream << Name;

if (!ContainedType)
return;

StringRef ElementName;
ElementType ET = toDXILElementType(ContainedType, IsSigned);
if (ET != ElementType::Invalid) {
Copy link
Contributor

@V-FEXrt V-FEXrt May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have a test covering both branches here? I'm not exactly sure what's happening when ET isn't invalid or what the nominal flow is

ElementName = getElementTypeNameForTemplate(ET);
} else {
assert(isa<StructType>(ContainedType) &&
"invalid element type for raw buffer");
StructType *ST = cast<StructType>(ContainedType);
if (!ST->hasName())
return;
ElementName = ST->getStructName();
}

DestStream << "<" << ElementName;
if (const FixedVectorType *VTy = dyn_cast<FixedVectorType>(ContainedType))
DestStream << VTy->getNumElements();
DestStream << ">";
}

static StructType *getOrCreateElementStruct(Type *ElemType, StringRef Name) {
StructType *Ty = StructType::getTypeByName(ElemType->getContext(), Name);
if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType)
return Ty;
return StructType::create(ElemType, Name);
}

StructType *ResourceTypeInfo::createElementStruct() {
StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) {
SmallString<64> TypeName;

switch (Kind) {
Expand All @@ -237,51 +307,61 @@ StructType *ResourceTypeInfo::createElementStruct() {
case ResourceKind::TextureCubeArray: {
auto *RTy = cast<TextureExtType>(HandleTy);
formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
RTy->isROV());
return StructType::create(RTy->getResourceType(), TypeName);
RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
}
case ResourceKind::Texture2DMS:
case ResourceKind::Texture2DMSArray: {
auto *RTy = cast<MSTextureExtType>(HandleTy);
formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
/*IsROV=*/false);
return StructType::create(RTy->getResourceType(), TypeName);
/*IsROV=*/false, RTy->getResourceType(), RTy->isSigned());
return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
}
case ResourceKind::TypedBuffer: {
auto *RTy = cast<TypedBufferExtType>(HandleTy);
formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
RTy->isROV());
return StructType::create(RTy->getResourceType(), TypeName);
RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
}
case ResourceKind::RawBuffer: {
auto *RTy = cast<RawBufferExtType>(HandleTy);
formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
RTy->isROV());
return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
TypeName);
return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
TypeName);
}
case ResourceKind::StructuredBuffer: {
auto *RTy = cast<RawBufferExtType>(HandleTy);
Type *Ty = RTy->getResourceType();
formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
RTy->isROV());
return StructType::create(RTy->getResourceType(), TypeName);
RTy->isROV(), RTy->getResourceType(), true);
return getOrCreateElementStruct(Ty, TypeName);
}
case ResourceKind::FeedbackTexture2D:
case ResourceKind::FeedbackTexture2DArray: {
auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
llvm::to_underlying(RTy->getFeedbackType()));
return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
TypeName);
return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
TypeName);
}
case ResourceKind::CBuffer: {
auto *RTy = cast<CBufferExtType>(HandleTy);
LayoutExtType *LayoutType = cast<LayoutExtType>(RTy->getResourceType());
StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
SmallString<64> Name = getResourceKindName(Kind);
if (!CBufferName.empty()) {
Name.append(".");
Name.append(CBufferName);
}
return StructType::create(Ty->elements(), Name);
}
case ResourceKind::CBuffer:
return StructType::create(HandleTy->getContext(), "cbuffer");
case ResourceKind::Sampler: {
auto *RTy = cast<SamplerExtType>(HandleTy);
TypeName = formatv("SamplerState<{0}>",
llvm::to_underlying(RTy->getSamplerType()));
return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
TypeName);
return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
TypeName);
}
case ResourceKind::TBuffer:
case ResourceKind::RTAccelerationStructure:
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ static NamedMDNode *emitResourceMetadata(Module &M, DXILResourceMap &DRM,

for (ResourceInfo &RI : DRM)
if (!RI.hasSymbol())
RI.createSymbol(M, DRTM[RI.getHandleTy()].createElementStruct());
RI.createSymbol(M,
DRTM[RI.getHandleTy()].createElementStruct(RI.getName()));

SmallVector<Metadata *> SRVs, UAVs, CBufs, Smps;
for (const ResourceInfo &RI : DRM.srvs())
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/Analysis/DXILResource/buffer-frombinding.ll
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ define void @test_typedbuffer() {
; CHECK: Lower Bound: 3
; CHECK: Size: 24
; CHECK: Class: SRV
; CHECK: Kind: TypedBuffer
; CHECK: Kind: Buffer
; CHECK: Element Type: u32
; CHECK: Element Count: 4

Expand All @@ -70,7 +70,7 @@ define void @test_typedbuffer() {
; CHECK: Globally Coherent: 0
; CHECK: Counter Direction: Unknown
; CHECK: Class: UAV
; CHECK: Kind: TypedBuffer
; CHECK: Kind: Buffer
; CHECK: IsROV: 0
; CHECK: Element Type: i32
; CHECK: Element Count: 1
Expand All @@ -89,7 +89,7 @@ define void @test_typedbuffer() {
; CHECK: Globally Coherent: 0
; CHECK: Counter Direction: Decrement
; CHECK: Class: UAV
; CHECK: Kind: TypedBuffer
; CHECK: Kind: Buffer
; CHECK: IsROV: 0
; CHECK: Element Type: f32
; CHECK: Element Count: 4
Expand All @@ -112,7 +112,7 @@ define void @test_typedbuffer() {
; CHECK: Globally Coherent: 0
; CHECK: Counter Direction: Increment
; CHECK: Class: UAV
; CHECK: Kind: TypedBuffer
; CHECK: Kind: Buffer
; CHECK: IsROV: 0
; CHECK: Element Type: f32
; CHECK: Element Count: 4
Expand All @@ -132,7 +132,7 @@ define void @test_typedbuffer() {
; CHECK: Globally Coherent: 0
; CHECK: Counter Direction: Invalid
; CHECK: Class: UAV
; CHECK: Kind: TypedBuffer
; CHECK: Kind: Buffer
; CHECK: IsROV: 0
; CHECK: Element Type: f32
; CHECK: Element Count: 4
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/DirectX/Metadata/cbuffer-only.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ target triple = "dxil-pc-shadermodel6.6-compute"
define void @cbuffer_is_only_binding() {
%cbuf = call target("dx.CBuffer", target("dx.Layout", {float}, 4, 0))
@llvm.dx.resource.handlefrombinding(i32 1, i32 8, i32 1, i32 0, i1 false, ptr null)
; CHECK: %cbuffer = type
; CHECK: %CBuffer = type { float }

ret void
}

; CHECK: @[[CB0:.*]] = external constant %cbuffer
; CHECK: @[[CB0:.*]] = external constant %CBuffer

; CHECK: !{i32 0, ptr @[[CB0]], !""
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ define void @test() #0 {

attributes #0 = { noinline nounwind "hlsl.shader"="compute" }

; CHECK: @CB1 = external constant %cbuffer
; CHECK: @CB2 = external constant %cbuffer.0
; CHECK: @MyConstants = external constant %cbuffer.1
; CHECK: @CB1 = external constant %CBuffer.CB1
; CHECK: @CB2 = external constant %CBuffer.CB2
; CHECK: @MyConstants = external constant %CBuffer.MyConstants

; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}

Expand Down
16 changes: 8 additions & 8 deletions llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ define void @test() {
; Buffer<float4>
%float4 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, i1 false, ptr @A.str)
; CHECK: %TypedBuffer = type { <4 x float> }
; CHECK: %"Buffer<float4>" = type { <4 x float> }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the " quotes around the types here? I've seen this before but I'm not the biggest fan of them stylistically. Is there something about the name that requires them? Guessing the </> are the problem?


; Buffer<int>
%int = call target("dx.TypedBuffer", i32, 0, 0, 1)
@llvm.dx.resource.handlefrombinding(i32 0, i32 1, i32 1, i32 0, i1 false, ptr null)
; CHECK: %TypedBuffer.0 = type { i32 }
; CHECK: %"Buffer<int32_t>" = type { i32 }

; Buffer<uint3>
%uint3 = call target("dx.TypedBuffer", <3 x i32>, 0, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 2, i32 1, i32 0, i1 false, ptr null)
; CHECK: %TypedBuffer.1 = type { <3 x i32> }
; CHECK: %"Buffer<uint32_t3>" = type { <3 x i32> }

; StructuredBuffer<S>
%struct0 = call target("dx.RawBuffer", %struct.S, 0, 0)
@llvm.dx.resource.handlefrombinding(i32 0, i32 10, i32 1, i32 0, i1 true, ptr @SB.str)
; CHECK: %StructuredBuffer = type { %struct.S }
; CHECK: %"StructuredBuffer<struct.S>" = type { %struct.S }

; ByteAddressBuffer
%byteaddr = call target("dx.RawBuffer", i8, 0, 0)
Expand All @@ -36,10 +36,10 @@ define void @test() {
ret void
}

; CHECK: @[[T0:.*]] = external constant %TypedBuffer
; CHECK-NEXT: @[[T1:.*]] = external constant %TypedBuffer.0
; CHECK-NEXT: @[[T2:.*]] = external constant %TypedBuffer.1
; CHECK-NEXT: @[[S0:.*]] = external constant %StructuredBuffer
; CHECK: @[[T0:.*]] = external constant %"Buffer<float4>"
; CHECK-NEXT: @[[T1:.*]] = external constant %"Buffer<int32_t>"
; CHECK-NEXT: @[[T2:.*]] = external constant %"Buffer<uint32_t3>"
; CHECK-NEXT: @[[S0:.*]] = external constant %"StructuredBuffer<struct.S>"
; CHECK-NEXT: @[[B0:.*]] = external constant %ByteAddressBuffer

; CHECK: !{i32 0, ptr @[[T0]], !"A"
Expand Down
33 changes: 16 additions & 17 deletions llvm/test/CodeGen/DirectX/Metadata/srv_metadata.ll
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,24 @@ define void @test() #0 {

attributes #0 = { noinline nounwind "hlsl.shader"="compute" }

; CHECK: %TypedBuffer = type { <4 x half> }
; CHECK: %TypedBuffer.0 = type { <2 x float> }
; CHECK: %TypedBuffer.1 = type { double }
; CHECK: %TypedBuffer.2 = type { <4 x i32> }
; CHECK: %"Buffer<half4>" = type { <4 x half> }
; CHECK: %"Buffer<float2>" = type { <2 x float> }
; CHECK: %"Buffer<double>" = type { double }
; CHECK: %"Buffer<int32_t4>" = type { <4 x i32> }
; CHECK: %ByteAddressBuffer = type { i32 }
; CHECK: %StructuredBuffer = type { i16 }
; CHECK: %TypedBuffer.3 = type { i64 }
; CHECK: %TypedBuffer.4 = type { <4 x float> }
; CHECK: %TypedBuffer.5 = type { i64 }

; CHECK: @Zero = external constant %TypedBuffer
; CHECK: @One = external constant %TypedBuffer.0
; CHECK: @Two = external constant %TypedBuffer.1
; CHECK: @Three = external constant %TypedBuffer.2
; CHECK: %"StructuredBuffer<int16_t>" = type { i16 }
; CHECK: %"Buffer<uint32_t>" = type { i64 }
; CHECK: %"Buffer<float4>" = type { <4 x float> }

; CHECK: @Zero = external constant %"Buffer<half4>"
; CHECK: @One = external constant %"Buffer<float2>"
; CHECK: @Two = external constant %"Buffer<double>"
; CHECK: @Three = external constant %"Buffer<int32_t4>"
; CHECK: @Four = external constant %ByteAddressBuffer
; CHECK: @Five = external constant %StructuredBuffer
; CHECK: @Six = external constant %TypedBuffer.3
; CHECK: @Array = external constant %TypedBuffer.4
; CHECK: @Seven = external constant %TypedBuffer.5
; CHECK: @Five = external constant %"StructuredBuffer<int16_t>"
; CHECK: @Six = external constant %"Buffer<uint32_t>"
; CHECK: @Array = external constant %"Buffer<float4>"
; CHECK: @Seven = external constant %"Buffer<uint32_t>"

; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}

Expand Down
Loading