LLVM 24.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"
15#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"
27#include "llvm/Pass.h"
28#include "llvm/Support/Error.h"
32#include <cstdint>
33
34using namespace llvm;
35using namespace llvm::dxil;
36
37static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
38 unsigned int OpId) {
39 if (auto *CI =
40 mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
41 return CI->getZExtValue();
42 return std::nullopt;
43}
44
45static bool reportError(LLVMContext *Ctx, Twine Message,
46 DiagnosticSeverity Severity = DS_Error) {
47 Ctx->diagnose(DiagnosticInfoGeneric(Message, Severity));
48 return true;
49}
50
53
54 /** Root Signature are specified as following in the metadata:
55
56 !dx.rootsignatures = !{!2} ; list of function/root signature pairs
57 !2 = !{ ptr @main, !3 } ; function, root signature
58 !3 = !{ !4, !5, !6, !7 } ; list of root signature elements
59
60 So for each MDNode inside dx.rootsignatures NamedMDNode
61 (the Root parameter of this function), the parsing process needs
62 to loop through each of its operands and process the function,
63 signature pair.
64 */
65
66 LLVMContext *Ctx = &M.getContext();
67
69
70 NamedMDNode *RootSignatureNode = M.getNamedMetadata("dx.rootsignatures");
71 if (RootSignatureNode == nullptr)
72 return RSDMap;
73
74 bool AllowNullFunctions = false;
75 if (M.getTargetTriple().getEnvironment() ==
77 assert(RootSignatureNode->getNumOperands() == 1);
78 AllowNullFunctions = true;
79 }
80
81 for (const auto &RSDefNode : RootSignatureNode->operands()) {
82 if (RSDefNode->getNumOperands() != 3) {
83 reportError(Ctx, "Invalid Root Signature metadata - expected function, "
84 "signature, and version.");
85 continue;
86 }
87
88 // Function was pruned during compilation.
89 Function *F = nullptr;
90
91 if (!AllowNullFunctions) {
92 const MDOperand &FunctionPointerMdNode = RSDefNode->getOperand(0);
93 if (FunctionPointerMdNode == nullptr) {
95 Ctx, "Function associated with Root Signature definition is null.");
96 continue;
97 }
98
99 ValueAsMetadata *VAM =
100 llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get());
101 if (VAM == nullptr) {
102 reportError(Ctx, "First element of root signature is not a Value");
103 continue;
104 }
105
106 F = dyn_cast<Function>(VAM->getValue());
107 if (F == nullptr) {
108 reportError(Ctx, "First element of root signature is not a Function");
109 continue;
110 }
111 }
112
113 Metadata *RootElementListOperand = RSDefNode->getOperand(1).get();
114
115 if (RootElementListOperand == nullptr) {
116 reportError(Ctx, "Root Element mdnode is null.");
117 continue;
118 }
119
120 MDNode *RootElementListNode = dyn_cast<MDNode>(RootElementListOperand);
121 if (RootElementListNode == nullptr) {
122 reportError(Ctx, "Root Element is not a metadata node.");
123 continue;
124 }
125 std::optional<uint32_t> V = extractMdIntValue(RSDefNode, 2);
126 if (!V.has_value()) {
127 reportError(Ctx, "Invalid RSDefNode value, expected constant int");
128 continue;
129 }
130
132 reportError(Ctx, "Invalid Root Signature Version: " + Twine(*V));
133 continue;
134 }
135
136 llvm::hlsl::rootsig::MetadataParser MDParser(RootElementListNode);
138 MDParser.ParseRootSignature(V.value());
139
140 if (!RSDOrErr) {
141 handleAllErrors(RSDOrErr.takeError(), [&](ErrorInfoBase &EIB) {
142 Ctx->emitError(EIB.message());
143 });
144 continue;
145 }
146
147 auto &RSD = *RSDOrErr;
148
149 // Clang emits the root signature data in dxcontainer following a specific
150 // sequence. First the header, then the root parameters. So the header
151 // offset will always equal to the header size.
152 RSD.RootParameterOffset = sizeof(dxbc::RTS0::v1::RootSignatureHeader);
153
154 // static sampler offset is calculated when writting dxcontainer.
155 RSD.StaticSamplersOffset = 0u;
156
157 RSDMap.insert(std::make_pair(F, RSD));
158 }
159
160 return RSDMap;
161}
162
163AnalysisKey RootSignatureAnalysis::Key;
164
169
170//===----------------------------------------------------------------------===//
171
174
176 if (RSDMap.empty())
177 return PreservedAnalyses::all();
178
179 OS << "Root Signature Definitions"
180 << "\n";
181 for (const Function &F : M) {
182 auto It = RSDMap.find(&F);
183 if (It == RSDMap.end())
184 continue;
185 const auto &RS = It->second;
186 OS << "Definition for '" << F.getName() << "':\n";
187 // start root signature header
188 OS << "Flags: " << format_hex(RS.Flags, 8) << "\n"
189 << "Version: " << RS.Version << "\n"
190 << "RootParametersOffset: " << RS.RootParameterOffset << "\n"
191 << "NumParameters: " << RS.ParametersContainer.size() << "\n";
192 for (size_t I = 0; I < RS.ParametersContainer.size(); I++) {
193 const mcdxbc::RootParameterInfo &Info = RS.ParametersContainer.getInfo(I);
194
195 OS << "- Parameter Type: "
196 << dxbc::getRootParameterTypes().toString(Info.Type) << "\n"
197 << " Shader Visibility: "
198 << dxbc::getShaderVisibility().toString(Info.Visibility) << "\n";
199 switch (Info.Type) {
200 case dxbc::RootParameterType::Constants32Bit: {
201 const mcdxbc::RootConstants &Constants =
202 RS.ParametersContainer.getConstant(Info.Location);
203 OS << " Register Space: " << Constants.RegisterSpace << "\n"
204 << " Shader Register: " << Constants.ShaderRegister << "\n"
205 << " Num 32 Bit Values: " << Constants.Num32BitValues << "\n";
206 break;
207 }
208 case dxbc::RootParameterType::CBV:
209 case dxbc::RootParameterType::UAV:
210 case dxbc::RootParameterType::SRV: {
211 const mcdxbc::RootDescriptor &Descriptor =
212 RS.ParametersContainer.getRootDescriptor(Info.Location);
213 OS << " Register Space: " << Descriptor.RegisterSpace << "\n"
214 << " Shader Register: " << Descriptor.ShaderRegister << "\n";
215 if (RS.Version > 1)
216 OS << " Flags: " << Descriptor.Flags << "\n";
217 break;
218 }
219 case dxbc::RootParameterType::DescriptorTable: {
221 RS.ParametersContainer.getDescriptorTable(Info.Location);
222 OS << " NumRanges: " << Table.Ranges.size() << "\n";
223
224 for (const mcdxbc::DescriptorRange &Range : Table) {
225 OS << " - Range Type: "
226 << dxil::getResourceClassName(Range.RangeType) << "\n"
227 << " Register Space: " << Range.RegisterSpace << "\n"
228 << " Base Shader Register: " << Range.BaseShaderRegister << "\n"
229 << " Num Descriptors: " << Range.NumDescriptors << "\n"
230 << " Offset In Descriptors From Table Start: "
231 << Range.OffsetInDescriptorsFromTableStart << "\n";
232 if (RS.Version > 1)
233 OS << " Flags: " << Range.Flags << "\n";
234 }
235 break;
236 }
237 }
238 }
239 OS << "NumStaticSamplers: " << 0 << "\n";
240 OS << "StaticSamplersOffset: " << RS.StaticSamplersOffset << "\n";
241 }
242 return PreservedAnalyses::all();
243}
244
245//===----------------------------------------------------------------------===//
247 FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
249 return false;
250}
251
256
258
260 "dxil-root-signature-analysis",
261 "DXIL Root Signature Analysis", true, true)
263 "dxil-root-signature-analysis",
264 "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
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:827
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:76
Metadata node.
Definition Metadata.h:1081
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:68
A tuple of MDNodes.
Definition Metadata.h:1797
LLVM_ABI unsigned getNumOperands() const
iterator_range< op_iterator > operands()
Definition Metadata.h:1893
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:413
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:471
Value * getValue() const
Definition Metadata.h:510
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 EnumStrings< RootParameterType, 1 > getRootParameterTypes()
LLVM_ABI EnumStrings< ShaderVisibility, 1 > getShaderVisibility()
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:707
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:164
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
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