Thanks to visit codestin.com
Credit goes to llvm.org

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 bool AllowNullFunctions = false;
76 if (M.getTargetTriple().getEnvironment() ==
78 assert(RootSignatureNode->getNumOperands() == 1);
79 AllowNullFunctions = true;
80 }
81
82 for (const auto &RSDefNode : RootSignatureNode->operands()) {
83 if (RSDefNode->getNumOperands() != 3) {
84 reportError(Ctx, "Invalid Root Signature metadata - expected function, "
85 "signature, and version.");
86 continue;
87 }
88
89 // Function was pruned during compilation.
90 Function *F = nullptr;
91
92 if (!AllowNullFunctions) {
93 const MDOperand &FunctionPointerMdNode = RSDefNode->getOperand(0);
94 if (FunctionPointerMdNode == nullptr) {
96 Ctx, "Function associated with Root Signature definition is null.");
97 continue;
98 }
99
100 ValueAsMetadata *VAM =
101 llvm::dyn_cast<ValueAsMetadata>(FunctionPointerMdNode.get());
102 if (VAM == nullptr) {
103 reportError(Ctx, "First element of root signature is not a Value");
104 continue;
105 }
106
107 F = dyn_cast<Function>(VAM->getValue());
108 if (F == nullptr) {
109 reportError(Ctx, "First element of root signature is not a Function");
110 continue;
111 }
112 }
113
114 Metadata *RootElementListOperand = RSDefNode->getOperand(1).get();
115
116 if (RootElementListOperand == nullptr) {
117 reportError(Ctx, "Root Element mdnode is null.");
118 continue;
119 }
120
121 MDNode *RootElementListNode = dyn_cast<MDNode>(RootElementListOperand);
122 if (RootElementListNode == nullptr) {
123 reportError(Ctx, "Root Element is not a metadata node.");
124 continue;
125 }
126 std::optional<uint32_t> V = extractMdIntValue(RSDefNode, 2);
127 if (!V.has_value()) {
128 reportError(Ctx, "Invalid RSDefNode value, expected constant int");
129 continue;
130 }
131
132 llvm::hlsl::rootsig::MetadataParser MDParser(RootElementListNode);
134 MDParser.ParseRootSignature(V.value());
135
136 if (!RSDOrErr) {
137 handleAllErrors(RSDOrErr.takeError(), [&](ErrorInfoBase &EIB) {
138 Ctx->emitError(EIB.message());
139 });
140 continue;
141 }
142
143 auto &RSD = *RSDOrErr;
144
145 // Clang emits the root signature data in dxcontainer following a specific
146 // sequence. First the header, then the root parameters. So the header
147 // offset will always equal to the header size.
148 RSD.RootParameterOffset = sizeof(dxbc::RTS0::v1::RootSignatureHeader);
149
150 // static sampler offset is calculated when writting dxcontainer.
151 RSD.StaticSamplersOffset = 0u;
152
153 RSDMap.insert(std::make_pair(F, RSD));
154 }
155
156 return RSDMap;
157}
158
159AnalysisKey RootSignatureAnalysis::Key;
160
165
166//===----------------------------------------------------------------------===//
167
170
172
173 OS << "Root Signature Definitions"
174 << "\n";
175 for (const Function &F : M) {
176 auto It = RSDMap.find(&F);
177 if (It == RSDMap.end())
178 continue;
179 const auto &RS = It->second;
180 OS << "Definition for '" << F.getName() << "':\n";
181 // start root signature header
182 OS << "Flags: " << format_hex(RS.Flags, 8) << "\n"
183 << "Version: " << RS.Version << "\n"
184 << "RootParametersOffset: " << RS.RootParameterOffset << "\n"
185 << "NumParameters: " << RS.ParametersContainer.size() << "\n";
186 for (size_t I = 0; I < RS.ParametersContainer.size(); I++) {
187 const mcdxbc::RootParameterInfo &Info = RS.ParametersContainer.getInfo(I);
188
189 OS << "- Parameter Type: "
190 << enumToStringRef(Info.Type, dxbc::getRootParameterTypes()) << "\n"
191 << " Shader Visibility: "
192 << enumToStringRef(Info.Visibility, dxbc::getShaderVisibility())
193 << "\n";
194 switch (Info.Type) {
195 case dxbc::RootParameterType::Constants32Bit: {
196 const mcdxbc::RootConstants &Constants =
197 RS.ParametersContainer.getConstant(Info.Location);
198 OS << " Register Space: " << Constants.RegisterSpace << "\n"
199 << " Shader Register: " << Constants.ShaderRegister << "\n"
200 << " Num 32 Bit Values: " << Constants.Num32BitValues << "\n";
201 break;
202 }
203 case dxbc::RootParameterType::CBV:
204 case dxbc::RootParameterType::UAV:
205 case dxbc::RootParameterType::SRV: {
206 const mcdxbc::RootDescriptor &Descriptor =
207 RS.ParametersContainer.getRootDescriptor(Info.Location);
208 OS << " Register Space: " << Descriptor.RegisterSpace << "\n"
209 << " Shader Register: " << Descriptor.ShaderRegister << "\n";
210 if (RS.Version > 1)
211 OS << " Flags: " << Descriptor.Flags << "\n";
212 break;
213 }
214 case dxbc::RootParameterType::DescriptorTable: {
215 const mcdxbc::DescriptorTable &Table =
216 RS.ParametersContainer.getDescriptorTable(Info.Location);
217 OS << " NumRanges: " << Table.Ranges.size() << "\n";
218
219 for (const mcdxbc::DescriptorRange &Range : Table) {
220 OS << " - Range Type: "
221 << dxil::getResourceClassName(Range.RangeType) << "\n"
222 << " Register Space: " << Range.RegisterSpace << "\n"
223 << " Base Shader Register: " << Range.BaseShaderRegister << "\n"
224 << " Num Descriptors: " << Range.NumDescriptors << "\n"
225 << " Offset In Descriptors From Table Start: "
226 << Range.OffsetInDescriptorsFromTableStart << "\n";
227 if (RS.Version > 1)
228 OS << " Flags: " << Range.Flags << "\n";
229 }
230 break;
231 }
232 }
233 }
234 OS << "NumStaticSamplers: " << 0 << "\n";
235 OS << "StaticSamplersOffset: " << RS.StaticSamplersOffset << "\n";
236 }
237 return PreservedAnalyses::all();
238}
239
240//===----------------------------------------------------------------------===//
242 FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
244 return false;
245}
246
251
253
255 "dxil-root-signature-analysis",
256 "DXIL Root Signature Analysis", true, true)
258 "dxil-root-signature-analysis",
259 "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:55
#define I(x, y, z)
Definition MD5.cpp:58
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:214
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: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:1749
LLVM_ABI unsigned getNumOperands() const
iterator_range< op_iterator > operands()
Definition Metadata.h:1845
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:308
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.
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
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:694
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:649
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.
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