DxilModule.cpp 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilModule.cpp //
  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. ///////////////////////////////////////////////////////////////////////////////
  9. #include "dxc/Support/Global.h"
  10. #include "dxc/HLSL/DxilOperations.h"
  11. #include "dxc/HLSL/DxilModule.h"
  12. #include "dxc/HLSL/DxilShaderModel.h"
  13. #include "dxc/HLSL/DxilSignatureElement.h"
  14. #include "dxc/HLSL/DxilContainer.h"
  15. #include "dxc/HLSL/DxilRootSignature.h"
  16. #include "dxc/HLSL/DxilFunctionProps.h"
  17. #include "llvm/IR/Constants.h"
  18. #include "llvm/IR/Function.h"
  19. #include "llvm/IR/Instructions.h"
  20. #include "llvm/IR/LLVMContext.h"
  21. #include "llvm/IR/Metadata.h"
  22. #include "llvm/IR/Module.h"
  23. #include "llvm/IR/Operator.h"
  24. #include "llvm/IR/DebugInfo.h"
  25. #include "llvm/IR/DiagnosticInfo.h"
  26. #include "llvm/IR/DiagnosticPrinter.h"
  27. #include "llvm/Support/raw_ostream.h"
  28. #include <unordered_set>
  29. using namespace llvm;
  30. using std::string;
  31. using std::vector;
  32. using std::unique_ptr;
  33. namespace {
  34. class DxilErrorDiagnosticInfo : public DiagnosticInfo {
  35. private:
  36. const char *m_message;
  37. public:
  38. DxilErrorDiagnosticInfo(const char *str)
  39. : DiagnosticInfo(DK_FirstPluginKind, DiagnosticSeverity::DS_Error),
  40. m_message(str) { }
  41. __override void print(DiagnosticPrinter &DP) const {
  42. DP << m_message;
  43. }
  44. };
  45. } // anon namespace
  46. namespace hlsl {
  47. //------------------------------------------------------------------------------
  48. //
  49. // DxilModule methods.
  50. //
  51. DxilModule::DxilModule(Module *pModule)
  52. : m_Ctx(pModule->getContext())
  53. , m_pModule(pModule)
  54. , m_pOP(std::make_unique<OP>(pModule->getContext(), pModule))
  55. , m_pTypeSystem(std::make_unique<DxilTypeSystem>(pModule))
  56. , m_pViewIdState(std::make_unique<DxilViewIdState>(this))
  57. , m_pMDHelper(std::make_unique<DxilMDHelper>(pModule, std::make_unique<DxilExtraPropertyHelper>(pModule)))
  58. , m_pDebugInfoFinder(nullptr)
  59. , m_pEntryFunc(nullptr)
  60. , m_EntryName("")
  61. , m_pPatchConstantFunc(nullptr)
  62. , m_pSM(nullptr)
  63. , m_DxilMajor(DXIL::kDxilMajor)
  64. , m_DxilMinor(DXIL::kDxilMinor)
  65. , m_ValMajor(1)
  66. , m_ValMinor(0)
  67. , m_InputPrimitive(DXIL::InputPrimitive::Undefined)
  68. , m_MaxVertexCount(0)
  69. , m_StreamPrimitiveTopology(DXIL::PrimitiveTopology::Undefined)
  70. , m_ActiveStreamMask(0)
  71. , m_NumGSInstances(1)
  72. , m_InputControlPointCount(0)
  73. , m_TessellatorDomain(DXIL::TessellatorDomain::Undefined)
  74. , m_OutputControlPointCount(0)
  75. , m_TessellatorPartitioning(DXIL::TessellatorPartitioning::Undefined)
  76. , m_TessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive::Undefined)
  77. , m_MaxTessellationFactor(0.f)
  78. , m_RootSignature(nullptr) {
  79. DXASSERT_NOMSG(m_pModule != nullptr);
  80. m_NumThreads[0] = m_NumThreads[1] = m_NumThreads[2] = 0;
  81. #if defined(_DEBUG) || defined(DBG)
  82. // Pin LLVM dump methods.
  83. void (__thiscall Module::*pfnModuleDump)() const = &Module::dump;
  84. void (__thiscall Type::*pfnTypeDump)() const = &Type::dump;
  85. void (__thiscall Function::*pfnViewCFGOnly)() const = &Function::viewCFGOnly;
  86. m_pUnused = (char *)&pfnModuleDump - (char *)&pfnTypeDump;
  87. m_pUnused -= (size_t)&pfnViewCFGOnly;
  88. #endif
  89. }
  90. DxilModule::~DxilModule() {
  91. }
  92. DxilModule::ShaderFlags::ShaderFlags():
  93. m_bDisableOptimizations(false)
  94. , m_bDisableMathRefactoring(false)
  95. , m_bEnableDoublePrecision(false)
  96. , m_bForceEarlyDepthStencil(false)
  97. , m_bEnableRawAndStructuredBuffers(false)
  98. , m_bEnableMinPrecision(false)
  99. , m_bEnableDoubleExtensions(false)
  100. , m_bEnableMSAD(false)
  101. , m_bAllResourcesBound(false)
  102. , m_bViewportAndRTArrayIndex(false)
  103. , m_bInnerCoverage(false)
  104. , m_bStencilRef(false)
  105. , m_bTiledResources(false)
  106. , m_bUAVLoadAdditionalFormats(false)
  107. , m_bLevel9ComparisonFiltering(false)
  108. , m_bCSRawAndStructuredViaShader4X(false)
  109. , m_b64UAVs(false)
  110. , m_UAVsAtEveryStage(false)
  111. , m_bROVS(false)
  112. , m_bWaveOps(false)
  113. , m_bInt64Ops(false)
  114. , m_bViewID(false)
  115. , m_bBarycentrics(false)
  116. , m_align0(0)
  117. , m_align1(0)
  118. {}
  119. LLVMContext &DxilModule::GetCtx() const { return m_Ctx; }
  120. Module *DxilModule::GetModule() const { return m_pModule; }
  121. OP *DxilModule::GetOP() const { return m_pOP.get(); }
  122. void DxilModule::SetShaderModel(const ShaderModel *pSM) {
  123. DXASSERT(m_pSM == nullptr || (pSM != nullptr && *m_pSM == *pSM), "shader model must not change for the module");
  124. DXASSERT(pSM != nullptr && pSM->IsValidForDxil(), "shader model must be valid");
  125. m_pSM = pSM;
  126. m_pSM->GetDxilVersion(m_DxilMajor, m_DxilMinor);
  127. m_pMDHelper->SetShaderModel(m_pSM);
  128. DXIL::ShaderKind shaderKind = pSM->GetKind();
  129. m_EntrySignature = llvm::make_unique<DxilEntrySignature>(shaderKind);
  130. m_RootSignature.reset(new RootSignatureHandle());
  131. }
  132. const ShaderModel *DxilModule::GetShaderModel() const {
  133. return m_pSM;
  134. }
  135. void DxilModule::GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const {
  136. DxilMajor = m_DxilMajor;
  137. DxilMinor = m_DxilMinor;
  138. }
  139. void DxilModule::SetValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
  140. m_ValMajor = ValMajor;
  141. m_ValMinor = ValMinor;
  142. }
  143. bool DxilModule::UpgradeValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
  144. if (ValMajor > m_ValMajor || (ValMajor == m_ValMajor && ValMinor > m_ValMinor)) {
  145. // Module requires higher validator version than previously set
  146. SetValidatorVersion(ValMajor, ValMinor);
  147. return true;
  148. }
  149. return false;
  150. }
  151. void DxilModule::GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
  152. ValMajor = m_ValMajor;
  153. ValMinor = m_ValMinor;
  154. }
  155. bool DxilModule::GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
  156. if (!m_pSM)
  157. return false;
  158. m_pSM->GetMinValidatorVersion(ValMajor, ValMinor);
  159. if (ValMajor == 1 && ValMinor == 0 && (m_ShaderFlags.GetFeatureInfo() & hlsl::ShaderFeatureInfo_ViewID))
  160. ValMinor = 1;
  161. return true;
  162. }
  163. bool DxilModule::UpgradeToMinValidatorVersion() {
  164. unsigned ValMajor = 1, ValMinor = 0;
  165. if (GetMinValidatorVersion(ValMajor, ValMinor)) {
  166. return UpgradeValidatorVersion(ValMajor, ValMinor);
  167. }
  168. return false;
  169. }
  170. Function *DxilModule::GetEntryFunction() {
  171. return m_pEntryFunc;
  172. }
  173. const Function *DxilModule::GetEntryFunction() const {
  174. return m_pEntryFunc;
  175. }
  176. void DxilModule::SetEntryFunction(Function *pEntryFunc) {
  177. m_pEntryFunc = pEntryFunc;
  178. }
  179. const string &DxilModule::GetEntryFunctionName() const {
  180. return m_EntryName;
  181. }
  182. void DxilModule::SetEntryFunctionName(const string &name) {
  183. m_EntryName = name;
  184. }
  185. llvm::Function *DxilModule::GetPatchConstantFunction() {
  186. return m_pPatchConstantFunc;
  187. }
  188. const llvm::Function *DxilModule::GetPatchConstantFunction() const {
  189. return m_pPatchConstantFunc;
  190. }
  191. void DxilModule::SetPatchConstantFunction(llvm::Function *pFunc) {
  192. m_pPatchConstantFunc = pFunc;
  193. }
  194. unsigned DxilModule::ShaderFlags::GetGlobalFlags() const {
  195. unsigned Flags = 0;
  196. Flags |= m_bDisableOptimizations ? DXIL::kDisableOptimizations : 0;
  197. Flags |= m_bDisableMathRefactoring ? DXIL::kDisableMathRefactoring : 0;
  198. Flags |= m_bEnableDoublePrecision ? DXIL::kEnableDoublePrecision : 0;
  199. Flags |= m_bForceEarlyDepthStencil ? DXIL::kForceEarlyDepthStencil : 0;
  200. Flags |= m_bEnableRawAndStructuredBuffers ? DXIL::kEnableRawAndStructuredBuffers : 0;
  201. Flags |= m_bEnableMinPrecision ? DXIL::kEnableMinPrecision : 0;
  202. Flags |= m_bEnableDoubleExtensions ? DXIL::kEnableDoubleExtensions : 0;
  203. Flags |= m_bEnableMSAD ? DXIL::kEnableMSAD : 0;
  204. Flags |= m_bAllResourcesBound ? DXIL::kAllResourcesBound : 0;
  205. return Flags;
  206. }
  207. uint64_t DxilModule::ShaderFlags::GetFeatureInfo() const {
  208. uint64_t Flags = 0;
  209. Flags |= m_bEnableDoublePrecision ? hlsl::ShaderFeatureInfo_Doubles : 0;
  210. Flags |= m_bEnableMinPrecision ? hlsl::ShaderFeatureInfo_MininumPrecision : 0;
  211. Flags |= m_bEnableDoubleExtensions ? hlsl::ShaderFeatureInfo_11_1_DoubleExtensions : 0;
  212. Flags |= m_bWaveOps ? hlsl::ShaderFeatureInfo_WaveOps : 0;
  213. Flags |= m_bInt64Ops ? hlsl::ShaderFeatureInfo_Int64Ops : 0;
  214. Flags |= m_bROVS ? hlsl::ShaderFeatureInfo_ROVs : 0;
  215. Flags |= m_bViewportAndRTArrayIndex ? hlsl::ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer : 0;
  216. Flags |= m_bInnerCoverage ? hlsl::ShaderFeatureInfo_InnerCoverage : 0;
  217. Flags |= m_bStencilRef ? hlsl::ShaderFeatureInfo_StencilRef : 0;
  218. Flags |= m_bTiledResources ? hlsl::ShaderFeatureInfo_TiledResources : 0;
  219. Flags |= m_bEnableMSAD ? hlsl::ShaderFeatureInfo_11_1_ShaderExtensions : 0;
  220. Flags |= m_bCSRawAndStructuredViaShader4X ? hlsl::ShaderFeatureInfo_ComputeShadersPlusRawAndStructuredBuffersViaShader4X : 0;
  221. Flags |= m_UAVsAtEveryStage ? hlsl::ShaderFeatureInfo_UAVsAtEveryStage : 0;
  222. Flags |= m_b64UAVs ? hlsl::ShaderFeatureInfo_64UAVs : 0;
  223. Flags |= m_bLevel9ComparisonFiltering ? hlsl::ShaderFeatureInfo_LEVEL9ComparisonFiltering : 0;
  224. Flags |= m_bUAVLoadAdditionalFormats ? hlsl::ShaderFeatureInfo_TypedUAVLoadAdditionalFormats : 0;
  225. Flags |= m_bViewID ? hlsl::ShaderFeatureInfo_ViewID : 0;
  226. Flags |= m_bBarycentrics ? hlsl::ShaderFeatureInfo_Barycentrics : 0;
  227. return Flags;
  228. }
  229. uint64_t DxilModule::ShaderFlags::GetShaderFlagsRaw() const {
  230. union Cast {
  231. Cast(const DxilModule::ShaderFlags &flags) {
  232. shaderFlags = flags;
  233. }
  234. DxilModule::ShaderFlags shaderFlags;
  235. uint64_t rawData;
  236. };
  237. static_assert(sizeof(uint64_t) == sizeof(DxilModule::ShaderFlags),
  238. "size must match to make sure no undefined bits when cast");
  239. Cast rawCast(*this);
  240. return rawCast.rawData;
  241. }
  242. void DxilModule::ShaderFlags::SetShaderFlagsRaw(uint64_t data) {
  243. union Cast {
  244. Cast(uint64_t data) {
  245. rawData = data;
  246. }
  247. DxilModule::ShaderFlags shaderFlags;
  248. uint64_t rawData;
  249. };
  250. Cast rawCast(data);
  251. *this = rawCast.shaderFlags;
  252. }
  253. unsigned DxilModule::GetGlobalFlags() const {
  254. unsigned Flags = m_ShaderFlags.GetGlobalFlags();
  255. return Flags;
  256. }
  257. static bool IsResourceSingleComponent(llvm::Type *Ty) {
  258. if (llvm::ArrayType *arrType = llvm::dyn_cast<llvm::ArrayType>(Ty)) {
  259. if (arrType->getArrayNumElements() > 1) {
  260. return false;
  261. }
  262. return IsResourceSingleComponent(arrType->getArrayElementType());
  263. } else if (llvm::StructType *structType =
  264. llvm::dyn_cast<llvm::StructType>(Ty)) {
  265. if (structType->getStructNumElements() > 1) {
  266. return false;
  267. }
  268. return IsResourceSingleComponent(structType->getStructElementType(0));
  269. } else if (llvm::VectorType *vectorType =
  270. llvm::dyn_cast<llvm::VectorType>(Ty)) {
  271. if (vectorType->getNumElements() > 1) {
  272. return false;
  273. }
  274. return IsResourceSingleComponent(vectorType->getVectorElementType());
  275. }
  276. return true;
  277. }
  278. bool DxilModule::ModuleHasMulticomponentUAVLoads() {
  279. for (const auto &uav : GetUAVs()) {
  280. const DxilResource *res = uav.get();
  281. if (res->IsTypedBuffer() || res->IsAnyTexture()) {
  282. if (!IsResourceSingleComponent(res->GetRetType())) {
  283. return true;
  284. }
  285. }
  286. }
  287. return false;
  288. }
  289. void DxilModule::CollectShaderFlags(ShaderFlags &Flags) {
  290. bool hasDouble = false;
  291. // ddiv dfma drcp d2i d2u i2d u2d.
  292. // fma has dxil op. Others should check IR instruction div/cast.
  293. bool hasDoubleExtension = false;
  294. bool has64Int = false;
  295. bool has16FloatInt = false;
  296. bool hasWaveOps = false;
  297. bool hasCheckAccessFully = false;
  298. bool hasMSAD = false;
  299. bool hasInnerCoverage = false;
  300. bool hasViewID = false;
  301. bool hasMulticomponentUAVLoads = false;
  302. bool hasMulticomponentUAVLoadsBackCompat = false;
  303. // Try to maintain compatibility with a v1.0 validator if that's what we have.
  304. {
  305. unsigned valMajor, valMinor;
  306. GetValidatorVersion(valMajor, valMinor);
  307. hasMulticomponentUAVLoadsBackCompat = valMajor <= 1 && valMinor == 0;
  308. }
  309. if (!hasMulticomponentUAVLoadsBackCompat)
  310. hasMulticomponentUAVLoads = ModuleHasMulticomponentUAVLoads();
  311. Type *int16Ty = Type::getInt16Ty(GetCtx());
  312. Type *int64Ty = Type::getInt64Ty(GetCtx());
  313. for (Function &F : GetModule()->functions()) {
  314. for (BasicBlock &BB : F.getBasicBlockList()) {
  315. for (Instruction &I : BB.getInstList()) {
  316. // Skip none dxil function call.
  317. if (CallInst *CI = dyn_cast<CallInst>(&I)) {
  318. if (!OP::IsDxilOpFunc(CI->getCalledFunction()))
  319. continue;
  320. }
  321. Type *Ty = I.getType();
  322. bool isDouble = Ty->isDoubleTy();
  323. bool isHalf = Ty->isHalfTy();
  324. bool isInt16 = Ty == int16Ty;
  325. bool isInt64 = Ty == int64Ty;
  326. if (isa<ExtractElementInst>(&I) ||
  327. isa<InsertElementInst>(&I))
  328. continue;
  329. for (Value *operand : I.operands()) {
  330. Type *Ty = operand->getType();
  331. isDouble |= Ty->isDoubleTy();
  332. isHalf |= Ty->isHalfTy();
  333. isInt16 |= Ty == int16Ty;
  334. isInt64 |= Ty == int64Ty;
  335. }
  336. if (isDouble) {
  337. hasDouble = true;
  338. switch (I.getOpcode()) {
  339. case Instruction::FDiv:
  340. case Instruction::UIToFP:
  341. case Instruction::SIToFP:
  342. case Instruction::FPToUI:
  343. case Instruction::FPToSI:
  344. hasDoubleExtension = true;
  345. break;
  346. }
  347. }
  348. has16FloatInt |= isHalf;
  349. has16FloatInt |= isInt16;
  350. has64Int |= isInt64;
  351. if (CallInst *CI = dyn_cast<CallInst>(&I)) {
  352. if (!OP::IsDxilOpFunc(CI->getCalledFunction()))
  353. continue;
  354. Value *opcodeArg = CI->getArgOperand(DXIL::OperandIndex::kOpcodeIdx);
  355. ConstantInt *opcodeConst = dyn_cast<ConstantInt>(opcodeArg);
  356. DXASSERT(opcodeConst, "DXIL opcode arg must be immediate");
  357. unsigned opcode = opcodeConst->getLimitedValue();
  358. DXASSERT(opcode < static_cast<unsigned>(DXIL::OpCode::NumOpCodes),
  359. "invalid DXIL opcode");
  360. DXIL::OpCode dxilOp = static_cast<DXIL::OpCode>(opcode);
  361. if (hlsl::OP::IsDxilOpWave(dxilOp))
  362. hasWaveOps = true;
  363. switch (dxilOp) {
  364. case DXIL::OpCode::CheckAccessFullyMapped:
  365. hasCheckAccessFully = true;
  366. break;
  367. case DXIL::OpCode::Msad:
  368. hasMSAD = true;
  369. break;
  370. case DXIL::OpCode::BufferLoad:
  371. case DXIL::OpCode::TextureLoad: {
  372. if (hasMulticomponentUAVLoads) continue;
  373. if (!hasMulticomponentUAVLoadsBackCompat) continue;
  374. // This is the old-style computation (overestimating requirements).
  375. Value *resHandle = CI->getArgOperand(DXIL::OperandIndex::kBufferStoreHandleOpIdx);
  376. CallInst *handleCall = cast<CallInst>(resHandle);
  377. if (ConstantInt *resClassArg =
  378. dyn_cast<ConstantInt>(handleCall->getArgOperand(
  379. DXIL::OperandIndex::kCreateHandleResClassOpIdx))) {
  380. DXIL::ResourceClass resClass = static_cast<DXIL::ResourceClass>(
  381. resClassArg->getLimitedValue());
  382. if (resClass == DXIL::ResourceClass::UAV) {
  383. // For DXIL, all uav load is multi component load.
  384. hasMulticomponentUAVLoads = true;
  385. }
  386. }
  387. else if (PHINode *resClassPhi = dyn_cast<
  388. PHINode>(handleCall->getArgOperand(
  389. DXIL::OperandIndex::kCreateHandleResClassOpIdx))) {
  390. unsigned numOperands = resClassPhi->getNumOperands();
  391. for (unsigned i = 0; i < numOperands; i++) {
  392. if (ConstantInt *resClassArg = dyn_cast<ConstantInt>(
  393. resClassPhi->getIncomingValue(i))) {
  394. DXIL::ResourceClass resClass =
  395. static_cast<DXIL::ResourceClass>(
  396. resClassArg->getLimitedValue());
  397. if (resClass == DXIL::ResourceClass::UAV) {
  398. // For DXIL, all uav load is multi component load.
  399. hasMulticomponentUAVLoads = true;
  400. break;
  401. }
  402. }
  403. }
  404. }
  405. } break;
  406. case DXIL::OpCode::Fma:
  407. hasDoubleExtension |= isDouble;
  408. break;
  409. case DXIL::OpCode::InnerCoverage:
  410. hasInnerCoverage = true;
  411. break;
  412. case DXIL::OpCode::ViewID:
  413. hasViewID = true;
  414. break;
  415. default:
  416. // Normal opcodes.
  417. break;
  418. }
  419. }
  420. }
  421. }
  422. }
  423. Flags.SetEnableDoublePrecision(hasDouble);
  424. Flags.SetInt64Ops(has64Int);
  425. Flags.SetEnableMinPrecision(has16FloatInt);
  426. Flags.SetEnableDoubleExtensions(hasDoubleExtension);
  427. Flags.SetWaveOps(hasWaveOps);
  428. Flags.SetTiledResources(hasCheckAccessFully);
  429. Flags.SetEnableMSAD(hasMSAD);
  430. Flags.SetUAVLoadAdditionalFormats(hasMulticomponentUAVLoads);
  431. Flags.SetViewID(hasViewID);
  432. const ShaderModel *SM = GetShaderModel();
  433. if (SM->IsPS()) {
  434. bool hasStencilRef = false;
  435. DxilSignature &outS = GetOutputSignature();
  436. for (auto &&E : outS.GetElements()) {
  437. if (E->GetKind() == Semantic::Kind::StencilRef) {
  438. hasStencilRef = true;
  439. } else if (E->GetKind() == Semantic::Kind::InnerCoverage) {
  440. hasInnerCoverage = true;
  441. }
  442. }
  443. Flags.SetStencilRef(hasStencilRef);
  444. Flags.SetInnerCoverage(hasInnerCoverage);
  445. }
  446. bool checkInputRTArrayIndex =
  447. SM->IsGS() || SM->IsDS() || SM->IsHS() || SM->IsPS();
  448. if (checkInputRTArrayIndex) {
  449. bool hasViewportArrayIndex = false;
  450. bool hasRenderTargetArrayIndex = false;
  451. DxilSignature &inS = GetInputSignature();
  452. for (auto &E : inS.GetElements()) {
  453. if (E->GetKind() == Semantic::Kind::ViewPortArrayIndex) {
  454. hasViewportArrayIndex = true;
  455. } else if (E->GetKind() == Semantic::Kind::RenderTargetArrayIndex) {
  456. hasRenderTargetArrayIndex = true;
  457. }
  458. }
  459. Flags.SetViewportAndRTArrayIndex(hasViewportArrayIndex |
  460. hasRenderTargetArrayIndex);
  461. }
  462. bool checkOutputRTArrayIndex =
  463. SM->IsVS() || SM->IsDS() || SM->IsHS() || SM->IsPS();
  464. if (checkOutputRTArrayIndex) {
  465. bool hasViewportArrayIndex = false;
  466. bool hasRenderTargetArrayIndex = false;
  467. DxilSignature &outS = GetOutputSignature();
  468. for (auto &E : outS.GetElements()) {
  469. if (E->GetKind() == Semantic::Kind::ViewPortArrayIndex) {
  470. hasViewportArrayIndex = true;
  471. } else if (E->GetKind() == Semantic::Kind::RenderTargetArrayIndex) {
  472. hasRenderTargetArrayIndex = true;
  473. }
  474. }
  475. Flags.SetViewportAndRTArrayIndex(hasViewportArrayIndex |
  476. hasRenderTargetArrayIndex);
  477. }
  478. unsigned NumUAVs = m_UAVs.size();
  479. const unsigned kSmallUAVCount = 8;
  480. if (NumUAVs > kSmallUAVCount)
  481. Flags.Set64UAVs(true);
  482. if (NumUAVs && !(SM->IsCS() || SM->IsPS()))
  483. Flags.SetUAVsAtEveryStage(true);
  484. bool hasRawAndStructuredBuffer = false;
  485. for (auto &UAV : m_UAVs) {
  486. if (UAV->IsROV())
  487. Flags.SetROVs(true);
  488. switch (UAV->GetKind()) {
  489. case DXIL::ResourceKind::RawBuffer:
  490. case DXIL::ResourceKind::StructuredBuffer:
  491. hasRawAndStructuredBuffer = true;
  492. break;
  493. default:
  494. // Not raw/structured.
  495. break;
  496. }
  497. }
  498. for (auto &SRV : m_SRVs) {
  499. switch (SRV->GetKind()) {
  500. case DXIL::ResourceKind::RawBuffer:
  501. case DXIL::ResourceKind::StructuredBuffer:
  502. hasRawAndStructuredBuffer = true;
  503. break;
  504. default:
  505. // Not raw/structured.
  506. break;
  507. }
  508. }
  509. Flags.SetEnableRawAndStructuredBuffers(hasRawAndStructuredBuffer);
  510. bool hasCSRawAndStructuredViaShader4X =
  511. hasRawAndStructuredBuffer && m_pSM->GetMajor() == 4 && m_pSM->IsCS();
  512. Flags.SetCSRawAndStructuredViaShader4X(hasCSRawAndStructuredViaShader4X);
  513. }
  514. void DxilModule::CollectShaderFlags() {
  515. CollectShaderFlags(m_ShaderFlags);
  516. }
  517. uint64_t DxilModule::ShaderFlags::GetShaderFlagsRawForCollection() {
  518. // This should be all the flags that can be set by DxilModule::CollectShaderFlags.
  519. ShaderFlags Flags;
  520. Flags.SetEnableDoublePrecision(true);
  521. Flags.SetInt64Ops(true);
  522. Flags.SetEnableMinPrecision(true);
  523. Flags.SetEnableDoubleExtensions(true);
  524. Flags.SetWaveOps(true);
  525. Flags.SetTiledResources(true);
  526. Flags.SetEnableMSAD(true);
  527. Flags.SetUAVLoadAdditionalFormats(true);
  528. Flags.SetStencilRef(true);
  529. Flags.SetInnerCoverage(true);
  530. Flags.SetViewportAndRTArrayIndex(true);
  531. Flags.Set64UAVs(true);
  532. Flags.SetUAVsAtEveryStage(true);
  533. Flags.SetEnableRawAndStructuredBuffers(true);
  534. Flags.SetCSRawAndStructuredViaShader4X(true);
  535. Flags.SetViewID(true);
  536. Flags.SetBarycentrics(true);
  537. return Flags.GetShaderFlagsRaw();
  538. }
  539. DXIL::InputPrimitive DxilModule::GetInputPrimitive() const {
  540. return m_InputPrimitive;
  541. }
  542. void DxilModule::SetInputPrimitive(DXIL::InputPrimitive IP) {
  543. DXASSERT_NOMSG(m_InputPrimitive == DXIL::InputPrimitive::Undefined);
  544. DXASSERT_NOMSG(DXIL::InputPrimitive::Undefined < IP && IP < DXIL::InputPrimitive::LastEntry);
  545. m_InputPrimitive = IP;
  546. }
  547. unsigned DxilModule::GetMaxVertexCount() const {
  548. DXASSERT_NOMSG(m_MaxVertexCount != 0);
  549. return m_MaxVertexCount;
  550. }
  551. void DxilModule::SetMaxVertexCount(unsigned Count) {
  552. DXASSERT_NOMSG(m_MaxVertexCount == 0);
  553. m_MaxVertexCount = Count;
  554. }
  555. DXIL::PrimitiveTopology DxilModule::GetStreamPrimitiveTopology() const {
  556. return m_StreamPrimitiveTopology;
  557. }
  558. void DxilModule::SetStreamPrimitiveTopology(DXIL::PrimitiveTopology Topology) {
  559. m_StreamPrimitiveTopology = Topology;
  560. }
  561. bool DxilModule::HasMultipleOutputStreams() const {
  562. if (!m_pSM->IsGS()) {
  563. return false;
  564. } else {
  565. unsigned NumStreams = (m_ActiveStreamMask & 0x1) +
  566. ((m_ActiveStreamMask & 0x2) >> 1) +
  567. ((m_ActiveStreamMask & 0x4) >> 2) +
  568. ((m_ActiveStreamMask & 0x8) >> 3);
  569. DXASSERT_NOMSG(NumStreams <= DXIL::kNumOutputStreams);
  570. return NumStreams > 1;
  571. }
  572. }
  573. unsigned DxilModule::GetOutputStream() const {
  574. if (!m_pSM->IsGS()) {
  575. return 0;
  576. } else {
  577. DXASSERT_NOMSG(!HasMultipleOutputStreams());
  578. switch (m_ActiveStreamMask) {
  579. case 0x1: return 0;
  580. case 0x2: return 1;
  581. case 0x4: return 2;
  582. case 0x8: return 3;
  583. default: DXASSERT_NOMSG(false);
  584. }
  585. return (unsigned)(-1);
  586. }
  587. }
  588. unsigned DxilModule::GetGSInstanceCount() const {
  589. return m_NumGSInstances;
  590. }
  591. void DxilModule::SetGSInstanceCount(unsigned Count) {
  592. m_NumGSInstances = Count;
  593. }
  594. bool DxilModule::IsStreamActive(unsigned Stream) const {
  595. return (m_ActiveStreamMask & (1<<Stream)) != 0;
  596. }
  597. void DxilModule::SetStreamActive(unsigned Stream, bool bActive) {
  598. if (bActive) {
  599. m_ActiveStreamMask |= (1<<Stream);
  600. } else {
  601. m_ActiveStreamMask &= ~(1<<Stream);
  602. }
  603. }
  604. void DxilModule::SetActiveStreamMask(unsigned Mask) {
  605. m_ActiveStreamMask = Mask;
  606. }
  607. unsigned DxilModule::GetActiveStreamMask() const {
  608. return m_ActiveStreamMask;
  609. }
  610. unsigned DxilModule::GetInputControlPointCount() const {
  611. return m_InputControlPointCount;
  612. }
  613. void DxilModule::SetInputControlPointCount(unsigned NumICPs) {
  614. m_InputControlPointCount = NumICPs;
  615. }
  616. DXIL::TessellatorDomain DxilModule::GetTessellatorDomain() const {
  617. return m_TessellatorDomain;
  618. }
  619. void DxilModule::SetTessellatorDomain(DXIL::TessellatorDomain TessDomain) {
  620. m_TessellatorDomain = TessDomain;
  621. }
  622. unsigned DxilModule::GetOutputControlPointCount() const {
  623. return m_OutputControlPointCount;
  624. }
  625. void DxilModule::SetOutputControlPointCount(unsigned NumOCPs) {
  626. m_OutputControlPointCount = NumOCPs;
  627. }
  628. DXIL::TessellatorPartitioning DxilModule::GetTessellatorPartitioning() const {
  629. return m_TessellatorPartitioning;
  630. }
  631. void DxilModule::SetTessellatorPartitioning(DXIL::TessellatorPartitioning TessPartitioning) {
  632. m_TessellatorPartitioning = TessPartitioning;
  633. }
  634. DXIL::TessellatorOutputPrimitive DxilModule::GetTessellatorOutputPrimitive() const {
  635. return m_TessellatorOutputPrimitive;
  636. }
  637. void DxilModule::SetTessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive TessOutputPrimitive) {
  638. m_TessellatorOutputPrimitive = TessOutputPrimitive;
  639. }
  640. float DxilModule::GetMaxTessellationFactor() const {
  641. return m_MaxTessellationFactor;
  642. }
  643. void DxilModule::SetMaxTessellationFactor(float MaxTessellationFactor) {
  644. m_MaxTessellationFactor = MaxTessellationFactor;
  645. }
  646. void DxilModule::SetShaderProperties(DxilFunctionProps *props) {
  647. if (!props)
  648. return;
  649. switch (props->shaderKind) {
  650. case DXIL::ShaderKind::Pixel: {
  651. auto &PS = props->ShaderProps.PS;
  652. m_ShaderFlags.SetForceEarlyDepthStencil(PS.EarlyDepthStencil);
  653. } break;
  654. case DXIL::ShaderKind::Compute: {
  655. auto &CS = props->ShaderProps.CS;
  656. for (size_t i = 0; i < _countof(m_NumThreads); ++i)
  657. m_NumThreads[i] = CS.numThreads[i];
  658. } break;
  659. case DXIL::ShaderKind::Domain: {
  660. auto &DS = props->ShaderProps.DS;
  661. SetTessellatorDomain(DS.domain);
  662. SetInputControlPointCount(DS.inputControlPoints);
  663. } break;
  664. case DXIL::ShaderKind::Hull: {
  665. auto &HS = props->ShaderProps.HS;
  666. SetPatchConstantFunction(HS.patchConstantFunc);
  667. SetTessellatorDomain(HS.domain);
  668. SetTessellatorPartitioning(HS.partition);
  669. SetTessellatorOutputPrimitive(HS.outputPrimitive);
  670. SetInputControlPointCount(HS.inputControlPoints);
  671. SetOutputControlPointCount(HS.outputControlPoints);
  672. SetMaxTessellationFactor(HS.maxTessFactor);
  673. } break;
  674. case DXIL::ShaderKind::Vertex:
  675. break;
  676. default: {
  677. DXASSERT(props->shaderKind == DXIL::ShaderKind::Geometry,
  678. "else invalid shader kind");
  679. auto &GS = props->ShaderProps.GS;
  680. SetInputPrimitive(GS.inputPrimitive);
  681. SetMaxVertexCount(GS.maxVertexCount);
  682. for (size_t i = 0; i < _countof(GS.streamPrimitiveTopologies); ++i) {
  683. if (GS.streamPrimitiveTopologies[i] !=
  684. DXIL::PrimitiveTopology::Undefined) {
  685. SetStreamActive(i, true);
  686. DXASSERT_NOMSG(GetStreamPrimitiveTopology() ==
  687. DXIL::PrimitiveTopology::Undefined ||
  688. GetStreamPrimitiveTopology() ==
  689. GS.streamPrimitiveTopologies[i]);
  690. SetStreamPrimitiveTopology(GS.streamPrimitiveTopologies[i]);
  691. }
  692. }
  693. SetGSInstanceCount(GS.instanceCount);
  694. } break;
  695. }
  696. }
  697. template<typename T> unsigned
  698. DxilModule::AddResource(vector<unique_ptr<T> > &Vec, unique_ptr<T> pRes) {
  699. DXASSERT_NOMSG((unsigned)Vec.size() < UINT_MAX);
  700. unsigned Id = (unsigned)Vec.size();
  701. Vec.emplace_back(std::move(pRes));
  702. return Id;
  703. }
  704. unsigned DxilModule::AddCBuffer(unique_ptr<DxilCBuffer> pCB) {
  705. return AddResource<DxilCBuffer>(m_CBuffers, std::move(pCB));
  706. }
  707. DxilCBuffer &DxilModule::GetCBuffer(unsigned idx) {
  708. return *m_CBuffers[idx];
  709. }
  710. const DxilCBuffer &DxilModule::GetCBuffer(unsigned idx) const {
  711. return *m_CBuffers[idx];
  712. }
  713. const vector<unique_ptr<DxilCBuffer> > &DxilModule::GetCBuffers() const {
  714. return m_CBuffers;
  715. }
  716. unsigned DxilModule::AddSampler(unique_ptr<DxilSampler> pSampler) {
  717. return AddResource<DxilSampler>(m_Samplers, std::move(pSampler));
  718. }
  719. DxilSampler &DxilModule::GetSampler(unsigned idx) {
  720. return *m_Samplers[idx];
  721. }
  722. const DxilSampler &DxilModule::GetSampler(unsigned idx) const {
  723. return *m_Samplers[idx];
  724. }
  725. const vector<unique_ptr<DxilSampler> > &DxilModule::GetSamplers() const {
  726. return m_Samplers;
  727. }
  728. unsigned DxilModule::AddSRV(unique_ptr<DxilResource> pSRV) {
  729. return AddResource<DxilResource>(m_SRVs, std::move(pSRV));
  730. }
  731. DxilResource &DxilModule::GetSRV(unsigned idx) {
  732. return *m_SRVs[idx];
  733. }
  734. const DxilResource &DxilModule::GetSRV(unsigned idx) const {
  735. return *m_SRVs[idx];
  736. }
  737. const vector<unique_ptr<DxilResource> > &DxilModule::GetSRVs() const {
  738. return m_SRVs;
  739. }
  740. unsigned DxilModule::AddUAV(unique_ptr<DxilResource> pUAV) {
  741. return AddResource<DxilResource>(m_UAVs, std::move(pUAV));
  742. }
  743. DxilResource &DxilModule::GetUAV(unsigned idx) {
  744. return *m_UAVs[idx];
  745. }
  746. const DxilResource &DxilModule::GetUAV(unsigned idx) const {
  747. return *m_UAVs[idx];
  748. }
  749. const vector<unique_ptr<DxilResource> > &DxilModule::GetUAVs() const {
  750. return m_UAVs;
  751. }
  752. static void CreateResourceLinkConstant(Module &M, DxilResourceBase *pRes,
  753. std::vector<DxilModule::ResourceLinkInfo> &resLinkInfo) {
  754. Type *i32Ty = Type::getInt32Ty(M.getContext());
  755. const bool IsConstantTrue = true;
  756. Constant *NullInitVal = nullptr;
  757. GlobalVariable *rangeID = new GlobalVariable(
  758. M, i32Ty, IsConstantTrue, llvm::GlobalValue::ExternalLinkage, NullInitVal,
  759. pRes->GetGlobalName() + "_rangeID");
  760. GlobalVariable *index = new GlobalVariable(
  761. M, i32Ty, IsConstantTrue, llvm::GlobalValue::ExternalLinkage, NullInitVal,
  762. pRes->GetGlobalName() + "_index");
  763. resLinkInfo.emplace_back(DxilModule::ResourceLinkInfo{rangeID, index});
  764. }
  765. void DxilModule::CreateResourceLinkInfo() {
  766. DXASSERT(GetShaderModel()->IsLib(), "only for library profile");
  767. DXASSERT(m_SRVsLinkInfo.empty() && m_UAVsLinkInfo.empty() &&
  768. m_CBuffersLinkInfo.empty() && m_SamplersLinkInfo.empty(),
  769. "else resource link info was already created");
  770. Module &M = *m_pModule;
  771. for (auto &SRV : m_SRVs) {
  772. CreateResourceLinkConstant(M, SRV.get(), m_SRVsLinkInfo);
  773. }
  774. for (auto &UAV : m_UAVs) {
  775. CreateResourceLinkConstant(M, UAV.get(), m_UAVsLinkInfo);
  776. }
  777. for (auto &CBuffer : m_CBuffers) {
  778. CreateResourceLinkConstant(M, CBuffer.get(), m_CBuffersLinkInfo);
  779. }
  780. for (auto &Sampler : m_Samplers) {
  781. CreateResourceLinkConstant(M, Sampler.get(), m_SamplersLinkInfo);
  782. }
  783. }
  784. const DxilModule::ResourceLinkInfo &
  785. DxilModule::GetResourceLinkInfo(DXIL::ResourceClass resClass,
  786. unsigned rangeID) const {
  787. switch (resClass) {
  788. case DXIL::ResourceClass::UAV:
  789. return m_UAVsLinkInfo[rangeID];
  790. case DXIL::ResourceClass::CBuffer:
  791. return m_CBuffersLinkInfo[rangeID];
  792. case DXIL::ResourceClass::Sampler:
  793. return m_SamplersLinkInfo[rangeID];
  794. default:
  795. DXASSERT(DXIL::ResourceClass::SRV == resClass,
  796. "else invalid resource class");
  797. return m_SRVsLinkInfo[rangeID];
  798. }
  799. }
  800. void DxilModule::LoadDxilResourceBaseFromMDNode(MDNode *MD, DxilResourceBase &R) {
  801. return m_pMDHelper->LoadDxilResourceBaseFromMDNode(MD, R);
  802. }
  803. void DxilModule::LoadDxilResourceFromMDNode(llvm::MDNode *MD, DxilResource &R) {
  804. return m_pMDHelper->LoadDxilResourceFromMDNode(MD, R);
  805. }
  806. void DxilModule::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  807. return m_pMDHelper->LoadDxilSamplerFromMDNode(MD, S);
  808. }
  809. template <typename TResource>
  810. static void RemoveResources(std::vector<std::unique_ptr<TResource>> &vec,
  811. std::unordered_set<unsigned> &immResID) {
  812. for (std::vector<std::unique_ptr<TResource>>::iterator p = vec.begin(); p != vec.end();) {
  813. std::vector<std::unique_ptr<TResource>>::iterator c = p++;
  814. if (immResID.count((*c)->GetID()) == 0) {
  815. p = vec.erase(c);
  816. }
  817. }
  818. }
  819. static void CollectUsedResource(Value *resID,
  820. std::unordered_set<Value *> &usedResID) {
  821. if (usedResID.count(resID) > 0)
  822. return;
  823. usedResID.insert(resID);
  824. if (ConstantInt *cResID = dyn_cast<ConstantInt>(resID)) {
  825. // Do nothing
  826. } else if (ZExtInst *ZEI = dyn_cast<ZExtInst>(resID)) {
  827. if (ZEI->getSrcTy()->isIntegerTy()) {
  828. IntegerType *ITy = cast<IntegerType>(ZEI->getSrcTy());
  829. if (ITy->getBitWidth() == 1) {
  830. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 0));
  831. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 1));
  832. }
  833. }
  834. } else if (SelectInst *SI = dyn_cast<SelectInst>(resID)) {
  835. CollectUsedResource(SI->getTrueValue(), usedResID);
  836. CollectUsedResource(SI->getFalseValue(), usedResID);
  837. } else {
  838. PHINode *Phi = cast<PHINode>(resID);
  839. for (Use &U : Phi->incoming_values()) {
  840. CollectUsedResource(U.get(), usedResID);
  841. }
  842. }
  843. }
  844. static void ConvertUsedResource(std::unordered_set<unsigned> &immResID,
  845. std::unordered_set<Value *> &usedResID) {
  846. for (Value *V : usedResID) {
  847. if (ConstantInt *cResID = dyn_cast<ConstantInt>(V)) {
  848. immResID.insert(cResID->getLimitedValue());
  849. }
  850. }
  851. }
  852. void DxilModule::RemoveFunction(llvm::Function *F) {
  853. DXASSERT_NOMSG(F != nullptr);
  854. m_DxilFunctionPropsMap.erase(F);
  855. m_DxilEntrySignatureMap.erase(F);
  856. if (m_pTypeSystem.get()->GetFunctionAnnotation(F))
  857. m_pTypeSystem.get()->EraseFunctionAnnotation(F);
  858. m_pOP->RemoveFunction(F);
  859. }
  860. void DxilModule::RemoveUnusedResources() {
  861. hlsl::OP *hlslOP = GetOP();
  862. Function *createHandleFunc = hlslOP->GetOpFunc(DXIL::OpCode::CreateHandle, Type::getVoidTy(GetCtx()));
  863. if (createHandleFunc->user_empty()) {
  864. m_CBuffers.clear();
  865. m_UAVs.clear();
  866. m_SRVs.clear();
  867. m_Samplers.clear();
  868. createHandleFunc->eraseFromParent();
  869. return;
  870. }
  871. std::unordered_set<Value *> usedUAVID;
  872. std::unordered_set<Value *> usedSRVID;
  873. std::unordered_set<Value *> usedSamplerID;
  874. std::unordered_set<Value *> usedCBufID;
  875. // Collect used ID.
  876. for (User *U : createHandleFunc->users()) {
  877. CallInst *CI = cast<CallInst>(U);
  878. Value *vResClass =
  879. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
  880. ConstantInt *cResClass = cast<ConstantInt>(vResClass);
  881. DXIL::ResourceClass resClass =
  882. static_cast<DXIL::ResourceClass>(cResClass->getLimitedValue());
  883. // Skip unused resource handle.
  884. if (CI->user_empty())
  885. continue;
  886. Value *resID =
  887. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
  888. switch (resClass) {
  889. case DXIL::ResourceClass::CBuffer:
  890. CollectUsedResource(resID, usedCBufID);
  891. break;
  892. case DXIL::ResourceClass::Sampler:
  893. CollectUsedResource(resID, usedSamplerID);
  894. break;
  895. case DXIL::ResourceClass::SRV:
  896. CollectUsedResource(resID, usedSRVID);
  897. break;
  898. case DXIL::ResourceClass::UAV:
  899. CollectUsedResource(resID, usedUAVID);
  900. break;
  901. default:
  902. DXASSERT(0, "invalid res class");
  903. break;
  904. }
  905. }
  906. std::unordered_set<unsigned> immUAVID;
  907. std::unordered_set<unsigned> immSRVID;
  908. std::unordered_set<unsigned> immSamplerID;
  909. std::unordered_set<unsigned> immCBufID;
  910. ConvertUsedResource(immUAVID, usedUAVID);
  911. RemoveResources(m_UAVs, immUAVID);
  912. ConvertUsedResource(immSRVID, usedSRVID);
  913. ConvertUsedResource(immSamplerID, usedSamplerID);
  914. ConvertUsedResource(immCBufID, usedCBufID);
  915. RemoveResources(m_SRVs, immSRVID);
  916. RemoveResources(m_Samplers, immSamplerID);
  917. RemoveResources(m_CBuffers, immCBufID);
  918. }
  919. DxilSignature &DxilModule::GetInputSignature() {
  920. return m_EntrySignature->InputSignature;
  921. }
  922. const DxilSignature &DxilModule::GetInputSignature() const {
  923. return m_EntrySignature->InputSignature;
  924. }
  925. DxilSignature &DxilModule::GetOutputSignature() {
  926. return m_EntrySignature->OutputSignature;
  927. }
  928. const DxilSignature &DxilModule::GetOutputSignature() const {
  929. return m_EntrySignature->OutputSignature;
  930. }
  931. DxilSignature &DxilModule::GetPatchConstantSignature() {
  932. return m_EntrySignature->PatchConstantSignature;
  933. }
  934. const DxilSignature &DxilModule::GetPatchConstantSignature() const {
  935. return m_EntrySignature->PatchConstantSignature;
  936. }
  937. const RootSignatureHandle &DxilModule::GetRootSignature() const {
  938. return *m_RootSignature;
  939. }
  940. bool DxilModule::HasDxilEntrySignature(llvm::Function *F) const {
  941. return m_DxilEntrySignatureMap.find(F) != m_DxilEntrySignatureMap.end();
  942. }
  943. DxilEntrySignature &DxilModule::GetDxilEntrySignature(llvm::Function *F) {
  944. DXASSERT(m_DxilEntrySignatureMap.count(F) != 0, "cannot find F in map");
  945. return *m_DxilEntrySignatureMap[F];
  946. }
  947. void DxilModule::ReplaceDxilEntrySignature(llvm::Function *F,
  948. llvm::Function *NewF) {
  949. DXASSERT(m_DxilEntrySignatureMap.count(F) != 0, "cannot find F in map");
  950. std::unique_ptr<DxilEntrySignature> Sig =
  951. std::move(m_DxilEntrySignatureMap[F]);
  952. m_DxilEntrySignatureMap.erase(F);
  953. m_DxilEntrySignatureMap[NewF] = std::move(Sig);
  954. }
  955. bool DxilModule::HasDxilFunctionProps(llvm::Function *F) const {
  956. return m_DxilFunctionPropsMap.find(F) != m_DxilFunctionPropsMap.end();
  957. }
  958. DxilFunctionProps &DxilModule::GetDxilFunctionProps(llvm::Function *F) {
  959. DXASSERT(m_DxilFunctionPropsMap.count(F) != 0, "cannot find F in map");
  960. return *m_DxilFunctionPropsMap[F];
  961. }
  962. void DxilModule::ReplaceDxilFunctionProps(llvm::Function *F,
  963. llvm::Function *NewF) {
  964. DXASSERT(m_DxilFunctionPropsMap.count(F) != 0, "cannot find F in map");
  965. std::unique_ptr<DxilFunctionProps> props =
  966. std::move(m_DxilFunctionPropsMap[F]);
  967. m_DxilFunctionPropsMap.erase(F);
  968. m_DxilFunctionPropsMap[NewF] = std::move(props);
  969. }
  970. void DxilModule::StripRootSignatureFromMetadata() {
  971. NamedMDNode *pRootSignatureNamedMD = GetModule()->getNamedMetadata(DxilMDHelper::kDxilRootSignatureMDName);
  972. if (pRootSignatureNamedMD) {
  973. GetModule()->eraseNamedMetadata(pRootSignatureNamedMD);
  974. }
  975. }
  976. void DxilModule::UpdateValidatorVersionMetadata() {
  977. m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
  978. }
  979. void DxilModule::ResetEntrySignature(DxilEntrySignature *pValue) {
  980. m_EntrySignature.reset(pValue);
  981. }
  982. void DxilModule::ResetRootSignature(RootSignatureHandle *pValue) {
  983. m_RootSignature.reset(pValue);
  984. }
  985. DxilTypeSystem &DxilModule::GetTypeSystem() {
  986. return *m_pTypeSystem;
  987. }
  988. DxilViewIdState &DxilModule::GetViewIdState() {
  989. return *m_pViewIdState;
  990. }
  991. const DxilViewIdState &DxilModule::GetViewIdState() const {
  992. return *m_pViewIdState;
  993. }
  994. void DxilModule::ResetTypeSystem(DxilTypeSystem *pValue) {
  995. m_pTypeSystem.reset(pValue);
  996. }
  997. void DxilModule::ResetOP(hlsl::OP *hlslOP) { m_pOP.reset(hlslOP); }
  998. void DxilModule::ResetFunctionPropsMap(
  999. std::unordered_map<llvm::Function *, std::unique_ptr<DxilFunctionProps>>
  1000. &&propsMap) {
  1001. m_DxilFunctionPropsMap = std::move(propsMap);
  1002. }
  1003. void DxilModule::ResetEntrySignatureMap(
  1004. std::unordered_map<llvm::Function *, std::unique_ptr<DxilEntrySignature>>
  1005. &&SigMap) {
  1006. m_DxilEntrySignatureMap = std::move(SigMap);
  1007. }
  1008. void DxilModule::EmitLLVMUsed() {
  1009. if (m_LLVMUsed.empty())
  1010. return;
  1011. vector<llvm::Constant*> GVs;
  1012. Type *pI8PtrType = Type::getInt8PtrTy(m_Ctx, DXIL::kDefaultAddrSpace);
  1013. GVs.resize(m_LLVMUsed.size());
  1014. for (size_t i = 0, e = m_LLVMUsed.size(); i != e; i++) {
  1015. Constant *pConst = cast<Constant>(&*m_LLVMUsed[i]);
  1016. PointerType * pPtrType = dyn_cast<PointerType>(pConst->getType());
  1017. if (pPtrType->getPointerAddressSpace() != DXIL::kDefaultAddrSpace) {
  1018. // Cast pointer to addrspace 0, as LLVMUsed elements must have the same type.
  1019. GVs[i] = ConstantExpr::getAddrSpaceCast(pConst, pI8PtrType);
  1020. } else {
  1021. GVs[i] = ConstantExpr::getPointerCast(pConst, pI8PtrType);
  1022. }
  1023. }
  1024. ArrayType *pATy = ArrayType::get(pI8PtrType, GVs.size());
  1025. StringRef llvmUsedName = "llvm.used";
  1026. if (GlobalVariable *oldGV = m_pModule->getGlobalVariable(llvmUsedName)) {
  1027. oldGV->eraseFromParent();
  1028. }
  1029. GlobalVariable *pGV = new GlobalVariable(*m_pModule, pATy, false,
  1030. GlobalValue::AppendingLinkage,
  1031. ConstantArray::get(pATy, GVs),
  1032. llvmUsedName);
  1033. pGV->setSection("llvm.metadata");
  1034. }
  1035. vector<GlobalVariable* > &DxilModule::GetLLVMUsed() {
  1036. return m_LLVMUsed;
  1037. }
  1038. // DXIL metadata serialization/deserialization.
  1039. void DxilModule::EmitDxilMetadata() {
  1040. m_pMDHelper->EmitDxilVersion(m_DxilMajor, m_DxilMinor);
  1041. m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
  1042. m_pMDHelper->EmitDxilShaderModel(m_pSM);
  1043. MDTuple *pMDProperties = EmitDxilShaderProperties();
  1044. MDTuple *pMDSignatures = m_pMDHelper->EmitDxilSignatures(*m_EntrySignature);
  1045. MDTuple *pMDResources = EmitDxilResources();
  1046. m_pMDHelper->EmitDxilTypeSystem(GetTypeSystem(), m_LLVMUsed);
  1047. if (!m_pSM->IsCS() &&
  1048. (m_ValMajor > 1 || (m_ValMajor == 1 && m_ValMinor >= 1))) {
  1049. m_pMDHelper->EmitDxilViewIdState(GetViewIdState());
  1050. }
  1051. EmitLLVMUsed();
  1052. MDTuple *pEntry = m_pMDHelper->EmitDxilEntryPointTuple(GetEntryFunction(), m_EntryName, pMDSignatures, pMDResources, pMDProperties);
  1053. vector<MDNode *> Entries;
  1054. Entries.emplace_back(pEntry);
  1055. m_pMDHelper->EmitDxilEntryPoints(Entries);
  1056. if (!m_RootSignature->IsEmpty()) {
  1057. m_pMDHelper->EmitRootSignature(*m_RootSignature.get());
  1058. }
  1059. if (m_pSM->IsLib()) {
  1060. EmitDxilResourcesLinkInfo();
  1061. NamedMDNode *fnProps = m_pModule->getOrInsertNamedMetadata(
  1062. DxilMDHelper::kDxilFunctionPropertiesMDName);
  1063. for (auto &&pair : m_DxilFunctionPropsMap) {
  1064. const hlsl::DxilFunctionProps *props = pair.second.get();
  1065. MDTuple *pProps = m_pMDHelper->EmitDxilFunctionProps(props, pair.first);
  1066. fnProps->addOperand(pProps);
  1067. }
  1068. NamedMDNode *entrySigs = m_pModule->getOrInsertNamedMetadata(
  1069. DxilMDHelper::kDxilEntrySignaturesMDName);
  1070. for (auto &&pair : m_DxilEntrySignatureMap) {
  1071. Function *F = pair.first;
  1072. DxilEntrySignature *Sig = pair.second.get();
  1073. MDTuple *pSig = m_pMDHelper->EmitDxilSignatures(*Sig);
  1074. entrySigs->addOperand(
  1075. MDTuple::get(m_Ctx, {ValueAsMetadata::get(F), pSig}));
  1076. }
  1077. }
  1078. }
  1079. bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
  1080. return DxilMDHelper::IsKnownNamedMetaData(Node);
  1081. }
  1082. void DxilModule::LoadDxilMetadata() {
  1083. m_pMDHelper->LoadDxilVersion(m_DxilMajor, m_DxilMinor);
  1084. m_pMDHelper->LoadValidatorVersion(m_ValMajor, m_ValMinor);
  1085. const ShaderModel *loadedModule;
  1086. m_pMDHelper->LoadDxilShaderModel(loadedModule);
  1087. SetShaderModel(loadedModule);
  1088. DXASSERT(m_EntrySignature != nullptr, "else SetShaderModel didn't create entry signature");
  1089. const llvm::NamedMDNode *pEntries = m_pMDHelper->GetDxilEntryPoints();
  1090. IFTBOOL(pEntries->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1091. Function *pEntryFunc;
  1092. string EntryName;
  1093. const llvm::MDOperand *pSignatures, *pResources, *pProperties;
  1094. m_pMDHelper->GetDxilEntryPoint(pEntries->getOperand(0), pEntryFunc, EntryName, pSignatures, pResources, pProperties);
  1095. SetEntryFunction(pEntryFunc);
  1096. SetEntryFunctionName(EntryName);
  1097. LoadDxilShaderProperties(*pProperties);
  1098. m_pMDHelper->LoadDxilSignatures(*pSignatures, *m_EntrySignature);
  1099. LoadDxilResources(*pResources);
  1100. m_pMDHelper->LoadDxilTypeSystem(*m_pTypeSystem.get());
  1101. m_pMDHelper->LoadRootSignature(*m_RootSignature.get());
  1102. m_pMDHelper->LoadDxilViewIdState(*m_pViewIdState.get());
  1103. if (loadedModule->IsLib()) {
  1104. LoadDxilResourcesLinkInfo();
  1105. NamedMDNode *fnProps = m_pModule->getNamedMetadata(
  1106. DxilMDHelper::kDxilFunctionPropertiesMDName);
  1107. size_t propIdx = 0;
  1108. while (propIdx < fnProps->getNumOperands()) {
  1109. MDTuple *pProps = dyn_cast<MDTuple>(fnProps->getOperand(propIdx++));
  1110. std::unique_ptr<hlsl::DxilFunctionProps> props =
  1111. llvm::make_unique<hlsl::DxilFunctionProps>();
  1112. Function *F = m_pMDHelper->LoadDxilFunctionProps(pProps, props.get());
  1113. m_DxilFunctionPropsMap[F] = std::move(props);
  1114. }
  1115. NamedMDNode *entrySigs = m_pModule->getOrInsertNamedMetadata(
  1116. DxilMDHelper::kDxilEntrySignaturesMDName);
  1117. size_t sigIdx = 0;
  1118. while (sigIdx < entrySigs->getNumOperands()) {
  1119. MDTuple *pSig = dyn_cast<MDTuple>(entrySigs->getOperand(sigIdx++));
  1120. unsigned idx = 0;
  1121. Function *F = dyn_cast<Function>(
  1122. dyn_cast<ValueAsMetadata>(pSig->getOperand(idx++))->getValue());
  1123. // Entry must have props.
  1124. IFTBOOL(m_DxilFunctionPropsMap.count(F), DXC_E_INCORRECT_DXIL_METADATA);
  1125. DXIL::ShaderKind shaderKind = m_DxilFunctionPropsMap[F]->shaderKind;
  1126. std::unique_ptr<hlsl::DxilEntrySignature> Sig =
  1127. llvm::make_unique<hlsl::DxilEntrySignature>(shaderKind);
  1128. m_pMDHelper->LoadDxilSignatures(pSig->getOperand(idx), *Sig);
  1129. m_DxilEntrySignatureMap[F] = std::move(Sig);
  1130. }
  1131. }
  1132. }
  1133. MDTuple *DxilModule::EmitDxilResources() {
  1134. // Emit SRV records.
  1135. MDTuple *pTupleSRVs = nullptr;
  1136. if (!m_SRVs.empty()) {
  1137. vector<Metadata *> MDVals;
  1138. for (size_t i = 0; i < m_SRVs.size(); i++) {
  1139. MDVals.emplace_back(m_pMDHelper->EmitDxilSRV(*m_SRVs[i]));
  1140. }
  1141. pTupleSRVs = MDNode::get(m_Ctx, MDVals);
  1142. }
  1143. // Emit UAV records.
  1144. MDTuple *pTupleUAVs = nullptr;
  1145. if (!m_UAVs.empty()) {
  1146. vector<Metadata *> MDVals;
  1147. for (size_t i = 0; i < m_UAVs.size(); i++) {
  1148. MDVals.emplace_back(m_pMDHelper->EmitDxilUAV(*m_UAVs[i]));
  1149. }
  1150. pTupleUAVs = MDNode::get(m_Ctx, MDVals);
  1151. }
  1152. // Emit CBuffer records.
  1153. MDTuple *pTupleCBuffers = nullptr;
  1154. if (!m_CBuffers.empty()) {
  1155. vector<Metadata *> MDVals;
  1156. for (size_t i = 0; i < m_CBuffers.size(); i++) {
  1157. MDVals.emplace_back(m_pMDHelper->EmitDxilCBuffer(*m_CBuffers[i]));
  1158. }
  1159. pTupleCBuffers = MDNode::get(m_Ctx, MDVals);
  1160. }
  1161. // Emit Sampler records.
  1162. MDTuple *pTupleSamplers = nullptr;
  1163. if (!m_Samplers.empty()) {
  1164. vector<Metadata *> MDVals;
  1165. for (size_t i = 0; i < m_Samplers.size(); i++) {
  1166. MDVals.emplace_back(m_pMDHelper->EmitDxilSampler(*m_Samplers[i]));
  1167. }
  1168. pTupleSamplers = MDNode::get(m_Ctx, MDVals);
  1169. }
  1170. if (pTupleSRVs != nullptr || pTupleUAVs != nullptr || pTupleCBuffers != nullptr || pTupleSamplers != nullptr) {
  1171. return m_pMDHelper->EmitDxilResourceTuple(pTupleSRVs, pTupleUAVs, pTupleCBuffers, pTupleSamplers);
  1172. } else {
  1173. return nullptr;
  1174. }
  1175. }
  1176. void DxilModule::LoadDxilResources(const llvm::MDOperand &MDO) {
  1177. if (MDO.get() == nullptr)
  1178. return;
  1179. const llvm::MDTuple *pSRVs, *pUAVs, *pCBuffers, *pSamplers;
  1180. m_pMDHelper->GetDxilResources(MDO, pSRVs, pUAVs, pCBuffers, pSamplers);
  1181. // Load SRV records.
  1182. if (pSRVs != nullptr) {
  1183. for (unsigned i = 0; i < pSRVs->getNumOperands(); i++) {
  1184. unique_ptr<DxilResource> pSRV(new DxilResource);
  1185. m_pMDHelper->LoadDxilSRV(pSRVs->getOperand(i), *pSRV);
  1186. AddSRV(std::move(pSRV));
  1187. }
  1188. }
  1189. // Load UAV records.
  1190. if (pUAVs != nullptr) {
  1191. for (unsigned i = 0; i < pUAVs->getNumOperands(); i++) {
  1192. unique_ptr<DxilResource> pUAV(new DxilResource);
  1193. m_pMDHelper->LoadDxilUAV(pUAVs->getOperand(i), *pUAV);
  1194. AddUAV(std::move(pUAV));
  1195. }
  1196. }
  1197. // Load CBuffer records.
  1198. if (pCBuffers != nullptr) {
  1199. for (unsigned i = 0; i < pCBuffers->getNumOperands(); i++) {
  1200. unique_ptr<DxilCBuffer> pCB(new DxilCBuffer);
  1201. m_pMDHelper->LoadDxilCBuffer(pCBuffers->getOperand(i), *pCB);
  1202. AddCBuffer(std::move(pCB));
  1203. }
  1204. }
  1205. // Load Sampler records.
  1206. if (pSamplers != nullptr) {
  1207. for (unsigned i = 0; i < pSamplers->getNumOperands(); i++) {
  1208. unique_ptr<DxilSampler> pSampler(new DxilSampler);
  1209. m_pMDHelper->LoadDxilSampler(pSamplers->getOperand(i), *pSampler);
  1210. AddSampler(std::move(pSampler));
  1211. }
  1212. }
  1213. }
  1214. static MDTuple *CreateResourcesLinkInfo(std::vector<DxilModule::ResourceLinkInfo> &LinkInfoList,
  1215. unsigned size, LLVMContext &Ctx) {
  1216. DXASSERT(size == LinkInfoList.size(), "link info size must match resource size");
  1217. if (LinkInfoList.empty())
  1218. return nullptr;
  1219. vector<Metadata *> MDVals;
  1220. for (size_t i = 0; i < size; i++) {
  1221. MDVals.emplace_back(ValueAsMetadata::get(LinkInfoList[i].ResRangeID));
  1222. MDVals.emplace_back(ValueAsMetadata::get(LinkInfoList[i].ResIndex));
  1223. }
  1224. return MDNode::get(Ctx, MDVals);
  1225. }
  1226. void DxilModule::EmitDxilResourcesLinkInfo() {
  1227. // Emit SRV base records.
  1228. MDTuple *pTupleSRVs =
  1229. CreateResourcesLinkInfo(m_SRVsLinkInfo, m_SRVs.size(), m_Ctx);
  1230. // Emit UAV base records.
  1231. MDTuple *pTupleUAVs =
  1232. CreateResourcesLinkInfo(m_UAVsLinkInfo, m_UAVs.size(), m_Ctx);
  1233. // Emit CBuffer base records.
  1234. MDTuple *pTupleCBuffers =
  1235. CreateResourcesLinkInfo(m_CBuffersLinkInfo, m_CBuffers.size(), m_Ctx);
  1236. // Emit Sampler records.
  1237. MDTuple *pTupleSamplers =
  1238. CreateResourcesLinkInfo(m_SamplersLinkInfo, m_Samplers.size(), m_Ctx);
  1239. if (pTupleSRVs != nullptr || pTupleUAVs != nullptr ||
  1240. pTupleCBuffers != nullptr || pTupleSamplers != nullptr) {
  1241. m_pMDHelper->EmitDxilResourceLinkInfoTuple(pTupleSRVs, pTupleUAVs,
  1242. pTupleCBuffers, pTupleSamplers);
  1243. }
  1244. }
  1245. static void
  1246. LoadResourcesLinkInfo(const llvm::MDTuple *pMD,
  1247. std::vector<DxilModule::ResourceLinkInfo> &LinkInfoList,
  1248. unsigned size, DxilMDHelper *pMDHelper) {
  1249. if (!pMD) {
  1250. IFTBOOL(size == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1251. return;
  1252. }
  1253. unsigned operandSize = pMD->getNumOperands();
  1254. IFTBOOL(operandSize == (2 * size), DXC_E_INCORRECT_DXIL_METADATA);
  1255. for (unsigned i = 0; i < operandSize; i += 2) {
  1256. Constant *rangeID =
  1257. dyn_cast<Constant>(pMDHelper->ValueMDToValue(pMD->getOperand(i)));
  1258. Constant *index =
  1259. dyn_cast<Constant>(pMDHelper->ValueMDToValue(pMD->getOperand(i + 1)));
  1260. LinkInfoList.emplace_back(DxilModule::ResourceLinkInfo{rangeID, index});
  1261. }
  1262. }
  1263. void DxilModule::LoadDxilResourcesLinkInfo() {
  1264. const llvm::MDTuple *pSRVs, *pUAVs, *pCBuffers, *pSamplers;
  1265. m_pMDHelper->LoadDxilResourceLinkInfoTuple(pSRVs, pUAVs, pCBuffers,
  1266. pSamplers);
  1267. // Load SRV base records.
  1268. LoadResourcesLinkInfo(pSRVs, m_SRVsLinkInfo, m_SRVs.size(),
  1269. m_pMDHelper.get());
  1270. // Load UAV base records.
  1271. LoadResourcesLinkInfo(pUAVs, m_UAVsLinkInfo, m_UAVs.size(),
  1272. m_pMDHelper.get());
  1273. // Load CBuffer records.
  1274. LoadResourcesLinkInfo(pCBuffers, m_CBuffersLinkInfo, m_CBuffers.size(),
  1275. m_pMDHelper.get());
  1276. // Load Sampler records.
  1277. LoadResourcesLinkInfo(pSamplers, m_SamplersLinkInfo, m_Samplers.size(),
  1278. m_pMDHelper.get());
  1279. }
  1280. MDTuple *DxilModule::EmitDxilShaderProperties() {
  1281. vector<Metadata *> MDVals;
  1282. // DXIL shader flags.
  1283. uint64_t Flags = m_ShaderFlags.GetShaderFlagsRaw();
  1284. if (Flags != 0) {
  1285. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilShaderFlagsTag));
  1286. MDVals.emplace_back(m_pMDHelper->Uint64ToConstMD(Flags));
  1287. }
  1288. // Compute shader.
  1289. if (m_pSM->IsCS()) {
  1290. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  1291. vector<Metadata *> NumThreadVals;
  1292. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[0]));
  1293. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[1]));
  1294. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[2]));
  1295. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  1296. }
  1297. // Geometry shader.
  1298. if (m_pSM->IsGS()) {
  1299. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  1300. MDTuple *pMDTuple = m_pMDHelper->EmitDxilGSState(m_InputPrimitive,
  1301. m_MaxVertexCount,
  1302. GetActiveStreamMask(),
  1303. m_StreamPrimitiveTopology,
  1304. m_NumGSInstances);
  1305. MDVals.emplace_back(pMDTuple);
  1306. }
  1307. // Domain shader.
  1308. if (m_pSM->IsDS()) {
  1309. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  1310. MDTuple *pMDTuple = m_pMDHelper->EmitDxilDSState(m_TessellatorDomain,
  1311. m_InputControlPointCount);
  1312. MDVals.emplace_back(pMDTuple);
  1313. }
  1314. // Hull shader.
  1315. if (m_pSM->IsHS()) {
  1316. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  1317. MDTuple *pMDTuple = m_pMDHelper->EmitDxilHSState(m_pPatchConstantFunc,
  1318. m_InputControlPointCount,
  1319. m_OutputControlPointCount,
  1320. m_TessellatorDomain,
  1321. m_TessellatorPartitioning,
  1322. m_TessellatorOutputPrimitive,
  1323. m_MaxTessellationFactor);
  1324. MDVals.emplace_back(pMDTuple);
  1325. }
  1326. if (!MDVals.empty())
  1327. return MDNode::get(m_Ctx, MDVals);
  1328. else
  1329. return nullptr;
  1330. }
  1331. void DxilModule::LoadDxilShaderProperties(const MDOperand &MDO) {
  1332. if (MDO.get() == nullptr)
  1333. return;
  1334. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1335. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1336. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1337. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  1338. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  1339. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  1340. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1341. switch (Tag) {
  1342. case DxilMDHelper::kDxilShaderFlagsTag:
  1343. m_ShaderFlags.SetShaderFlagsRaw(DxilMDHelper::ConstMDToUint64(MDO));
  1344. break;
  1345. case DxilMDHelper::kDxilNumThreadsTag: {
  1346. MDNode *pNode = cast<MDNode>(MDO.get());
  1347. m_NumThreads[0] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(0));
  1348. m_NumThreads[1] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(1));
  1349. m_NumThreads[2] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(2));
  1350. break;
  1351. }
  1352. case DxilMDHelper::kDxilGSStateTag: {
  1353. m_pMDHelper->LoadDxilGSState(MDO, m_InputPrimitive, m_MaxVertexCount, m_ActiveStreamMask,
  1354. m_StreamPrimitiveTopology, m_NumGSInstances);
  1355. break;
  1356. }
  1357. case DxilMDHelper::kDxilDSStateTag:
  1358. m_pMDHelper->LoadDxilDSState(MDO, m_TessellatorDomain, m_InputControlPointCount);
  1359. break;
  1360. case DxilMDHelper::kDxilHSStateTag:
  1361. m_pMDHelper->LoadDxilHSState(MDO,
  1362. m_pPatchConstantFunc,
  1363. m_InputControlPointCount,
  1364. m_OutputControlPointCount,
  1365. m_TessellatorDomain,
  1366. m_TessellatorPartitioning,
  1367. m_TessellatorOutputPrimitive,
  1368. m_MaxTessellationFactor);
  1369. break;
  1370. default:
  1371. DXASSERT(false, "Unknown extended shader properties tag");
  1372. break;
  1373. }
  1374. }
  1375. }
  1376. void DxilModule::StripDebugRelatedCode() {
  1377. // Remove all users of global resources.
  1378. for (GlobalVariable &GV : m_pModule->globals()) {
  1379. if (GV.hasInternalLinkage())
  1380. continue;
  1381. if (GV.getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace)
  1382. continue;
  1383. for (auto git = GV.user_begin(); git != GV.user_end();) {
  1384. User *U = *(git++);
  1385. // Try to remove load of GV.
  1386. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  1387. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1388. Instruction *LIUser = cast<Instruction>(*(it++));
  1389. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1390. Value *Ptr = SI->getPointerOperand();
  1391. SI->eraseFromParent();
  1392. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1393. if (Ptr->user_empty())
  1394. PtrInst->eraseFromParent();
  1395. }
  1396. }
  1397. }
  1398. if (LI->user_empty())
  1399. LI->eraseFromParent();
  1400. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
  1401. for (auto GEPIt = GEP->user_begin(); GEPIt != GEP->user_end();) {
  1402. User *GEPU = *(GEPIt++);
  1403. // Try to remove load of GEP.
  1404. if (LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
  1405. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1406. Instruction *LIUser = cast<Instruction>(*(it++));
  1407. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1408. Value *Ptr = SI->getPointerOperand();
  1409. SI->eraseFromParent();
  1410. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1411. if (Ptr->user_empty())
  1412. PtrInst->eraseFromParent();
  1413. }
  1414. }
  1415. if (LI->user_empty())
  1416. LI->eraseFromParent();
  1417. }
  1418. }
  1419. }
  1420. if (GEP->user_empty())
  1421. GEP->eraseFromParent();
  1422. }
  1423. }
  1424. }
  1425. }
  1426. DebugInfoFinder &DxilModule::GetOrCreateDebugInfoFinder() {
  1427. if (m_pDebugInfoFinder == nullptr) {
  1428. m_pDebugInfoFinder = std::make_unique<llvm::DebugInfoFinder>();
  1429. m_pDebugInfoFinder->processModule(*m_pModule);
  1430. }
  1431. return *m_pDebugInfoFinder;
  1432. }
  1433. hlsl::DxilModule *hlsl::DxilModule::TryGetDxilModule(llvm::Module *pModule) {
  1434. LLVMContext &Ctx = pModule->getContext();
  1435. std::string diagStr;
  1436. raw_string_ostream diagStream(diagStr);
  1437. hlsl::DxilModule *pDxilModule = nullptr;
  1438. // TODO: add detail error in DxilMDHelper.
  1439. try {
  1440. pDxilModule = &pModule->GetOrCreateDxilModule();
  1441. } catch (const ::hlsl::Exception &hlslException) {
  1442. diagStream << "load dxil metadata failed -";
  1443. try {
  1444. const char *msg = hlslException.what();
  1445. if (msg == nullptr || *msg == '\0')
  1446. diagStream << " error code " << hlslException.hr << "\n";
  1447. else
  1448. diagStream << msg;
  1449. } catch (...) {
  1450. diagStream << " unable to retrieve error message.\n";
  1451. }
  1452. Ctx.diagnose(DxilErrorDiagnosticInfo(diagStream.str().c_str()));
  1453. } catch (...) {
  1454. Ctx.diagnose(DxilErrorDiagnosticInfo("load dxil metadata failed - unknown error.\n"));
  1455. }
  1456. return pDxilModule;
  1457. }
  1458. // Check if the instruction has fast math flags configured to indicate
  1459. // the instruction is precise.
  1460. // Precise fast math flags means none of the fast math flags are set.
  1461. bool DxilModule::HasPreciseFastMathFlags(const Instruction *inst) {
  1462. return isa<FPMathOperator>(inst) && !inst->getFastMathFlags().any();
  1463. }
  1464. // Set fast math flags configured to indicate the instruction is precise.
  1465. void DxilModule::SetPreciseFastMathFlags(llvm::Instruction *inst) {
  1466. assert(isa<FPMathOperator>(inst));
  1467. inst->copyFastMathFlags(FastMathFlags());
  1468. }
  1469. // True if fast math flags are preserved across serialization/deserialization
  1470. // of the dxil module.
  1471. //
  1472. // We need to check for this when querying fast math flags for preciseness
  1473. // otherwise we will be overly conservative by reporting instructions precise
  1474. // because their fast math flags were not preserved.
  1475. //
  1476. // Currently we restrict it to the instruction types that have fast math
  1477. // preserved in the bitcode. We can expand this by converting fast math
  1478. // flags to dx.precise metadata during serialization and back to fast
  1479. // math flags during deserialization.
  1480. bool DxilModule::PreservesFastMathFlags(const llvm::Instruction *inst) {
  1481. return
  1482. isa<FPMathOperator>(inst) && (isa<BinaryOperator>(inst) || isa<FCmpInst>(inst));
  1483. }
  1484. bool DxilModule::IsPrecise(const Instruction *inst) const {
  1485. if (m_ShaderFlags.GetDisableMathRefactoring())
  1486. return true;
  1487. else if (DxilMDHelper::IsMarkedPrecise(inst))
  1488. return true;
  1489. else if (PreservesFastMathFlags(inst))
  1490. return HasPreciseFastMathFlags(inst);
  1491. else
  1492. return false;
  1493. }
  1494. } // namespace hlsl
  1495. namespace llvm {
  1496. hlsl::DxilModule &Module::GetOrCreateDxilModule(bool skipInit) {
  1497. std::unique_ptr<hlsl::DxilModule> M;
  1498. if (!HasDxilModule()) {
  1499. M = std::make_unique<hlsl::DxilModule>(this);
  1500. if (!skipInit) {
  1501. M->LoadDxilMetadata();
  1502. }
  1503. SetDxilModule(M.release());
  1504. }
  1505. return GetDxilModule();
  1506. }
  1507. void Module::ResetDxilModule() {
  1508. if (HasDxilModule()) {
  1509. delete TheDxilModule;
  1510. TheDxilModule = nullptr;
  1511. }
  1512. }
  1513. }