Skip to content

Commit 87157ab

Browse files
authored
[DirectX] Add resource handling to the DXIL pretty printer
Handle target extension type resources when printing resources to textual IR. Pull Request: #104448
1 parent 2a50dac commit 87157ab

File tree

4 files changed

+257
-6
lines changed

4 files changed

+257
-6
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ class ResourceInfo {
164164
UAVFlags.HasCounter = HasCounter;
165165
UAVFlags.IsROV = IsROV;
166166
}
167+
const UAVInfo &getUAV() const {
168+
assert(isUAV() && "Not a UAV");
169+
return UAVFlags;
170+
}
167171
void setCBuffer(uint32_t Size) {
168172
assert(isCBuffer() && "Not a CBuffer");
169173
CBufferSize = Size;
@@ -179,6 +183,10 @@ class ResourceInfo {
179183
Typed.ElementTy = ElementTy;
180184
Typed.ElementCount = ElementCount;
181185
}
186+
const TypedInfo &getTyped() const {
187+
assert(isTyped() && "Not typed");
188+
return Typed;
189+
}
182190
void setFeedback(dxil::SamplerFeedbackType Type) {
183191
assert(isFeedback() && "Not Feedback");
184192
Feedback.Type = Type;
@@ -187,8 +195,14 @@ class ResourceInfo {
187195
assert(isMultiSample() && "Not MultiSampled");
188196
MultiSample.Count = Count;
189197
}
198+
const MSInfo &getMultiSample() const {
199+
assert(isMultiSample() && "Not MultiSampled");
200+
return MultiSample;
201+
}
190202

203+
StringRef getName() const { return Name; }
191204
dxil::ResourceClass getResourceClass() const { return RC; }
205+
dxil::ResourceKind getResourceKind() const { return Kind; }
192206

193207
bool operator==(const ResourceInfo &RHS) const;
194208
bool operator!=(const ResourceInfo &RHS) const { return !(*this == RHS); }

llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp

Lines changed: 223 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,234 @@
1010
#include "DXILResourceAnalysis.h"
1111
#include "DirectX.h"
1212
#include "llvm/ADT/StringRef.h"
13+
#include "llvm/Analysis/DXILResource.h"
1314
#include "llvm/IR/PassManager.h"
15+
#include "llvm/InitializePasses.h"
1416
#include "llvm/Pass.h"
17+
#include "llvm/Support/FormatAdapters.h"
1518
#include "llvm/Support/FormatVariadic.h"
1619
#include "llvm/Support/raw_ostream.h"
1720

1821
using namespace llvm;
1922

20-
static void prettyPrintResources(raw_ostream &OS,
23+
static StringRef getRCName(dxil::ResourceClass RC) {
24+
switch (RC) {
25+
case dxil::ResourceClass::SRV:
26+
return "SRV";
27+
case dxil::ResourceClass::UAV:
28+
return "UAV";
29+
case dxil::ResourceClass::CBuffer:
30+
return "cbuffer";
31+
case dxil::ResourceClass::Sampler:
32+
return "sampler";
33+
}
34+
llvm_unreachable("covered switch");
35+
}
36+
37+
static StringRef getRCPrefix(dxil::ResourceClass RC) {
38+
switch (RC) {
39+
case dxil::ResourceClass::SRV:
40+
return "t";
41+
case dxil::ResourceClass::UAV:
42+
return "u";
43+
case dxil::ResourceClass::CBuffer:
44+
return "cb";
45+
case dxil::ResourceClass::Sampler:
46+
return "s";
47+
}
48+
}
49+
50+
static StringRef getFormatName(const dxil::ResourceInfo &RI) {
51+
if (RI.isTyped()) {
52+
switch (RI.getTyped().ElementTy) {
53+
case dxil::ElementType::I1:
54+
return "i1";
55+
case dxil::ElementType::I16:
56+
return "i16";
57+
case dxil::ElementType::U16:
58+
return "u16";
59+
case dxil::ElementType::I32:
60+
return "i32";
61+
case dxil::ElementType::U32:
62+
return "u32";
63+
case dxil::ElementType::I64:
64+
return "i64";
65+
case dxil::ElementType::U64:
66+
return "u64";
67+
case dxil::ElementType::F16:
68+
return "f16";
69+
case dxil::ElementType::F32:
70+
return "f32";
71+
case dxil::ElementType::F64:
72+
return "f64";
73+
case dxil::ElementType::SNormF16:
74+
return "snorm_f16";
75+
case dxil::ElementType::UNormF16:
76+
return "unorm_f16";
77+
case dxil::ElementType::SNormF32:
78+
return "snorm_f32";
79+
case dxil::ElementType::UNormF32:
80+
return "unorm_f32";
81+
case dxil::ElementType::SNormF64:
82+
return "snorm_f64";
83+
case dxil::ElementType::UNormF64:
84+
return "unorm_f64";
85+
case dxil::ElementType::PackedS8x32:
86+
return "p32i8";
87+
case dxil::ElementType::PackedU8x32:
88+
return "p32u8";
89+
case dxil::ElementType::Invalid:
90+
llvm_unreachable("Invalid ElementType");
91+
}
92+
llvm_unreachable("Unhandled ElementType");
93+
} else if (RI.isStruct())
94+
return "struct";
95+
else if (RI.isCBuffer() || RI.isSampler())
96+
return "NA";
97+
return "byte";
98+
}
99+
100+
static StringRef getTextureDimName(dxil::ResourceKind RK) {
101+
switch (RK) {
102+
case dxil::ResourceKind::Texture1D:
103+
return "1d";
104+
case dxil::ResourceKind::Texture2D:
105+
return "2d";
106+
case dxil::ResourceKind::Texture3D:
107+
return "3d";
108+
case dxil::ResourceKind::TextureCube:
109+
return "cube";
110+
case dxil::ResourceKind::Texture1DArray:
111+
return "1darray";
112+
case dxil::ResourceKind::Texture2DArray:
113+
return "2darray";
114+
case dxil::ResourceKind::TextureCubeArray:
115+
return "cubearray";
116+
case dxil::ResourceKind::TBuffer:
117+
return "tbuffer";
118+
case dxil::ResourceKind::FeedbackTexture2D:
119+
return "fbtex2d";
120+
case dxil::ResourceKind::FeedbackTexture2DArray:
121+
return "fbtex2darray";
122+
case dxil::ResourceKind::Texture2DMS:
123+
return "2dMS";
124+
case dxil::ResourceKind::Texture2DMSArray:
125+
return "2darrayMS";
126+
case dxil::ResourceKind::Invalid:
127+
case dxil::ResourceKind::NumEntries:
128+
case dxil::ResourceKind::CBuffer:
129+
case dxil::ResourceKind::RawBuffer:
130+
case dxil::ResourceKind::Sampler:
131+
case dxil::ResourceKind::StructuredBuffer:
132+
case dxil::ResourceKind::TypedBuffer:
133+
case dxil::ResourceKind::RTAccelerationStructure:
134+
llvm_unreachable("Invalid ResourceKind for texture");
135+
}
136+
llvm_unreachable("Unhandled ResourceKind");
137+
}
138+
139+
namespace {
140+
struct FormatResourceDimension
141+
: public llvm::FormatAdapter<const dxil::ResourceInfo &> {
142+
explicit FormatResourceDimension(const dxil::ResourceInfo &RI)
143+
: llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
144+
145+
void format(llvm::raw_ostream &OS, StringRef Style) override {
146+
dxil::ResourceKind RK = Item.getResourceKind();
147+
switch (RK) {
148+
default: {
149+
OS << getTextureDimName(RK);
150+
if (Item.isMultiSample())
151+
OS << Item.getMultiSample().Count;
152+
break;
153+
}
154+
case dxil::ResourceKind::RawBuffer:
155+
case dxil::ResourceKind::StructuredBuffer:
156+
if (!Item.isUAV())
157+
OS << "r/o";
158+
else if (Item.getUAV().HasCounter)
159+
OS << "r/w+cnt";
160+
else
161+
OS << "r/w";
162+
break;
163+
case dxil::ResourceKind::TypedBuffer:
164+
OS << "buf";
165+
break;
166+
case dxil::ResourceKind::RTAccelerationStructure:
167+
// TODO: dxc would print "ras" here. Can/should this happen?
168+
llvm_unreachable("RTAccelerationStructure printing is not implemented");
169+
}
170+
}
171+
};
172+
173+
struct FormatBindingID
174+
: public llvm::FormatAdapter<const dxil::ResourceInfo &> {
175+
explicit FormatBindingID(const dxil::ResourceInfo &RI)
176+
: llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
177+
178+
void format(llvm::raw_ostream &OS, StringRef Style) override {
179+
OS << getRCPrefix(Item.getResourceClass()).upper()
180+
<< Item.getBinding().RecordID;
181+
}
182+
};
183+
184+
struct FormatBindingLocation
185+
: public llvm::FormatAdapter<const dxil::ResourceInfo &> {
186+
explicit FormatBindingLocation(const dxil::ResourceInfo &RI)
187+
: llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
188+
189+
void format(llvm::raw_ostream &OS, StringRef Style) override {
190+
const auto &Binding = Item.getBinding();
191+
OS << getRCPrefix(Item.getResourceClass()) << Binding.LowerBound;
192+
if (Binding.Space)
193+
OS << ",space" << Binding.Space;
194+
}
195+
};
196+
197+
struct FormatBindingSize
198+
: public llvm::FormatAdapter<const dxil::ResourceInfo &> {
199+
explicit FormatBindingSize(const dxil::ResourceInfo &RI)
200+
: llvm::FormatAdapter<const dxil::ResourceInfo &>(RI) {}
201+
202+
void format(llvm::raw_ostream &OS, StringRef Style) override {
203+
uint32_t Size = Item.getBinding().Size;
204+
if (Size == std::numeric_limits<uint32_t>::max())
205+
OS << "unbounded";
206+
else
207+
OS << Size;
208+
}
209+
};
210+
211+
} // namespace
212+
213+
static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM,
21214
const dxil::Resources &MDResources) {
22215
// Column widths are arbitrary but match the widths DXC uses.
23216
OS << ";\n; Resource Bindings:\n;\n";
24-
OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,16}\n", "Name",
217+
OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,9}\n", "Name",
25218
"Type", "Format", "Dim", "ID", "HLSL Bind", "Count");
26219
OS << formatv(
27-
"; {0,-+30} {1,-+10} {2,-+7} {3,-+11} {4,-+7} {5,-+14} {6,-+16}\n", "",
28-
"", "", "", "", "", "");
220+
"; {0,-+30} {1,-+10} {2,-+7} {3,-+11} {4,-+7} {5,-+14} {6,-+9}\n", "", "",
221+
"", "", "", "", "");
222+
223+
// TODO: Do we want to sort these by binding or something like that?
224+
for (const dxil::ResourceInfo &RI : DRM) {
225+
dxil::ResourceClass RC = RI.getResourceClass();
226+
assert((RC != dxil::ResourceClass::CBuffer || !MDResources.hasCBuffers()) &&
227+
"Old and new cbuffer representations can't coexist");
228+
assert((RC != dxil::ResourceClass::UAV || !MDResources.hasUAVs()) &&
229+
"Old and new UAV representations can't coexist");
230+
231+
StringRef Name(RI.getName());
232+
StringRef Type(getRCName(RC));
233+
StringRef Format(getFormatName(RI));
234+
FormatResourceDimension Dim(RI);
235+
FormatBindingID ID(RI);
236+
FormatBindingLocation Bind(RI);
237+
FormatBindingSize Count(RI);
238+
OS << formatv("; {0,-30} {1,10} {2,7} {3,11} {4,7} {5,14} {6,9}\n", Name,
239+
Type, Format, Dim, ID, Bind, Count);
240+
}
29241

