LLVM 22.0.0git
DXILRootSignature.cpp
Go to the documentation of this file.
1//===- DXILRootSignature.cpp - DXIL Root Signature helper objects -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file This file contains helper objects and APIs for working with DXIL
10/// Root Signatures.
11///
12//===----------------------------------------------------------------------===//
13#include "DXILRootSignature.h"
14#include "DirectX.h"
16#include "llvm/ADT/Twine.h"
20#include "llvm/IR/Constants.h"
22#include "llvm/IR/Function.h"
23#include "llvm/IR/LLVMContext.h"
24#include "llvm/IR/Metadata.h"
25#include "llvm/IR/Module.h"
28#include "llvm/Pass.h"
29#include "llvm/Support/Error.h"
33#include <cstdint>
34
35using namespace llvm;
36using namespace llvm::dxil;
37
38static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
39 unsigned int OpId) {
40 if (auto *CI =
41 mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
42 return CI->getZExtValue();
43 return std::nullopt;
44}
45
46static bool reportError(LLVMContext *Ctx, Twine Message,
47 DiagnosticSeverity Severity = DS_Error) {
48 Ctx->diagnose(DiagnosticInfoGeneric(Message, Severity));
49 return true;
50}
51
54
55 /** Root Signature are specified as following in the metadata:
56
57 !dx.rootsignatures = !{!2} ; list of function/root signature pairs
58 !2 = !{ ptr @main, !3 } ; function, root signature
59 !3 = !{ !4, !5, !6, !7 } ; list of root signature elements
60
61 So for each MDNode inside dx.rootsignatures NamedMDNode
62 (the Root parameter of this function), the parsing process needs
63 to loop through each of its operands and process the function,
64 signature pair.
65 */
66
67 LLVMContext *Ctx = &M.getContext();
68
70
71 NamedMDNode *RootSignatureNode = M.getNamedMetadata("dx.rootsignatures");
72 if (RootSignatureNode == nullptr)
73 return RSDMap;
74
75 for (const auto &RSDefNode : RootSignatureNode->operands()) {
76 if (RSDefNode->getNumOperands() != 3) {
77 reportError(Ctx, "Invalid Root Signature metadata - expected function, "
78 "signature, and version.");
79 continue;
80 }
81
82 // Function was pruned during compilation.
83 const MDOperand &FunctionPointerMdNode = RSDefNode->getOperand(0);
84 if (FunctionPointerMdNode == nullptr) {
86 Ctx, "Function associated with Root Signature definition is null.");
87 continue;
88 }
89
90 ValueAsMetadata *VAM =
91 llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get());
92 if (VAM == nullptr) {
93 reportError(Ctx, "First element of root signature is not a Value");
94 continue;
95 }
96
97 Function *F = dyn_cast<Function>(VAM->getValue());
98 if (F == nullptr) {
99 reportError(Ctx, "First element of root signature is not a Function");
100 continue;
101 }
102
103 Metadata *RootElementListOperand = RSDefNode->getOperand(1).get();
104
105 if (RootElementListOperand == nullptr) {
106 reportError(Ctx, "Root Element mdnode is null.");
107 continue;
108 }
109
110 MDNode *RootElementListNode = dyn_cast<MDNode>(RootElementListOperand);
111 if (RootElementListNode == nullptr) {
112 reportError(Ctx, "Root Element is not a metadata node.");
113 continue;
114 }
115 std::optional<uint32_t> V = extractMdIntValue(RSDefNode, 2);
116 if (!V.has_value()) {
117 reportError(Ctx, "Invalid RSDefNode value, expected constant int");
118 continue;
119 }
120
121 llvm::hlsl::rootsig::MetadataParser MDParser(RootElementListNode);
123 MDParser.ParseRootSignature(V.value());
124
125 if (!RSDOrErr) {
126 handleAllErrors(RSDOrErr.takeError(), [&](ErrorInfoBase &EIB) {
127 Ctx->emitError(EIB.message());
128 });
129 continue;
130 }
131
132 auto &RSD = *RSDOrErr;
133
134 // Clang emits the root signature data in dxcontainer following a specific
135 // sequence. First the header, then the root parameters. So the header
136 // offset will always equal to the header size.
137 RSD.RootParameterOffset = sizeof(dxbc::RTS0::v1::RootSignatureHeader);
138
139 // static sampler offset is calculated when writting dxcontainer.
140 RSD.StaticSamplersOffset = 0u;
141
142 RSDMap.insert(std::make_pair(F, RSD));
143 }
144
145 return RSDMap;
146}
147
148AnalysisKey RootSignatureAnalysis::Key;
149
153}
154
155//===----------------------------------------------------------------------===//
156
159
161
162 OS << "Root Signature Definitions"
163 << "\n";
164 for (const Function &F : M) {
165 auto It = RSDMap.find(&F);
166 if (It == RSDMap.end())
167 continue;
168 const auto &RS = It->second;
169 OS << "Definition for '" << F.getName() << "':\n";
170 // start root signature header
171 OS << "Flags: " << format_hex(RS.Flags, 8) << "\n"
172 << "Version: " << RS.Version << "\n"
173 << "RootParametersOffset: " << RS.RootParameterOffset << "\n"
174 << "NumParameters: " << RS.ParametersContainer.size() << "\n";
175 for (size_t I = 0; I < RS.ParametersContainer.size(); I++) {
176 const mcdxbc::RootParameterInfo &Info = RS.ParametersContainer.getInfo(I);
177
178 OS << "- Parameter Type: "
180 << " Shader Visibility: "
182 << "\n";
183 switch (Info.Type) {
184 case dxbc::RootParameterType::Constants32Bit: {
185 const mcdxbc::RootConstants &Constants =
186 RS.ParametersContainer.getConstant(Info.Location);
187 OS << " Register Space: " << Constants.RegisterSpace << "\n"
188 << " Shader Register: " << Constants.ShaderRegister << "\n"
189 << " Num 32 Bit Values: " << Constants.Num32BitValues << "\n";
190 break;
191 }
192 case dxbc::RootParameterType::CBV:
193 case dxbc::RootParameterType::UAV:
194 case dxbc::RootParameterType::SRV: {
195 const mcdxbc::RootDescriptor &Descriptor =
196 RS.ParametersContainer.getRootDescriptor(Info.Location);
197 OS << " Register Space: " << Descriptor.RegisterSpace << "\n"
198 << " Shader Register: " << Descriptor.ShaderRegister << "\n";
199 if (RS.Version > 1)
200 OS << " Flags: " << Descriptor.Flags << "\n";
201 break;
202 }
203 case dxbc::RootParameterType::DescriptorTable: {
204 const mcdxbc::DescriptorTable &Table =
205 RS.ParametersContainer.getDescriptorTable(Info.Location);
206 OS << " NumRanges: " << Table.Ranges.size() << "\n";
207
208 for (const dxbc::RTS0::v2::DescriptorRange Range : Table) {
209 OS << " - Range Type: " << Range.RangeType << "\n"
210 << " Register Space: " << Range.RegisterSpace << "\n"
211 << " Base Shader Register: " << Range.BaseShaderRegister << "\n"
212 << " Num Descriptors: " << Range.NumDescriptors << "\n"
213 << " Offset In Descriptors From Table Start: "
214 << Range.OffsetInDescriptorsFromTableStart << "\n";
215 if (RS.Version > 1)
216 OS << " Flags: " << Range.Flags << "\n";
217 }
218 break;
219 }
220 }
221 }
222 OS << "NumStaticSamplers: " << 0 << "\n";
223 OS << "StaticSamplersOffset: " << RS.StaticSamplersOffset << "\n";
224 }
225 return PreservedAnalyses::all();
226}
227
228//===----------------------------------------------------------------------===//
230 FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
232 return false;
233}
234
236 AU.setPreservesAll();
238}
239
241
243 "dxil-root-signature-analysis",
244 "DXIL Root Signature Analysis", true, true)
246 "dxil-root-signature-analysis",
247 "DXIL Root Signature Analysis", true, true)
block Block Frequency Analysis
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static std::optional< uint32_t > extractMdIntValue(MDNode *Node, unsigned int OpId)
static SmallDenseMap< const Function *, mcdxbc::RootSignatureDesc > analyzeModule(Module &M)
static bool reportError(LLVMContext *Ctx, Twine Message, DiagnosticSeverity Severity=DS_Error)
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains the declarations for metadata subclasses.
module summary analysis
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:39
raw_pwrite_stream & OS
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:230
Base class for error info classes.
Definition: Error.h:44
Tagged union holding either a T or a Error.
Definition: Error.h:485
Error takeError()
Take ownership of the stored error.
Definition: Error.h:612
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Metadata node.
Definition: Metadata.h:1077
Tracking metadata reference owned by Metadata.
Definition: Metadata.h:899
Metadata * get() const
Definition: Metadata.h:928
Root of the metadata hierarchy.
Definition: Metadata.h:63
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
A tuple of MDNodes.
Definition: Metadata.h:1753
iterator_range< op_iterator > operands()
Definition: Metadata.h:1849
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:82
Value wrapper in the Metadata hierarchy.
Definition: Metadata.h:457
Value * getValue() const
Definition: Metadata.h:497
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Wrapper pass for the legacy pass manager.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
Result run(Module &M, ModuleAnalysisManager &AM)
iterator find(const Function *F)
LLVM_ABI llvm::Expected< llvm::mcdxbc::RootSignatureDesc > ParseRootSignature(uint32_t Version)
LLVM_ABI ArrayRef< EnumEntry< ShaderVisibility > > getShaderVisibility()
Definition: DXContainer.cpp:98
LLVM_ABI ArrayRef< EnumEntry< RootParameterType > > getRootParameterTypes()
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition: Error.h:990
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition: Format.h:188
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
@ DS_Error
StringRef enumToStringRef(T Value, ArrayRef< EnumEntry< TEnum > > EnumValues)
Retrieves the Value's enum name.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:29
SmallVector< dxbc::RTS0::v2::DescriptorRange > Ranges