LLVM 23.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"
21#include "llvm/IR/Constants.h"
23#include "llvm/IR/Function.h"
24#include "llvm/IR/LLVMContext.h"
25#include "llvm/IR/Metadata.h"
26#include "llvm/IR/Module.h"
29#include "llvm/Pass.h"
30#include "llvm/Support/Error.h"
34#include <cstdint>
35
36using namespace llvm;
37using namespace llvm::dxil;
38
39static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
40 unsigned int OpId) {
41 if (auto *CI =
42 mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
43 return CI->getZExtValue();
44 return std::nullopt;
45}
46
47static bool reportError(LLVMContext *Ctx, Twine Message,
48 DiagnosticSeverity Severity = DS_Error) {
49 Ctx->diagnose(DiagnosticInfoGeneric(Message, Severity));
50 return true;
51}
52
55
56 /** Root Signature are specified as following in the metadata:
57
58 !dx.rootsignatures = !{!2} ; list of function/root signature pairs
59 !2 = !{ ptr @main, !3 } ; function, root signature
60 !3 = !{ !4, !5, !6, !7 } ; list of root signature elements
61
62 So for each MDNode inside dx.rootsignatures NamedMDNode
63 (the Root parameter of this function), the parsing process needs
64 to loop through each of its operands and process the function,
65 signature pair.
66 */
67
68 LLVMContext *Ctx = &M.getContext();
69
71
72 NamedMDNode *RootSignatureNode = M.getNamedMetadata("dx.rootsignatures");
73 if (RootSignatureNode == nullptr)
74 return RSDMap;
75
76 bool AllowNullFunctions = false;
77 if (M.getTargetTriple().getEnvironment() ==
79 assert(RootSignatureNode->getNumOperands() == 1);
80 AllowNullFunctions = true;
81 }
82
83 for (const auto &RSDefNode : RootSignatureNode->operands()) {
84 if (RSDefNode->getNumOperands() != 3) {
85 reportError(Ctx, "Invalid Root Signature metadata - expected function, "
86 "signature, and version.");
87 continue;
88 }
89
90 // Function was pruned during compilation.
91 Function *F = nullptr;
92
93 if (!AllowNullFunctions) {
94 const MDOperand &FunctionPointerMdNode = RSDefNode->getOperand(0);
95 if (FunctionPointerMdNode == nullptr) {
97 Ctx, "Function associated with Root Signature definition is null.");
98 continue;
99 }
100
101 ValueAsMetadata *VAM =
102 llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get());
103 if (VAM == nullptr) {
104 reportError(Ctx, "First element of root signature is not a Value");
105 continue;
106 }
107
108 F = dyn_cast<Function>(VAM->getValue());
109 if (F == nullptr) {
110 reportError(Ctx, "First element of root signature is not a Function");
111 continue;
112 }
113 }
114
115 Metadata *RootElementListOperand = RSDefNode->getOperand(1).get();
116
117 if (RootElementListOperand == nullptr) {
118 reportError(Ctx, "Root Element mdnode is null.");
119 continue;
120 }
121
122 MDNode *RootElementListNode = dyn_cast<MDNode>(RootElementListOperand);
123 if (RootElementListNode == nullptr) {
124 reportError(Ctx, "Root Element is not a metadata node.");
125 continue;
126 }
127 std::optional<uint32_t> V = extractMdIntValue(RSDefNode, 2);
128 if (!V.has_value()) {
129 reportError(Ctx, "Invalid RSDefNode value, expected constant int");
130 continue;
131 }
132
134 reportError(Ctx, "Invalid Root Signature Version: " + Twine(*V));
135 continue;
136 }
137
138 llvm::hlsl::rootsig::MetadataParser MDParser(RootElementListNode);
140 MDParser.ParseRootSignature(V.value());
141
142 if (!RSDOrErr) {
143 handleAllErrors(RSDOrErr.takeError(), [&](ErrorInfoBase &EIB) {
144 Ctx->emitError(EIB.message());
145 });
146 continue;
147 }
148
149 auto &RSD = *RSDOrErr;
150
151 // Clang emits the root signature data in dxcontainer following a specific
152 // sequence. First the header, then the root parameters. So the header
153 // offset will always equal to the header size.
154 RSD.RootParameterOffset = sizeof(dxbc::RTS0::v1::RootSignatureHeader);
155
156 // static sampler offset is calculated when writting dxcontainer.
157 RSD.StaticSamplersOffset = 0u;
158
159 RSDMap.insert(std::make_pair(F, RSD));
160 }
161
162 return RSDMap;
163}
164
165AnalysisKey RootSignatureAnalysis::Key;
166
171
172//===----------------------------------------------------------------------===//
173
176
178 if (RSDMap.empty())
179 return PreservedAnalyses::all();
180
181 OS << "Root Signature Definitions"
182 << "\n";
183 for (const Function &F : M) {
184 auto It = RSDMap.find(&F);
185 if (It == RSDMap.end())
186 continue;
187 const auto &RS = It->second;
188 OS << "Definition for '" << F.getName() << "':\n";
189 // start root signature header
190 OS << "Flags: " << format_hex(RS.Flags, 8) << "\n"
191 << "Version: " << RS.Version << "\n"
192 << "RootParametersOffset: " << RS.RootParameterOffset << "\n"
193 << "NumParameters: " << RS.ParametersContainer.size() << "\n";
194 for (size_t I = 0; I < RS.ParametersContainer.size(); I++) {
195 const mcdxbc::RootParameterInfo &Info = RS.ParametersContainer.getInfo(I);
196
197 OS << "- Parameter Type: "
198 << enumToStringRef(Info.Type, dxbc::getRootParameterTypes()) << "\n"
199 << " Shader Visibility: "
200 << enumToStringRef(Info.Visibility, dxbc::getShaderVisibility())
201 << "\n";
202 switch (Info.Type) {
203 case dxbc::RootParameterType::Constants32Bit: {
204 const mcdxbc::RootConstants &Constants =
205 RS.ParametersContainer.getConstant(Info.Location);
206 OS << " Register Space: " << Constants.RegisterSpace << "\n"
207 << " Shader Register: " << Constants.ShaderRegister << "\n"
208 << " Num 32 Bit Values: " << Constants.Num32BitValues << "\n";
209 break;
210 }
211 case dxbc::RootParameterType::CBV:
212 case dxbc::RootParameterType::UAV:
213 case dxbc::RootParameterType::SRV: {
214 const mcdxbc::RootDescriptor &Descriptor =
215 RS.ParametersContainer.getRootDescriptor(Info.Location);
216 OS << " Register Space: " << Descriptor.RegisterSpace << "\n"
217 << " Shader Register: " << Descriptor.ShaderRegister << "\n";
218 if (RS.Version > 1)
219 OS << " Flags: " << Descriptor.Flags << "\n";
220 break;
221 }
222 case dxbc::RootParameterType::DescriptorTable: {
223 const mcdxbc::DescriptorTable &Table =
224 RS.ParametersContainer.getDescriptorTable(Info.Location);
225 OS << " NumRanges: " << Table.Ranges.size() << "\n";
226
227 for (const mcdxbc::DescriptorRange &Range : Table) {
228 OS << " - Range Type: "
229 << dxil::getResourceClassName(Range.RangeType) << "\n"
230 << " Register Space: " << Range.RegisterSpace << "\n"
231 << " Base Shader Register: " << Range.BaseShaderRegister << "\n"
232 << " Num Descriptors: " << Range.NumDescriptors << "\n"
233 << " Offset In Descriptors From Table Start: "
234 << Range.OffsetInDescriptorsFromTableStart << "\n";
235 if (RS.Version > 1)
236 OS << " Flags: " << Range.Flags << "\n";
237 }
238 break;
239 }
240 }
241 }
242 OS << "NumStaticSamplers: " << 0 << "\n";
243 OS << "StaticSamplersOffset: " << RS.StaticSamplersOffset << "\n";
244 }
245 return PreservedAnalyses::all();
246}
247
248//===----------------------------------------------------------------------===//
250 FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
252 return false;
253}
254
259
261
263 "dxil-root-signature-analysis",
264 "DXIL Root Signature Analysis", true, true)
266 "dxil-root-signature-analysis",
267 "DXIL Root Signature Analysis", true, true)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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:54
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
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
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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:239
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
Metadata node.
Definition Metadata.h:1080
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
Metadata * get() const
Definition Metadata.h:931
Root of the metadata hierarchy.
Definition Metadata.h:64
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:1760
LLVM_ABI unsigned getNumOperands() const
iterator_range< op_iterator > operands()
Definition Metadata.h:1856
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
@ RootSignature
Definition Triple.h:323
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:459
Value * getValue() const
Definition Metadata.h:499
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.
RootSignatureBindingInfo Result
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()
LLVM_ABI ArrayRef< EnumEntry< RootParameterType > > getRootParameterTypes()
LLVM_ABI StringRef getResourceClassName(ResourceClass RC)
Definition DXILABI.cpp:21
LLVM_ABI bool verifyVersion(uint32_t Version)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:696
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:1013
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition Format.h:191
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
StringRef enumToStringRef(T Value, ArrayRef< EnumEntry< TEnum > > EnumValues)
Retrieves the Value's enum name.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
SmallVector< DescriptorRange > Ranges