HLModule.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // HLModule.h //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // HighLevel DX IR module. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #pragma once
  12. #include "dxc/Support/Global.h"
  13. #include "dxc/HLSL/DxilMetadataHelper.h"
  14. #include "dxc/HLSL/DxilConstants.h"
  15. #include "dxc/HLSL/HLResource.h"
  16. #include "dxc/HLSL/HLOperations.h"
  17. #include "dxc/HLSL/DxilSampler.h"
  18. #include "dxc/HLSL/DxilShaderModel.h"
  19. #include "dxc/HLSL/DxilSignature.h"
  20. #include <memory>
  21. #include <string>
  22. #include <vector>
  23. #include <unordered_map>
  24. namespace llvm {
  25. class LLVMContext;
  26. class Module;
  27. class Function;
  28. class Instruction;
  29. class CallInst;
  30. class MDTuple;
  31. class MDNode;
  32. class GlobalVariable;
  33. class DIGlobalVariable;
  34. class DebugInfoFinder;
  35. };
  36. namespace hlsl {
  37. class ShaderModel;
  38. class OP;
  39. class RootSignatureHandle;
  40. struct HLFunctionProps {
  41. union {
  42. // TODO: not every function need this union.
  43. // Compute shader.
  44. struct {
  45. unsigned numThreads[3];
  46. } CS;
  47. // Geometry shader.
  48. struct {
  49. DXIL::InputPrimitive inputPrimitive;
  50. unsigned maxVertexCount;
  51. unsigned instanceCount;
  52. DXIL::PrimitiveTopology streamPrimitiveTopologies[DXIL::kNumOutputStreams];
  53. } GS;
  54. // Hull shader.
  55. struct {
  56. llvm::Function *patchConstantFunc;
  57. DXIL::TessellatorDomain domain;
  58. DXIL::TessellatorPartitioning partition;
  59. DXIL::TessellatorOutputPrimitive outputPrimitive;
  60. unsigned inputControlPoints;
  61. unsigned outputControlPoints;
  62. float maxTessFactor;
  63. } HS;
  64. // Domain shader.
  65. struct {
  66. DXIL::TessellatorDomain domain;
  67. unsigned inputControlPoints;
  68. } DS;
  69. // Vertex shader.
  70. struct {
  71. llvm::Constant *clipPlanes[DXIL::kNumClipPlanes];
  72. } VS;
  73. // Pixel shader.
  74. struct {
  75. bool EarlyDepthStencil;
  76. } PS;
  77. } ShaderProps;
  78. DXIL::ShaderKind shaderKind;
  79. };
  80. struct HLOptions {
  81. HLOptions()
  82. : bDefaultRowMajor(false), bIEEEStrict(false), bDisableOptimizations(false),
  83. bLegacyCBufferLoad(false), PackingStrategy(0), unused(0) {
  84. }
  85. uint32_t GetHLOptionsRaw() const;
  86. void SetHLOptionsRaw(uint32_t data);
  87. unsigned bDefaultRowMajor : 1;
  88. unsigned bIEEEStrict : 1;
  89. unsigned bAllResourcesBound : 1;
  90. unsigned bDisableOptimizations : 1;
  91. unsigned bLegacyCBufferLoad : 1;
  92. unsigned PackingStrategy : 2;
  93. static_assert((unsigned)DXIL::PackingStrategy::Invalid < 4, "otherwise 2 bits is not enough to store PackingStrategy");
  94. unsigned unused : 25;
  95. };
  96. /// Use this class to manipulate HLDXIR of a shader.
  97. class HLModule {
  98. public:
  99. HLModule(llvm::Module *pModule);
  100. ~HLModule();
  101. using Domain = DXIL::TessellatorDomain;
  102. // Subsystems.
  103. llvm::LLVMContext &GetCtx() const;
  104. llvm::Module *GetModule() const;
  105. OP *GetOP() const;
  106. void SetShaderModel(const ShaderModel *pSM);
  107. const ShaderModel *GetShaderModel() const;
  108. void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor);
  109. void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
  110. // HLOptions
  111. void SetHLOptions(HLOptions &opts);
  112. const HLOptions &GetHLOptions() const;
  113. // Entry function.
  114. llvm::Function *GetEntryFunction() const;
  115. void SetEntryFunction(llvm::Function *pEntryFunc);
  116. const std::string &GetEntryFunctionName() const;
  117. void SetEntryFunctionName(const std::string &name);
  118. // Resources.
  119. unsigned AddCBuffer(std::unique_ptr<DxilCBuffer> pCB);
  120. DxilCBuffer &GetCBuffer(unsigned idx);
  121. const DxilCBuffer &GetCBuffer(unsigned idx) const;
  122. const std::vector<std::unique_ptr<DxilCBuffer> > &GetCBuffers() const;
  123. unsigned AddSampler(std::unique_ptr<DxilSampler> pSampler);
  124. DxilSampler &GetSampler(unsigned idx);
  125. const DxilSampler &GetSampler(unsigned idx) const;
  126. const std::vector<std::unique_ptr<DxilSampler> > &GetSamplers() const;
  127. unsigned AddSRV(std::unique_ptr<HLResource> pSRV);
  128. HLResource &GetSRV(unsigned idx);
  129. const HLResource &GetSRV(unsigned idx) const;
  130. const std::vector<std::unique_ptr<HLResource> > &GetSRVs() const;
  131. unsigned AddUAV(std::unique_ptr<HLResource> pUAV);
  132. HLResource &GetUAV(unsigned idx);
  133. const HLResource &GetUAV(unsigned idx) const;
  134. const std::vector<std::unique_ptr<HLResource> > &GetUAVs() const;
  135. void RemoveGlobal(llvm::GlobalVariable *GV);
  136. void RemoveFunction(llvm::Function *F);
  137. void RemoveResources(llvm::GlobalVariable **ppVariables, unsigned count);
  138. // ThreadGroupSharedMemory.
  139. typedef std::vector<llvm::GlobalVariable*>::iterator tgsm_iterator;
  140. tgsm_iterator tgsm_begin();
  141. tgsm_iterator tgsm_end();
  142. void AddGroupSharedVariable(llvm::GlobalVariable *GV);
  143. // Signatures.
  144. DxilSignature &GetInputSignature();
  145. DxilSignature &GetOutputSignature();
  146. DxilSignature &GetPatchConstantSignature();
  147. RootSignatureHandle &GetRootSignature();
  148. // HLFunctionProps.
  149. bool HasHLFunctionProps(llvm::Function *F);
  150. HLFunctionProps &GetHLFunctionProps(llvm::Function *F);
  151. void AddHLFunctionProps(llvm::Function *F, std::unique_ptr<HLFunctionProps> &info);
  152. DxilFunctionAnnotation *GetFunctionAnnotation(llvm::Function *F);
  153. DxilFunctionAnnotation *AddFunctionAnnotation(llvm::Function *F);
  154. void AddResourceTypeAnnotation(llvm::Type *Ty, DXIL::ResourceClass resClass,
  155. DXIL::ResourceKind kind);
  156. DXIL::ResourceClass GetResourceClass(llvm::Type *Ty);
  157. DXIL::ResourceKind GetResourceKind(llvm::Type *Ty);
  158. // HLDXIR metadata manipulation.
  159. /// Serialize HLDXIR in-memory form to metadata form.
  160. void EmitHLMetadata();
  161. /// Deserialize HLDXIR metadata form into in-memory form.
  162. void LoadHLMetadata();
  163. /// Delete any HLDXIR from the specified module.
  164. static void ClearHLMetadata(llvm::Module &M);
  165. /// Create Metadata from a resource.
  166. llvm::MDNode *DxilSamplerToMDNode(const DxilSampler &S);
  167. llvm::MDNode *DxilSRVToMDNode(const DxilResource &SRV);
  168. llvm::MDNode *DxilUAVToMDNode(const DxilResource &UAV);
  169. llvm::MDNode *DxilCBufferToMDNode(const DxilCBuffer &CB);
  170. void LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD, DxilResourceBase &R);
  171. void AddResourceWithGlobalVariableAndMDNode(llvm::Constant *GV,
  172. llvm::MDNode *MD);
  173. // Type related methods.
  174. static bool IsStreamOutputPtrType(llvm::Type *Ty);
  175. static bool IsStreamOutputType(llvm::Type *Ty);
  176. static bool IsHLSLObjectType(llvm::Type *Ty);
  177. static unsigned
  178. GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
  179. llvm::Type *Ty, DxilTypeSystem &typeSys);
  180. static llvm::Type *GetArrayEltTy(llvm::Type *Ty);
  181. static bool IsStaticGlobal(llvm::GlobalVariable *GV);
  182. static bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);
  183. static void GetParameterRowsAndCols(llvm::Type *Ty, unsigned &rows, unsigned &cols,
  184. DxilParameterAnnotation &paramAnnotation);
  185. static const char *GetLegacyDataLayoutDesc();
  186. static void MergeGepUse(llvm::Value *V);
  187. // HL code gen.
  188. template<class BuilderTy>
  189. static llvm::CallInst *EmitHLOperationCall(BuilderTy &Builder,
  190. HLOpcodeGroup group, unsigned opcode,
  191. llvm::Type *RetType,
  192. llvm::ArrayRef<llvm::Value *> paramList,
  193. llvm::Module &M);
  194. static unsigned FindCastOp(bool fromUnsigned, bool toUnsigned,
  195. llvm::Type *SrcTy, llvm::Type *DstTy);
  196. // Precise attribute.
  197. // Note: Precise will be marked on alloca inst with metadata in code gen.
  198. // But mem2reg will remove alloca inst, so need mark precise with
  199. // function call before mem2reg.
  200. static bool HasPreciseAttributeWithMetadata(llvm::Instruction *I);
  201. static void MarkPreciseAttributeWithMetadata(llvm::Instruction *I);
  202. static void ClearPreciseAttributeWithMetadata(llvm::Instruction *I);
  203. static void MarkPreciseAttributeOnPtrWithFunctionCall(llvm::Value *Ptr,
  204. llvm::Module &M);
  205. static bool HasPreciseAttribute(llvm::Function *F);
  206. // Resource attribute.
  207. static void MarkDxilResourceAttrib(llvm::Function *F, llvm::MDNode *MD);
  208. static llvm::MDNode *GetDxilResourceAttrib(llvm::Function *F);
  209. void MarkDxilResourceAttrib(llvm::Argument *Arg, llvm::MDNode *MD);
  210. llvm::MDNode *GetDxilResourceAttrib(llvm::Argument *Arg);
  211. static llvm::MDNode *GetDxilResourceAttrib(llvm::Type *Ty, llvm::Module &M);
  212. // DXIL type system.
  213. DxilTypeSystem &GetTypeSystem();
  214. /// Emit llvm.used array to make sure that optimizations do not remove unreferenced globals.
  215. void EmitLLVMUsed();
  216. std::vector<llvm::GlobalVariable* > &GetLLVMUsed();
  217. // Release functions used to transfer ownership.
  218. DxilSignature *ReleaseInputSignature();
  219. DxilSignature *ReleaseOutputSignature();
  220. DxilSignature *ReleasePatchConstantSignature();
  221. DxilTypeSystem *ReleaseTypeSystem();
  222. OP *ReleaseOP();
  223. RootSignatureHandle *ReleaseRootSignature();
  224. llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
  225. static llvm::DIGlobalVariable *
  226. FindGlobalVariableDebugInfo(llvm::GlobalVariable *GV,
  227. llvm::DebugInfoFinder &DbgInfoFinder);
  228. // Create global variable debug info for element global variable based on the
  229. // whole global variable.
  230. static void CreateElementGlobalVariableDebugInfo(
  231. llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder,
  232. llvm::GlobalVariable *EltGV, unsigned sizeInBits, unsigned alignInBits,
  233. unsigned offsetInBits, llvm::StringRef eltName);
  234. // Replace GV with NewGV in GlobalVariable debug info.
  235. static void
  236. UpdateGlobalVariableDebugInfo(llvm::GlobalVariable *GV,
  237. llvm::DebugInfoFinder &DbgInfoFinder,
  238. llvm::GlobalVariable *NewGV);
  239. private:
  240. // Signatures.
  241. std::unique_ptr<DxilSignature> m_InputSignature;
  242. std::unique_ptr<DxilSignature> m_OutputSignature;
  243. std::unique_ptr<DxilSignature> m_PatchConstantSignature;
  244. std::unique_ptr<RootSignatureHandle> m_RootSignature;
  245. // Shader resources.
  246. std::vector<std::unique_ptr<HLResource> > m_SRVs;
  247. std::vector<std::unique_ptr<HLResource> > m_UAVs;
  248. std::vector<std::unique_ptr<DxilCBuffer> > m_CBuffers;
  249. std::vector<std::unique_ptr<DxilSampler> > m_Samplers;
  250. // ThreadGroupSharedMemory.
  251. std::vector<llvm::GlobalVariable*> m_TGSMVariables;
  252. // High level function info.
  253. std::unordered_map<llvm::Function *, std::unique_ptr<HLFunctionProps>> m_HLFunctionPropsMap;
  254. // Resource type annotation.
  255. std::unordered_map<llvm::Type *, std::pair<DXIL::ResourceClass, DXIL::ResourceKind>> m_ResTypeAnnotation;
  256. private:
  257. llvm::LLVMContext &m_Ctx;
  258. llvm::Module *m_pModule;
  259. llvm::Function *m_pEntryFunc;
  260. std::string m_EntryName;
  261. std::unique_ptr<DxilMDHelper> m_pMDHelper;
  262. std::unique_ptr<llvm::DebugInfoFinder> m_pDebugInfoFinder;
  263. const ShaderModel *m_pSM;
  264. unsigned m_DxilMajor;
  265. unsigned m_DxilMinor;
  266. unsigned m_ValMajor;
  267. unsigned m_ValMinor;
  268. HLOptions m_Options;
  269. std::unique_ptr<OP> m_pOP;
  270. size_t m_pUnused;
  271. // DXIL metadata serialization/deserialization.
  272. llvm::MDTuple *EmitHLResources();
  273. void LoadHLResources(const llvm::MDOperand &MDO);
  274. llvm::MDTuple *EmitHLShaderProperties();
  275. void LoadHLShaderProperties(const llvm::MDOperand &MDO);
  276. llvm::MDTuple *EmitDxilShaderProperties();
  277. llvm::MDTuple *EmitResTyAnnotations();
  278. void LoadResTyAnnotations(const llvm::MDOperand &MDO);
  279. // LLVM used.
  280. std::vector<llvm::GlobalVariable*> m_LLVMUsed;
  281. // Type annotations.
  282. std::unique_ptr<DxilTypeSystem> m_pTypeSystem;
  283. // Helpers.
  284. template<typename T> unsigned AddResource(std::vector<std::unique_ptr<T> > &Vec, std::unique_ptr<T> pRes);
  285. };
  286. /// Use this class to manipulate metadata of extra metadata record properties that are specific to high-level DX IR.
  287. class HLExtraPropertyHelper : public DxilExtraPropertyHelper {
  288. public:
  289. HLExtraPropertyHelper(llvm::Module *pModule);
  290. virtual ~HLExtraPropertyHelper() {}
  291. virtual void EmitSignatureElementProperties(const DxilSignatureElement &SE, std::vector<llvm::Metadata *> &MDVals);
  292. virtual void LoadSignatureElementProperties(const llvm::MDOperand &MDO, DxilSignatureElement &SE);
  293. };
  294. } // namespace hlsl