30242
if (MDResources.hasCBuffers())
31243
MDResources.printCBuffers(OS);
@@ -37,8 +249,9 @@ static void prettyPrintResources(raw_ostream &OS,
37249

38250
PreservedAnalyses DXILPrettyPrinterPass::run(Module &M,
39251
ModuleAnalysisManager &MAM) {
252+
const DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
40253
const dxil::Resources &MDResources = MAM.getResult<DXILResourceMDAnalysis>(M);
41-
prettyPrintResources(OS, MDResources);
254+
prettyPrintResources(OS, DRM, MDResources);
42255
return PreservedAnalyses::all();
43256
}
44257

@@ -63,6 +276,7 @@ class DXILPrettyPrinterLegacy : public llvm::ModulePass {
63276
bool runOnModule(Module &M) override;
64277
void getAnalysisUsage(AnalysisUsage &AU) const override {
65278
AU.setPreservesAll();
279+
AU.addRequired<DXILResourceWrapperPass>();
66280
AU.addRequired<DXILResourceMDWrapper>();
67281
}
68282
};
@@ -71,13 +285,16 @@ class DXILPrettyPrinterLegacy : public llvm::ModulePass {
71285
char DXILPrettyPrinterLegacy::ID = 0;
72286
INITIALIZE_PASS_BEGIN(DXILPrettyPrinterLegacy, "dxil-pretty-printer",
73287
"DXIL Metadata Pretty Printer", true, true)
288+
INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
74289
INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper)
75290
INITIALIZE_PASS_END(DXILPrettyPrinterLegacy, "dxil-pretty-printer",
76291
"DXIL Metadata Pretty Printer", true, true)
77292

78293
bool DXILPrettyPrinterLegacy::runOnModule(Module &M) {
294+
const DXILResourceMap &DRM =
295+
getAnalysis<DXILResourceWrapperPass>().getResourceMap();
79296
dxil::Resources &Res = getAnalysis<DXILResourceMDWrapper>().getDXILResource();
80-
prettyPrintResources(OS, Res);
297+
prettyPrintResources(OS, DRM, Res);
81298
return false;
82299
}
83300

llvm/test/CodeGen/DirectX/CreateHandle.ll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
; RUN: opt -S -passes=dxil-op-lower,dxil-translate-metadata %s | FileCheck %s
2+
; RUN: opt -S -passes=dxil-pretty-printer %s 2>&1 >/dev/null | FileCheck --check-prefix=CHECK-PRETTY %s
3+
4+
; CHECK-PRETTY: Type Format Dim ID HLSL Bind Count
5+
; CHECK-PRETTY: ---------- ------- ----------- ------- -------------- ---------
6+
; CHECK-PRETTY: SRV f32 buf T0 t0 unbounded
7+
; CHECK-PRETTY: SRV byte r/o T1 t8,space1 1
8+
; CHECK-PRETTY: SRV struct r/o T2 t2,space4 1
9+
; CHECK-PRETTY: SRV u32 buf T3 t3,space5 24
10+
; CHECK-PRETTY: UAV i32 buf U0 u7,space2 1
11+
; CHECK-PRETTY: UAV f32 buf U1 u5,space3 1
212

313
target triple = "dxil-pc-shadermodel6.0-compute"
414

llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
; RUN: opt -S -passes=dxil-op-lower,dxil-translate-metadata %s | FileCheck %s
2+
; RUN: opt -S -passes=dxil-pretty-printer %s 2>&1 >/dev/null | FileCheck --check-prefix=CHECK-PRETTY %s
3+
4+
; CHECK-PRETTY: Type Format Dim ID HLSL Bind Count
5+
; CHECK-PRETTY: ---------- ------- ----------- ------- -------------- ---------
6+
; CHECK-PRETTY: SRV f32 buf T0 t0 unbounded
7+
; CHECK-PRETTY: SRV byte r/o T1 t8,space1 1
8+
; CHECK-PRETTY: SRV struct r/o T2 t2,space4 1
9+
; CHECK-PRETTY: SRV u32 buf T3 t3,space5 24
10+
; CHECK-PRETTY: UAV i32 buf U0 u7,space2 1
11+
; CHECK-PRETTY: UAV f32 buf U1 u5,space3 1
212

313
target triple = "dxil-pc-shadermodel6.6-compute"
414

0 commit comments

Comments
 (0)