-
Notifications
You must be signed in to change notification settings - Fork 873
Expand file tree
/
Copy pathDxilModule.h
More file actions
437 lines (360 loc) · 16.5 KB
/
DxilModule.h
File metadata and controls
437 lines (360 loc) · 16.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
///////////////////////////////////////////////////////////////////////////////
// //
// DxilModule.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// The main class to work with DXIL, similar to LLVM module. //
// //
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include "dxc/DXIL/DxilCBuffer.h"
#include "dxc/DXIL/DxilConstants.h"
#include "dxc/DXIL/DxilMetadataHelper.h"
#include "dxc/DXIL/DxilResource.h"
#include "dxc/DXIL/DxilSampler.h"
#include "dxc/DXIL/DxilShaderFlags.h"
#include "dxc/DXIL/DxilSignature.h"
#include "dxc/DXIL/DxilSubobject.h"
#include "dxc/DXIL/DxilTypeSystem.h"
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace llvm {
class LLVMContext;
class Module;
class Function;
class Instruction;
class MDTuple;
class MDOperand;
class DebugInfoFinder;
} // namespace llvm
namespace hlsl {
class ShaderModel;
class OP;
struct DxilFunctionProps;
class DxilEntryProps;
using DxilEntryPropsMap =
std::unordered_map<const llvm::Function *, std::unique_ptr<DxilEntryProps>>;
/// Use this class to manipulate DXIL of a shader.
class DxilModule {
public:
DxilModule(llvm::Module *pModule);
~DxilModule();
// Subsystems.
llvm::LLVMContext &GetCtx() const;
llvm::Module *GetModule() const;
OP *GetOP() const;
void SetShaderModel(const ShaderModel *pSM, bool bUseMinPrecision = true);
const ShaderModel *GetShaderModel() const;
void GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const;
void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor);
bool UpgradeValidatorVersion(unsigned ValMajor, unsigned ValMinor);
void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
void SetForceZeroStoreLifetimes(bool ForceZeroStoreLifetimes);
bool GetForceZeroStoreLifetimes() const;
// Return true on success, requires valid shader model and CollectShaderFlags
// to have been set
bool GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
// Update validator version to minimum if higher than current (ex: after
// CollectShaderFlags)
bool UpgradeToMinValidatorVersion();
// Entry functions.
llvm::Function *GetEntryFunction();
const llvm::Function *GetEntryFunction() const;
void SetEntryFunction(llvm::Function *pEntryFunc);
const std::string &GetEntryFunctionName() const;
void SetEntryFunctionName(const std::string &name);
llvm::Function *GetPatchConstantFunction();
const llvm::Function *GetPatchConstantFunction() const;
void SetPatchConstantFunction(llvm::Function *pFunc);
bool IsEntryOrPatchConstantFunction(const llvm::Function *pFunc) const;
llvm::SmallVector<llvm::Function *, 64> GetExportedFunctions();
// Flags.
unsigned GetGlobalFlags() const;
void CollectShaderFlagsForModule();
// Resources.
unsigned AddCBuffer(std::unique_ptr<DxilCBuffer> pCB);
DxilCBuffer &GetCBuffer(unsigned idx);
const DxilCBuffer &GetCBuffer(unsigned idx) const;
const std::vector<std::unique_ptr<DxilCBuffer>> &GetCBuffers() const;
unsigned AddSampler(std::unique_ptr<DxilSampler> pSampler);
DxilSampler &GetSampler(unsigned idx);
const DxilSampler &GetSampler(unsigned idx) const;
const std::vector<std::unique_ptr<DxilSampler>> &GetSamplers() const;
unsigned AddSRV(std::unique_ptr<DxilResource> pSRV);
DxilResource &GetSRV(unsigned idx);
const DxilResource &GetSRV(unsigned idx) const;
const std::vector<std::unique_ptr<DxilResource>> &GetSRVs() const;
unsigned AddUAV(std::unique_ptr<DxilResource> pUAV);
DxilResource &GetUAV(unsigned idx);
const DxilResource &GetUAV(unsigned idx) const;
const std::vector<std::unique_ptr<DxilResource>> &GetUAVs() const;
void RemoveUnusedResources();
bool RemoveResourcesWithUnusedSymbols();
void RemoveFunction(llvm::Function *F);
bool RenameResourcesWithPrefix(const std::string &prefix);
bool RenameResourceGlobalsWithBinding(bool bKeepName = true);
// Signatures.
DxilSignature &GetInputSignature();
const DxilSignature &GetInputSignature() const;
DxilSignature &GetOutputSignature();
const DxilSignature &GetOutputSignature() const;
DxilSignature &GetPatchConstOrPrimSignature();
const DxilSignature &GetPatchConstOrPrimSignature() const;
const std::vector<uint8_t> &GetSerializedRootSignature() const;
std::vector<uint8_t> &GetSerializedRootSignature();
bool HasDxilEntrySignature(const llvm::Function *F) const;
DxilEntrySignature &GetDxilEntrySignature(const llvm::Function *F);
// Move DxilEntryProps of F to NewF.
void ReplaceDxilEntryProps(llvm::Function *F, llvm::Function *NewF);
// Clone DxilEntryProps of F to NewF.
void CloneDxilEntryProps(llvm::Function *F, llvm::Function *NewF);
bool HasDxilEntryProps(const llvm::Function *F) const;
DxilEntryProps &GetDxilEntryProps(const llvm::Function *F);
const DxilEntryProps &GetDxilEntryProps(const llvm::Function *F) const;
// DxilFunctionProps.
bool HasDxilFunctionProps(const llvm::Function *F) const;
DxilFunctionProps &GetDxilFunctionProps(const llvm::Function *F);
const DxilFunctionProps &GetDxilFunctionProps(const llvm::Function *F) const;
// Move DxilFunctionProps of F to NewF.
void SetPatchConstantFunctionForHS(llvm::Function *hullShaderFunc,
llvm::Function *patchConstantFunc);
bool IsGraphicsShader(const llvm::Function *F) const; // vs,hs,ds,gs,ps
bool IsPatchConstantShader(const llvm::Function *F) const;
bool IsComputeShader(const llvm::Function *F) const;
// Is an entry function that uses input/output signature conventions?
// Includes: vs/hs/ds/gs/ps/cs as well as the patch constant function.
bool IsEntryThatUsesSignatures(const llvm::Function *F) const;
// Is F an entry?
// Includes: IsEntryThatUsesSignatures and all ray tracing shaders.
bool IsEntry(const llvm::Function *F) const;
// Remove Root Signature from module metadata, return true if changed
bool StripRootSignatureFromMetadata();
// Remove Subobjects from module metadata, return true if changed
bool StripSubobjectsFromMetadata();
// Update validator version metadata to current setting
void UpdateValidatorVersionMetadata();
// DXIL type system.
DxilTypeSystem &GetTypeSystem();
const DxilTypeSystem &GetTypeSystem() const;
/// Emit llvm.used array to make sure that optimizations do not remove
/// unreferenced globals.
void EmitLLVMUsed();
std::vector<llvm::GlobalVariable *> &GetLLVMUsed();
void ClearLLVMUsed();
// ViewId state.
std::vector<unsigned> &GetSerializedViewIdState();
const std::vector<unsigned> &GetSerializedViewIdState() const;
// DXIL metadata manipulation.
/// Clear all DXIL data that exists in in-memory form.
static void ClearDxilMetadata(llvm::Module &M);
/// Serialize DXIL in-memory form to metadata form.
void EmitDxilMetadata();
/// Update resource metadata.
/// Note: this method not update Metadata for ViewIdState.
void ReEmitDxilResources();
/// Deserialize DXIL metadata form into in-memory form.
void LoadDxilMetadata();
/// Return true if non-fatal metadata error was detected.
bool HasMetadataErrors();
void EmitDxilCounters();
void LoadDxilCounters(DxilCounters &counters) const;
/// Check if a Named meta data node is known by dxil module.
static bool IsKnownNamedMetaData(llvm::NamedMDNode &Node);
// Reset functions used to transfer ownership.
void ResetEntrySignature(DxilEntrySignature *pValue);
void ResetSerializedRootSignature(std::vector<uint8_t> &Value);
void ResetTypeSystem(DxilTypeSystem *pValue);
void ResetOP(hlsl::OP *hlslOP);
void ResetEntryPropsMap(DxilEntryPropsMap &&PropMap);
bool StripReflection();
void StripDebugRelatedCode();
void RemoveUnusedTypeAnnotations();
// Copy resource reflection back to this module's resources.
void RestoreResourceReflection(const DxilModule &SourceDM);
// Helper to remove dx.* metadata with source and compile options.
// If the parameter `bReplaceWithDummyData` is true, the named metadata
// are replaced with valid empty data that satisfy tools.
void StripShaderSourcesAndCompileOptions(bool bReplaceWithDummyData = false);
llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
static DxilModule *TryGetDxilModule(llvm::Module *pModule);
// Helpers for working with precise.
// Return true if the instruction should be considered precise.
//
// An instruction can be marked precise in the following ways:
//
// 1. Global refactoring is disabled.
// 2. The instruction has a precise metadata annotation.
// 3. The instruction has precise fast math flags set.
//
bool IsPrecise(const llvm::Instruction *inst) const;
// Check if the instruction has fast math flags configured to indicate
// the instruction is precise.
static bool HasPreciseFastMathFlags(const llvm::Instruction *inst);
// Set fast math flags configured to indicate the instruction is precise.
static void SetPreciseFastMathFlags(llvm::Instruction *inst);
// True if fast math flags are preserved across serialize/deserialize.
static bool PreservesFastMathFlags(const llvm::Instruction *inst);
public:
ShaderFlags m_ShaderFlags;
void CollectShaderFlagsForModule(ShaderFlags &Flags);
// Check if DxilModule contains multi component UAV Loads.
// This funciton must be called after unused resources are removed from
// DxilModule
bool ModuleHasMulticomponentUAVLoads();
// Compute/Mesh/Amplification shader.
void SetNumThreads(unsigned x, unsigned y, unsigned z);
unsigned GetNumThreads(unsigned idx) const;
// Compute shader
DxilWaveSize &GetWaveSize();
const DxilWaveSize &GetWaveSize() const;
// Geometry shader.
DXIL::InputPrimitive GetInputPrimitive() const;
void SetInputPrimitive(DXIL::InputPrimitive IP);
unsigned GetMaxVertexCount() const;
void SetMaxVertexCount(unsigned Count);
DXIL::PrimitiveTopology GetStreamPrimitiveTopology() const;
void SetStreamPrimitiveTopology(DXIL::PrimitiveTopology Topology);
bool HasMultipleOutputStreams() const;
unsigned GetOutputStream() const;
unsigned GetGSInstanceCount() const;
void SetGSInstanceCount(unsigned Count);
bool IsStreamActive(unsigned Stream) const;
void SetStreamActive(unsigned Stream, bool bActive);
void SetActiveStreamMask(unsigned Mask);
unsigned GetActiveStreamMask() const;
// Language options
// UseMinPrecision must be set at SetShaderModel time.
bool GetUseMinPrecision() const;
void SetDisableOptimization(bool disableOptimization);
bool GetDisableOptimization() const;
void SetAllResourcesBound(bool resourcesBound);
bool GetAllResourcesBound() const;
void SetResMayAlias(bool resMayAlias);
bool GetResMayAlias() const;
// Intermediate options that do not make it to DXIL
void SetLegacyResourceReservation(bool legacyResourceReservation);
bool GetLegacyResourceReservation() const;
void SetUnusedResourceBinding(UnusedResourceBinding unusedResourceBinding);
UnusedResourceBinding GetUnusedResourceBinding() const;
void ClearIntermediateOptions();
// Hull and Domain shaders.
unsigned GetInputControlPointCount() const;
void SetInputControlPointCount(unsigned NumICPs);
DXIL::TessellatorDomain GetTessellatorDomain() const;
void SetTessellatorDomain(DXIL::TessellatorDomain TessDomain);
// Hull shader.
unsigned GetOutputControlPointCount() const;
void SetOutputControlPointCount(unsigned NumOCPs);
DXIL::TessellatorPartitioning GetTessellatorPartitioning() const;
void
SetTessellatorPartitioning(DXIL::TessellatorPartitioning TessPartitioning);
DXIL::TessellatorOutputPrimitive GetTessellatorOutputPrimitive() const;
void SetTessellatorOutputPrimitive(
DXIL::TessellatorOutputPrimitive TessOutputPrimitive);
float GetMaxTessellationFactor() const;
void SetMaxTessellationFactor(float MaxTessellationFactor);
// Mesh shader
unsigned GetMaxOutputVertices() const;
void SetMaxOutputVertices(unsigned NumOVs);
unsigned GetMaxOutputPrimitives() const;
void SetMaxOutputPrimitives(unsigned NumOPs);
DXIL::MeshOutputTopology GetMeshOutputTopology() const;
void SetMeshOutputTopology(DXIL::MeshOutputTopology MeshOutputTopology);
unsigned GetPayloadSizeInBytes() const;
void SetPayloadSizeInBytes(unsigned Size);
// AutoBindingSpace also enables automatic binding for libraries if set.
// UINT_MAX == unset
void SetAutoBindingSpace(uint32_t Space);
uint32_t GetAutoBindingSpace() const;
void SetShaderProperties(DxilFunctionProps *props);
DxilSubobjects *GetSubobjects();
const DxilSubobjects *GetSubobjects() const;
DxilSubobjects *ReleaseSubobjects();
void ResetSubobjects(DxilSubobjects *subobjects);
private:
// Signatures.
std::vector<uint8_t> m_SerializedRootSignature;
// Shader resources.
std::vector<std::unique_ptr<DxilResource>> m_SRVs;
std::vector<std::unique_ptr<DxilResource>> m_UAVs;
std::vector<std::unique_ptr<DxilCBuffer>> m_CBuffers;
std::vector<std::unique_ptr<DxilSampler>> m_Samplers;
// Geometry shader.
DXIL::PrimitiveTopology m_StreamPrimitiveTopology =
DXIL::PrimitiveTopology::Undefined;
unsigned m_ActiveStreamMask = 0;
enum IntermediateFlags : uint32_t { LegacyResourceReservation = 1 << 0 };
llvm::LLVMContext &m_Ctx;
llvm::Module *m_pModule = nullptr;
llvm::Function *m_pEntryFunc = nullptr;
std::string m_EntryName = "";
std::unique_ptr<DxilMDHelper> m_pMDHelper;
std::unique_ptr<llvm::DebugInfoFinder> m_pDebugInfoFinder;
const ShaderModel *m_pSM = nullptr;
unsigned m_DxilMajor = DXIL::kDxilMajor;
unsigned m_DxilMinor = DXIL::kDxilMinor;
unsigned m_ValMajor = 1;
unsigned m_ValMinor = 0;
bool m_ForceZeroStoreLifetimes = false;
std::unique_ptr<OP> m_pOP;
// LLVM used.
std::vector<llvm::GlobalVariable *> m_LLVMUsed;
// Type annotations.
std::unique_ptr<DxilTypeSystem> m_pTypeSystem;
// EntryProps for shader functions.
DxilEntryPropsMap m_DxilEntryPropsMap;
// Keeps track of patch constant functions used by hull shaders
std::unordered_set<const llvm::Function *> m_PatchConstantFunctions;
// Serialized ViewId state.
std::vector<unsigned> m_SerializedState;
// properties from HLModule preserved as ShaderFlags
bool m_bDisableOptimizations = false;
bool m_bUseMinPrecision = true; // use min precision by default;
bool m_bAllResourcesBound = false;
bool m_bResMayAlias = false;
UnusedResourceBinding m_unusedResourceBinding = UnusedResourceBinding::Strip;
// properties from HLModule that should not make it to the final DXIL
uint32_t m_IntermediateFlags = 0;
uint32_t m_AutoBindingSpace = UINT_MAX;
std::unique_ptr<DxilSubobjects> m_pSubobjects;
// m_bMetadataErrors is true if non-fatal metadata errors were encountered.
// Validator will fail in this case, but should not block module load.
bool m_bMetadataErrors = false;
// DXIL metadata serialization/deserialization.
llvm::MDTuple *EmitDxilResources();
void LoadDxilResources(const llvm::MDOperand &MDO);
// Helpers.
template <typename T>
unsigned AddResource(std::vector<std::unique_ptr<T>> &Vec,
std::unique_ptr<T> pRes);
void LoadDxilSignature(const llvm::MDTuple *pSigTuple, DxilSignature &Sig,
bool bInput);
public:
// ShaderCompatInfo tracks requirements per-function, subsequently merged into
// final entry function requirements.
struct ShaderCompatInfo {
unsigned minMajor = 6, minMinor = 0;
// 'mask' is a set of bits representing each compatible shader kind.
// Mapping is: 1 << (unsigned)DXIL::ShaderKind::<kind>.
// Starts out with all kinds valid, will be masked down based on features
// used and by known shader kinds for a particular validation version.
unsigned mask = ((unsigned)1 << (unsigned)DXIL::ShaderKind::Invalid) - 1;
ShaderFlags shaderFlags;
bool Merge(ShaderCompatInfo &other);
};
// Compute ShaderCompatInfo for all functions in module.
void ComputeShaderCompatInfo();
const ShaderCompatInfo *
GetCompatInfoForFunction(const llvm::Function *F) const;
private:
typedef std::unordered_map<const llvm::Function *, ShaderCompatInfo>
FunctionShaderCompatMap;
FunctionShaderCompatMap m_FuncToShaderCompat;
void UpdateFunctionToShaderCompat(const llvm::Function *dxilFunc);
};
} // namespace hlsl