LLVM 22.0.0git
DXContainerGlobals.cpp
Go to the documentation of this file.
1//===- DXContainerGlobals.cpp - DXContainer global generator pass ---------===//
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// DXContainerGlobalsPass implementation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "DXILRootSignature.h"
14#include "DXILShaderFlags.h"
15#include "DirectX.h"
18#include "llvm/ADT/StringRef.h"
22#include "llvm/CodeGen/Passes.h"
23#include "llvm/IR/Constants.h"
24#include "llvm/IR/Module.h"
27#include "llvm/Pass.h"
28#include "llvm/Support/MD5.h"
31#include <optional>
32
33using namespace llvm;
34using namespace llvm::dxil;
35using namespace llvm::mcdxbc;
36
37namespace {
38class DXContainerGlobals : public llvm::ModulePass {
39
40 GlobalVariable *buildContainerGlobal(Module &M, Constant *Content,
42 GlobalVariable *getFeatureFlags(Module &M);
43 GlobalVariable *computeShaderHash(Module &M);
44 GlobalVariable *buildSignature(Module &M, Signature &Sig, StringRef Name,
46 void addSignature(Module &M, SmallVector<GlobalValue *> &Globals);
47 void addRootSignature(Module &M, SmallVector<GlobalValue *> &Globals);
48 void addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV);
49 void addPipelineStateValidationInfo(Module &M,
51
52public:
53 static char ID; // Pass identification, replacement for typeid
54 DXContainerGlobals() : ModulePass(ID) {}
55
56 StringRef getPassName() const override {
57 return "DXContainer Global Emitter";
58 }
59
60 bool runOnModule(Module &M) override;
61
62 void getAnalysisUsage(AnalysisUsage &AU) const override {
63 AU.setPreservesAll();
69 }
70};
71
72} // namespace
73
74bool DXContainerGlobals::runOnModule(Module &M) {
76 Globals.push_back(getFeatureFlags(M));
77 Globals.push_back(computeShaderHash(M));
78 addSignature(M, Globals);
79 addRootSignature(M, Globals);
80 addPipelineStateValidationInfo(M, Globals);
81 appendToCompilerUsed(M, Globals);
82 return true;
83}
84
85GlobalVariable *DXContainerGlobals::getFeatureFlags(Module &M) {
86 uint64_t CombinedFeatureFlags = getAnalysis<ShaderFlagsAnalysisWrapper>()
87 .getShaderFlags()
88 .getCombinedFlags()
89 .getFeatureFlags();
90
91 Constant *FeatureFlagsConstant =
92 ConstantInt::get(M.getContext(), APInt(64, CombinedFeatureFlags));
93 return buildContainerGlobal(M, FeatureFlagsConstant, "dx.sfi0", "SFI0");
94}
95
96GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) {
97 auto *DXILConstant =
98 cast<ConstantDataArray>(M.getNamedGlobal("dx.dxil")->getInitializer());
99 MD5 Digest;
100 Digest.update(DXILConstant->getRawDataValues());
101 MD5::MD5Result Result = Digest.final();
102
103 dxbc::ShaderHash HashData = {0, {0}};
104 // The Hash's IncludesSource flag gets set whenever the hashed shader includes
105 // debug information.
106 if (!M.debug_compile_units().empty())
107 HashData.Flags = static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);
108
109 memcpy(reinterpret_cast<void *>(&HashData.Digest), Result.data(), 16);
111 HashData.swapBytes();
112 StringRef Data(reinterpret_cast<char *>(&HashData), sizeof(dxbc::ShaderHash));
113
114 Constant *ModuleConstant =
115 ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));
116 return buildContainerGlobal(M, ModuleConstant, "dx.hash", "HASH");
117}
118
119GlobalVariable *DXContainerGlobals::buildContainerGlobal(
121 auto *GV = new llvm::GlobalVariable(
122 M, Content->getType(), true, GlobalValue::PrivateLinkage, Content, Name);
123 GV->setSection(SectionName);
124 GV->setAlignment(Align(4));
125 return GV;
126}
127
128GlobalVariable *DXContainerGlobals::buildSignature(Module &M, Signature &Sig,
131 SmallString<256> Data;
133 Sig.write(OS);
135 ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
136 return buildContainerGlobal(M, Constant, Name, SectionName);
137}
138
139void DXContainerGlobals::addSignature(Module &M,
141 // FIXME: support graphics shader.
142 // see issue https://github.com/llvm/llvm-project/issues/90504.
143
144 Signature InputSig;
145 Globals.emplace_back(buildSignature(M, InputSig, "dx.isg1", "ISG1"));
146
147 Signature OutputSig;
148 Globals.emplace_back(buildSignature(M, OutputSig, "dx.osg1", "OSG1"));
149}
150
151void DXContainerGlobals::addRootSignature(Module &M,
153
155 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
156
157 // Root Signature in Library don't compile to DXContainer.
159 return;
160
161 assert(MMI.EntryPropertyVec.size() == 1);
162
163 auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
164 const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry;
165 const mcdxbc::RootSignatureDesc *RS = RSA.getDescForFunction(EntryFunction);
166
167 if (!RS)
168 return;
169
170 SmallString<256> Data;
172
173 RS->write(OS);
174
176 ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
177 Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.rts0", "RTS0"));
178}
179
180void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {
181 const DXILResourceMap &DRM =
182 getAnalysis<DXILResourceWrapperPass>().getResourceMap();
183 DXILResourceTypeMap &DRTM =
184 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
185
186 auto MakeBinding =
191 BindInfo.Type = Type;
192 BindInfo.LowerBound = Binding.LowerBound;
193 BindInfo.UpperBound = Binding.LowerBound + Binding.Size - 1;
194 BindInfo.Space = Binding.Space;
195 BindInfo.Kind = static_cast<dxbc::PSV::ResourceKind>(Kind);
196 BindInfo.Flags = Flags;
197 return BindInfo;
198 };
199
200 for (const dxil::ResourceInfo &RI : DRM.cbuffers()) {
201 const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();
202 PSV.Resources.push_back(MakeBinding(Binding, dxbc::PSV::ResourceType::CBV,
203 dxil::ResourceKind::CBuffer));
204 }
205 for (const dxil::ResourceInfo &RI : DRM.samplers()) {
206 const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();
207 PSV.Resources.push_back(MakeBinding(Binding,
208 dxbc::PSV::ResourceType::Sampler,
209 dxil::ResourceKind::Sampler));
210 }
211 for (const dxil::ResourceInfo &RI : DRM.srvs()) {
212 const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();
213
214 dxil::ResourceTypeInfo &TypeInfo = DRTM[RI.getHandleTy()];
216 if (TypeInfo.isStruct())
217 ResType = dxbc::PSV::ResourceType::SRVStructured;
218 else if (TypeInfo.isTyped())
219 ResType = dxbc::PSV::ResourceType::SRVTyped;
220 else
221 ResType = dxbc::PSV::ResourceType::SRVRaw;
222
223 PSV.Resources.push_back(
224 MakeBinding(Binding, ResType, TypeInfo.getResourceKind()));
225 }
226 for (const dxil::ResourceInfo &RI : DRM.uavs()) {
227 const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();
228
229 dxil::ResourceTypeInfo &TypeInfo = DRTM[RI.getHandleTy()];
231 if (RI.hasCounter())
232 ResType = dxbc::PSV::ResourceType::UAVStructuredWithCounter;
233 else if (TypeInfo.isStruct())
234 ResType = dxbc::PSV::ResourceType::UAVStructured;
235 else if (TypeInfo.isTyped())
236 ResType = dxbc::PSV::ResourceType::UAVTyped;
237 else
238 ResType = dxbc::PSV::ResourceType::UAVRaw;
239
241 // TODO: Add support for dxbc::PSV::ResourceFlag::UsedByAtomic64, tracking
242 // with https://github.com/llvm/llvm-project/issues/104392
243 Flags.Flags = 0u;
244
245 PSV.Resources.push_back(
246 MakeBinding(Binding, ResType, TypeInfo.getResourceKind(), Flags));
247 }
248}
249
250void DXContainerGlobals::addPipelineStateValidationInfo(
251 Module &M, SmallVector<GlobalValue *> &Globals) {
252 SmallString<256> Data;
254 PSVRuntimeInfo PSV;
256 PSV.BaseData.MaximumWaveLaneCount = std::numeric_limits<uint32_t>::max();
257
259 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
260 assert(MMI.EntryPropertyVec.size() == 1 ||
263 static_cast<uint8_t>(MMI.ShaderProfile - Triple::Pixel);
264
265 addResourcesForPSV(M, PSV);
266
267 // Hardcoded values here to unblock loading the shader into D3D.
268 //
269 // TODO: Lots more stuff to do here!
270 //
271 // See issue https://github.com/llvm/llvm-project/issues/96674.
272 switch (MMI.ShaderProfile) {
273 case Triple::Compute:
274 PSV.BaseData.NumThreadsX = MMI.EntryPropertyVec[0].NumThreadsX;
275 PSV.BaseData.NumThreadsY = MMI.EntryPropertyVec[0].NumThreadsY;
276 PSV.BaseData.NumThreadsZ = MMI.EntryPropertyVec[0].NumThreadsZ;
277 break;
278 default:
279 break;
280 }
281
283 PSV.EntryName = MMI.EntryPropertyVec[0].Entry->getName();
284
285 PSV.finalize(MMI.ShaderProfile);
286 PSV.write(OS);
288 ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
289 Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.psv0", "PSV0"));
290}
291
292char DXContainerGlobals::ID = 0;
293INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals",
294 "DXContainer Global Emitter", false, true)
299INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals",
300 "DXContainer Global Emitter", false, true)
301
303 return new DXContainerGlobals();
304}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
dxil DXContainer Global Emitter
dxil globals
DXIL Resource Implicit Binding
T Content
std::string Name
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:42
#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 defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
Class for arbitrary precision integers.
Definition: APInt.h:78
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
Definition: Constants.cpp:2989
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
Definition: Constants.h:715
This is an important base class in LLVM.
Definition: Constant.h:43
iterator_range< iterator > samplers()
Definition: DXILResource.h:548
iterator_range< iterator > srvs()
Definition: DXILResource.h:519
iterator_range< iterator > cbuffers()
Definition: DXILResource.h:537
iterator_range< iterator > uavs()
Definition: DXILResource.h:528
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:61
Definition: MD5.h:42
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition: MD5.cpp:189
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition: MD5.cpp:234
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:255
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:112
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM_ABI bool isTyped() const
LLVM_ABI bool isStruct() const
dxil::ResourceKind getResourceKind() const
Definition: DXILResource.h:325
Wrapper pass for the legacy pass manager.
Wrapper pass for the legacy pass manager.
void write(raw_ostream &OS)
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:692
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
ResourceKind
The kind of resource for an SRV or UAV resource.
Definition: DXILABI.h:35
constexpr bool IsBigEndianHost
Definition: SwapByteOrder.h:26
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
ModulePass * createDXContainerGlobalsPass()
Pass for generating DXContainer part globals.
@ Global
Append to llvm.global_dtors.
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Triple::EnvironmentType ShaderProfile
SmallVector< EntryProperties > EntryPropertyVec
dxbc::PSV::v3::RuntimeInfo BaseData
SmallVector< dxbc::PSV::v2::ResourceBindInfo > Resources
void finalize(Triple::EnvironmentType Stage)
void write(raw_ostream &OS, uint32_t Version=std::numeric_limits< uint32_t >::max()) const
LLVM_ABI void write(raw_ostream &OS) const