DxilModule.cpp 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728
  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. resLinkInfo.emplace_back(DxilModule::ResourceLinkInfo{rangeID});
  761. }
  762. void DxilModule::CreateResourceLinkInfo() {
  763. DXASSERT(GetShaderModel()->IsLib(), "only for library profile");
  764. DXASSERT(m_SRVsLinkInfo.empty() && m_UAVsLinkInfo.empty() &&
  765. m_CBuffersLinkInfo.empty() && m_SamplersLinkInfo.empty(),
  766. "else resource link info was already created");
  767. Module &M = *m_pModule;
  768. for (auto &SRV : m_SRVs) {
  769. CreateResourceLinkConstant(M, SRV.get(), m_SRVsLinkInfo);
  770. }
  771. for (auto &UAV : m_UAVs) {
  772. CreateResourceLinkConstant(M, UAV.get(), m_UAVsLinkInfo);
  773. }
  774. for (auto &CBuffer : m_CBuffers) {
  775. CreateResourceLinkConstant(M, CBuffer.get(), m_CBuffersLinkInfo);
  776. }
  777. for (auto &Sampler : m_Samplers) {
  778. CreateResourceLinkConstant(M, Sampler.get(), m_SamplersLinkInfo);
  779. }
  780. }
  781. const DxilModule::ResourceLinkInfo &
  782. DxilModule::GetResourceLinkInfo(DXIL::ResourceClass resClass,
  783. unsigned rangeID) const {
  784. switch (resClass) {
  785. case DXIL::ResourceClass::UAV:
  786. return m_UAVsLinkInfo[rangeID];
  787. case DXIL::ResourceClass::CBuffer:
  788. return m_CBuffersLinkInfo[rangeID];
  789. case DXIL::ResourceClass::Sampler:
  790. return m_SamplersLinkInfo[rangeID];
  791. default:
  792. DXASSERT(DXIL::ResourceClass::SRV == resClass,
  793. "else invalid resource class");
  794. return m_SRVsLinkInfo[rangeID];
  795. }
  796. }
  797. void DxilModule::LoadDxilResourceBaseFromMDNode(MDNode *MD, DxilResourceBase &R) {
  798. return m_pMDHelper->LoadDxilResourceBaseFromMDNode(MD, R);
  799. }
  800. void DxilModule::LoadDxilResourceFromMDNode(llvm::MDNode *MD, DxilResource &R) {
  801. return m_pMDHelper->LoadDxilResourceFromMDNode(MD, R);
  802. }
  803. void DxilModule::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  804. return m_pMDHelper->LoadDxilSamplerFromMDNode(MD, S);
  805. }
  806. template <typename TResource>
  807. static void RemoveResources(std::vector<std::unique_ptr<TResource>> &vec,
  808. std::unordered_set<unsigned> &immResID) {
  809. for (std::vector<std::unique_ptr<TResource>>::iterator p = vec.begin(); p != vec.end();) {
  810. std::vector<std::unique_ptr<TResource>>::iterator c = p++;
  811. if (immResID.count((*c)->GetID()) == 0) {
  812. p = vec.erase(c);
  813. }
  814. }
  815. }
  816. static void CollectUsedResource(Value *resID,
  817. std::unordered_set<Value *> &usedResID) {
  818. if (usedResID.count(resID) > 0)
  819. return;
  820. usedResID.insert(resID);
  821. if (ConstantInt *cResID = dyn_cast<ConstantInt>(resID)) {
  822. // Do nothing
  823. } else if (ZExtInst *ZEI = dyn_cast<ZExtInst>(resID)) {
  824. if (ZEI->getSrcTy()->isIntegerTy()) {
  825. IntegerType *ITy = cast<IntegerType>(ZEI->getSrcTy());
  826. if (ITy->getBitWidth() == 1) {
  827. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 0));
  828. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 1));
  829. }
  830. }
  831. } else if (SelectInst *SI = dyn_cast<SelectInst>(resID)) {
  832. CollectUsedResource(SI->getTrueValue(), usedResID);
  833. CollectUsedResource(SI->getFalseValue(), usedResID);
  834. } else {
  835. PHINode *Phi = cast<PHINode>(resID);
  836. for (Use &U : Phi->incoming_values()) {
  837. CollectUsedResource(U.get(), usedResID);
  838. }
  839. }
  840. }
  841. static void ConvertUsedResource(std::unordered_set<unsigned> &immResID,
  842. std::unordered_set<Value *> &usedResID) {
  843. for (Value *V : usedResID) {
  844. if (ConstantInt *cResID = dyn_cast<ConstantInt>(V)) {
  845. immResID.insert(cResID->getLimitedValue());
  846. }
  847. }
  848. }
  849. void DxilModule::RemoveFunction(llvm::Function *F) {
  850. DXASSERT_NOMSG(F != nullptr);
  851. m_DxilFunctionPropsMap.erase(F);
  852. m_DxilEntrySignatureMap.erase(F);
  853. if (m_pTypeSystem.get()->GetFunctionAnnotation(F))
  854. m_pTypeSystem.get()->EraseFunctionAnnotation(F);
  855. m_pOP->RemoveFunction(F);
  856. }
  857. void DxilModule::RemoveUnusedResources() {
  858. hlsl::OP *hlslOP = GetOP();
  859. Function *createHandleFunc = hlslOP->GetOpFunc(DXIL::OpCode::CreateHandle, Type::getVoidTy(GetCtx()));
  860. if (createHandleFunc->user_empty()) {
  861. m_CBuffers.clear();
  862. m_UAVs.clear();
  863. m_SRVs.clear();
  864. m_Samplers.clear();
  865. createHandleFunc->eraseFromParent();
  866. return;
  867. }
  868. std::unordered_set<Value *> usedUAVID;
  869. std::unordered_set<Value *> usedSRVID;
  870. std::unordered_set<Value *> usedSamplerID;
  871. std::unordered_set<Value *> usedCBufID;
  872. // Collect used ID.
  873. for (User *U : createHandleFunc->users()) {
  874. CallInst *CI = cast<CallInst>(U);
  875. Value *vResClass =
  876. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
  877. ConstantInt *cResClass = cast<ConstantInt>(vResClass);
  878. DXIL::ResourceClass resClass =
  879. static_cast<DXIL::ResourceClass>(cResClass->getLimitedValue());
  880. // Skip unused resource handle.
  881. if (CI->user_empty())
  882. continue;
  883. Value *resID =
  884. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
  885. switch (resClass) {
  886. case DXIL::ResourceClass::CBuffer:
  887. CollectUsedResource(resID, usedCBufID);
  888. break;
  889. case DXIL::ResourceClass::Sampler:
  890. CollectUsedResource(resID, usedSamplerID);
  891. break;
  892. case DXIL::ResourceClass::SRV:
  893. CollectUsedResource(resID, usedSRVID);
  894. break;
  895. case DXIL::ResourceClass::UAV:
  896. CollectUsedResource(resID, usedUAVID);
  897. break;
  898. default:
  899. DXASSERT(0, "invalid res class");
  900. break;
  901. }
  902. }
  903. std::unordered_set<unsigned> immUAVID;
  904. std::unordered_set<unsigned> immSRVID;
  905. std::unordered_set<unsigned> immSamplerID;
  906. std::unordered_set<unsigned> immCBufID;
  907. ConvertUsedResource(immUAVID, usedUAVID);
  908. RemoveResources(m_UAVs, immUAVID);
  909. ConvertUsedResource(immSRVID, usedSRVID);
  910. ConvertUsedResource(immSamplerID, usedSamplerID);
  911. ConvertUsedResource(immCBufID, usedCBufID);
  912. RemoveResources(m_SRVs, immSRVID);
  913. RemoveResources(m_Samplers, immSamplerID);
  914. RemoveResources(m_CBuffers, immCBufID);
  915. }
  916. DxilSignature &DxilModule::GetInputSignature() {
  917. return m_EntrySignature->InputSignature;
  918. }
  919. const DxilSignature &DxilModule::GetInputSignature() const {
  920. return m_EntrySignature->InputSignature;
  921. }
  922. DxilSignature &DxilModule::GetOutputSignature() {
  923. return m_EntrySignature->OutputSignature;
  924. }
  925. const DxilSignature &DxilModule::GetOutputSignature() const {
  926. return m_EntrySignature->OutputSignature;
  927. }
  928. DxilSignature &DxilModule::GetPatchConstantSignature() {
  929. return m_EntrySignature->PatchConstantSignature;
  930. }
  931. const DxilSignature &DxilModule::GetPatchConstantSignature() const {
  932. return m_EntrySignature->PatchConstantSignature;
  933. }
  934. const RootSignatureHandle &DxilModule::GetRootSignature() const {
  935. return *m_RootSignature;
  936. }
  937. bool DxilModule::HasDxilEntrySignature(llvm::Function *F) const {
  938. return m_DxilEntrySignatureMap.find(F) != m_DxilEntrySignatureMap.end();
  939. }
  940. DxilEntrySignature &DxilModule::GetDxilEntrySignature(llvm::Function *F) {
  941. DXASSERT(m_DxilEntrySignatureMap.count(F) != 0, "cannot find F in map");
  942. return *m_DxilEntrySignatureMap[F];
  943. }
  944. void DxilModule::ReplaceDxilEntrySignature(llvm::Function *F,
  945. llvm::Function *NewF) {
  946. DXASSERT(m_DxilEntrySignatureMap.count(F) != 0, "cannot find F in map");
  947. std::unique_ptr<DxilEntrySignature> Sig =
  948. std::move(m_DxilEntrySignatureMap[F]);
  949. m_DxilEntrySignatureMap.erase(F);
  950. m_DxilEntrySignatureMap[NewF] = std::move(Sig);
  951. }
  952. bool DxilModule::HasDxilFunctionProps(llvm::Function *F) const {
  953. return m_DxilFunctionPropsMap.find(F) != m_DxilFunctionPropsMap.end();
  954. }
  955. DxilFunctionProps &DxilModule::GetDxilFunctionProps(llvm::Function *F) {
  956. DXASSERT(m_DxilFunctionPropsMap.count(F) != 0, "cannot find F in map");
  957. return *m_DxilFunctionPropsMap[F];
  958. }
  959. void DxilModule::ReplaceDxilFunctionProps(llvm::Function *F,
  960. llvm::Function *NewF) {
  961. DXASSERT(m_DxilFunctionPropsMap.count(F) != 0, "cannot find F in map");
  962. std::unique_ptr<DxilFunctionProps> props =
  963. std::move(m_DxilFunctionPropsMap[F]);
  964. m_DxilFunctionPropsMap.erase(F);
  965. m_DxilFunctionPropsMap[NewF] = std::move(props);
  966. }
  967. void DxilModule::StripRootSignatureFromMetadata() {
  968. NamedMDNode *pRootSignatureNamedMD = GetModule()->getNamedMetadata(DxilMDHelper::kDxilRootSignatureMDName);
  969. if (pRootSignatureNamedMD) {
  970. GetModule()->eraseNamedMetadata(pRootSignatureNamedMD);
  971. }
  972. }
  973. void DxilModule::UpdateValidatorVersionMetadata() {
  974. m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
  975. }
  976. void DxilModule::ResetEntrySignature(DxilEntrySignature *pValue) {
  977. m_EntrySignature.reset(pValue);
  978. }
  979. void DxilModule::ResetRootSignature(RootSignatureHandle *pValue) {
  980. m_RootSignature.reset(pValue);
  981. }
  982. DxilTypeSystem &DxilModule::GetTypeSystem() {
  983. return *m_pTypeSystem;
  984. }
  985. DxilViewIdState &DxilModule::GetViewIdState() {
  986. return *m_pViewIdState;
  987. }
  988. const DxilViewIdState &DxilModule::GetViewIdState() const {
  989. return *m_pViewIdState;
  990. }
  991. void DxilModule::ResetTypeSystem(DxilTypeSystem *pValue) {
  992. m_pTypeSystem.reset(pValue);
  993. }
  994. void DxilModule::ResetOP(hlsl::OP *hlslOP) { m_pOP.reset(hlslOP); }
  995. void DxilModule::ResetFunctionPropsMap(
  996. std::unordered_map<llvm::Function *, std::unique_ptr<DxilFunctionProps>>
  997. &&propsMap) {
  998. m_DxilFunctionPropsMap = std::move(propsMap);
  999. }
  1000. void DxilModule::ResetEntrySignatureMap(
  1001. std::unordered_map<llvm::Function *, std::unique_ptr<DxilEntrySignature>>
  1002. &&SigMap) {
  1003. m_DxilEntrySignatureMap = std::move(SigMap);
  1004. }
  1005. void DxilModule::EmitLLVMUsed() {
  1006. if (m_LLVMUsed.empty())
  1007. return;
  1008. vector<llvm::Constant*> GVs;
  1009. Type *pI8PtrType = Type::getInt8PtrTy(m_Ctx, DXIL::kDefaultAddrSpace);
  1010. GVs.resize(m_LLVMUsed.size());
  1011. for (size_t i = 0, e = m_LLVMUsed.size(); i != e; i++) {
  1012. Constant *pConst = cast<Constant>(&*m_LLVMUsed[i]);
  1013. PointerType * pPtrType = dyn_cast<PointerType>(pConst->getType());
  1014. if (pPtrType->getPointerAddressSpace() != DXIL::kDefaultAddrSpace) {
  1015. // Cast pointer to addrspace 0, as LLVMUsed elements must have the same type.
  1016. GVs[i] = ConstantExpr::getAddrSpaceCast(pConst, pI8PtrType);
  1017. } else {
  1018. GVs[i] = ConstantExpr::getPointerCast(pConst, pI8PtrType);
  1019. }
  1020. }
  1021. ArrayType *pATy = ArrayType::get(pI8PtrType, GVs.size());
  1022. StringRef llvmUsedName = "llvm.used";
  1023. if (GlobalVariable *oldGV = m_pModule->getGlobalVariable(llvmUsedName)) {
  1024. oldGV->eraseFromParent();
  1025. }
  1026. GlobalVariable *pGV = new GlobalVariable(*m_pModule, pATy, false,
  1027. GlobalValue::AppendingLinkage,
  1028. ConstantArray::get(pATy, GVs),
  1029. llvmUsedName);
  1030. pGV->setSection("llvm.metadata");
  1031. }
  1032. vector<GlobalVariable* > &DxilModule::GetLLVMUsed() {
  1033. return m_LLVMUsed;
  1034. }
  1035. // DXIL metadata serialization/deserialization.
  1036. void DxilModule::EmitDxilMetadata() {
  1037. m_pMDHelper->EmitDxilVersion(m_DxilMajor, m_DxilMinor);
  1038. m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
  1039. m_pMDHelper->EmitDxilShaderModel(m_pSM);
  1040. MDTuple *pMDProperties = EmitDxilShaderProperties();
  1041. MDTuple *pMDSignatures = m_pMDHelper->EmitDxilSignatures(*m_EntrySignature);
  1042. MDTuple *pMDResources = EmitDxilResources();
  1043. m_pMDHelper->EmitDxilTypeSystem(GetTypeSystem(), m_LLVMUsed);
  1044. if (!m_pSM->IsCS() &&
  1045. (m_ValMajor > 1 || (m_ValMajor == 1 && m_ValMinor >= 1))) {
  1046. m_pMDHelper->EmitDxilViewIdState(GetViewIdState());
  1047. }
  1048. EmitLLVMUsed();
  1049. MDTuple *pEntry = m_pMDHelper->EmitDxilEntryPointTuple(GetEntryFunction(), m_EntryName, pMDSignatures, pMDResources, pMDProperties);
  1050. vector<MDNode *> Entries;
  1051. Entries.emplace_back(pEntry);
  1052. m_pMDHelper->EmitDxilEntryPoints(Entries);
  1053. if (!m_RootSignature->IsEmpty()) {
  1054. m_pMDHelper->EmitRootSignature(*m_RootSignature.get());
  1055. }
  1056. if (m_pSM->IsLib()) {
  1057. EmitDxilResourcesLinkInfo();
  1058. NamedMDNode *fnProps = m_pModule->getOrInsertNamedMetadata(
  1059. DxilMDHelper::kDxilFunctionPropertiesMDName);
  1060. for (auto &&pair : m_DxilFunctionPropsMap) {
  1061. const hlsl::DxilFunctionProps *props = pair.second.get();
  1062. MDTuple *pProps = m_pMDHelper->EmitDxilFunctionProps(props, pair.first);
  1063. fnProps->addOperand(pProps);
  1064. }
  1065. NamedMDNode *entrySigs = m_pModule->getOrInsertNamedMetadata(
  1066. DxilMDHelper::kDxilEntrySignaturesMDName);
  1067. for (auto &&pair : m_DxilEntrySignatureMap) {
  1068. Function *F = pair.first;
  1069. DxilEntrySignature *Sig = pair.second.get();
  1070. MDTuple *pSig = m_pMDHelper->EmitDxilSignatures(*Sig);
  1071. entrySigs->addOperand(
  1072. MDTuple::get(m_Ctx, {ValueAsMetadata::get(F), pSig}));
  1073. }
  1074. }
  1075. }
  1076. bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
  1077. return DxilMDHelper::IsKnownNamedMetaData(Node);
  1078. }
  1079. void DxilModule::LoadDxilMetadata() {
  1080. m_pMDHelper->LoadDxilVersion(m_DxilMajor, m_DxilMinor);
  1081. m_pMDHelper->LoadValidatorVersion(m_ValMajor, m_ValMinor);
  1082. const ShaderModel *loadedModule;
  1083. m_pMDHelper->LoadDxilShaderModel(loadedModule);
  1084. SetShaderModel(loadedModule);
  1085. DXASSERT(m_EntrySignature != nullptr, "else SetShaderModel didn't create entry signature");
  1086. const llvm::NamedMDNode *pEntries = m_pMDHelper->GetDxilEntryPoints();
  1087. IFTBOOL(pEntries->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  1088. Function *pEntryFunc;
  1089. string EntryName;
  1090. const llvm::MDOperand *pSignatures, *pResources, *pProperties;
  1091. m_pMDHelper->GetDxilEntryPoint(pEntries->getOperand(0), pEntryFunc, EntryName, pSignatures, pResources, pProperties);
  1092. SetEntryFunction(pEntryFunc);
  1093. SetEntryFunctionName(EntryName);
  1094. LoadDxilShaderProperties(*pProperties);
  1095. m_pMDHelper->LoadDxilSignatures(*pSignatures, *m_EntrySignature);
  1096. LoadDxilResources(*pResources);
  1097. m_pMDHelper->LoadDxilTypeSystem(*m_pTypeSystem.get());
  1098. m_pMDHelper->LoadRootSignature(*m_RootSignature.get());
  1099. m_pMDHelper->LoadDxilViewIdState(*m_pViewIdState.get());
  1100. if (loadedModule->IsLib()) {
  1101. LoadDxilResourcesLinkInfo();
  1102. NamedMDNode *fnProps = m_pModule->getNamedMetadata(
  1103. DxilMDHelper::kDxilFunctionPropertiesMDName);
  1104. size_t propIdx = 0;
  1105. while (propIdx < fnProps->getNumOperands()) {
  1106. MDTuple *pProps = dyn_cast<MDTuple>(fnProps->getOperand(propIdx++));
  1107. std::unique_ptr<hlsl::DxilFunctionProps> props =
  1108. llvm::make_unique<hlsl::DxilFunctionProps>();
  1109. Function *F = m_pMDHelper->LoadDxilFunctionProps(pProps, props.get());
  1110. m_DxilFunctionPropsMap[F] = std::move(props);
  1111. }
  1112. NamedMDNode *entrySigs = m_pModule->getOrInsertNamedMetadata(
  1113. DxilMDHelper::kDxilEntrySignaturesMDName);
  1114. size_t sigIdx = 0;
  1115. while (sigIdx < entrySigs->getNumOperands()) {
  1116. MDTuple *pSig = dyn_cast<MDTuple>(entrySigs->getOperand(sigIdx++));
  1117. unsigned idx = 0;
  1118. Function *F = dyn_cast<Function>(
  1119. dyn_cast<ValueAsMetadata>(pSig->getOperand(idx++))->getValue());
  1120. // Entry must have props.
  1121. IFTBOOL(m_DxilFunctionPropsMap.count(F), DXC_E_INCORRECT_DXIL_METADATA);
  1122. DXIL::ShaderKind shaderKind = m_DxilFunctionPropsMap[F]->shaderKind;
  1123. std::unique_ptr<hlsl::DxilEntrySignature> Sig =
  1124. llvm::make_unique<hlsl::DxilEntrySignature>(shaderKind);
  1125. m_pMDHelper->LoadDxilSignatures(pSig->getOperand(idx), *Sig);
  1126. m_DxilEntrySignatureMap[F] = std::move(Sig);
  1127. }
  1128. }
  1129. }
  1130. MDTuple *DxilModule::EmitDxilResources() {
  1131. // Emit SRV records.
  1132. MDTuple *pTupleSRVs = nullptr;
  1133. if (!m_SRVs.empty()) {
  1134. vector<Metadata *> MDVals;
  1135. for (size_t i = 0; i < m_SRVs.size(); i++) {
  1136. MDVals.emplace_back(m_pMDHelper->EmitDxilSRV(*m_SRVs[i]));
  1137. }
  1138. pTupleSRVs = MDNode::get(m_Ctx, MDVals);
  1139. }
  1140. // Emit UAV records.
  1141. MDTuple *pTupleUAVs = nullptr;
  1142. if (!m_UAVs.empty()) {
  1143. vector<Metadata *> MDVals;
  1144. for (size_t i = 0; i < m_UAVs.size(); i++) {
  1145. MDVals.emplace_back(m_pMDHelper->EmitDxilUAV(*m_UAVs[i]));
  1146. }
  1147. pTupleUAVs = MDNode::get(m_Ctx, MDVals);
  1148. }
  1149. // Emit CBuffer records.
  1150. MDTuple *pTupleCBuffers = nullptr;
  1151. if (!m_CBuffers.empty()) {
  1152. vector<Metadata *> MDVals;
  1153. for (size_t i = 0; i < m_CBuffers.size(); i++) {
  1154. MDVals.emplace_back(m_pMDHelper->EmitDxilCBuffer(*m_CBuffers[i]));
  1155. }
  1156. pTupleCBuffers = MDNode::get(m_Ctx, MDVals);
  1157. }
  1158. // Emit Sampler records.
  1159. MDTuple *pTupleSamplers = nullptr;
  1160. if (!m_Samplers.empty()) {
  1161. vector<Metadata *> MDVals;
  1162. for (size_t i = 0; i < m_Samplers.size(); i++) {
  1163. MDVals.emplace_back(m_pMDHelper->EmitDxilSampler(*m_Samplers[i]));
  1164. }
  1165. pTupleSamplers = MDNode::get(m_Ctx, MDVals);
  1166. }
  1167. if (pTupleSRVs != nullptr || pTupleUAVs != nullptr || pTupleCBuffers != nullptr || pTupleSamplers != nullptr) {
  1168. return m_pMDHelper->EmitDxilResourceTuple(pTupleSRVs, pTupleUAVs, pTupleCBuffers, pTupleSamplers);
  1169. } else {
  1170. return nullptr;
  1171. }
  1172. }
  1173. void DxilModule::LoadDxilResources(const llvm::MDOperand &MDO) {
  1174. if (MDO.get() == nullptr)
  1175. return;
  1176. const llvm::MDTuple *pSRVs, *pUAVs, *pCBuffers, *pSamplers;
  1177. m_pMDHelper->GetDxilResources(MDO, pSRVs, pUAVs, pCBuffers, pSamplers);
  1178. // Load SRV records.
  1179. if (pSRVs != nullptr) {
  1180. for (unsigned i = 0; i < pSRVs->getNumOperands(); i++) {
  1181. unique_ptr<DxilResource> pSRV(new DxilResource);
  1182. m_pMDHelper->LoadDxilSRV(pSRVs->getOperand(i), *pSRV);
  1183. AddSRV(std::move(pSRV));
  1184. }
  1185. }
  1186. // Load UAV records.
  1187. if (pUAVs != nullptr) {
  1188. for (unsigned i = 0; i < pUAVs->getNumOperands(); i++) {
  1189. unique_ptr<DxilResource> pUAV(new DxilResource);
  1190. m_pMDHelper->LoadDxilUAV(pUAVs->getOperand(i), *pUAV);
  1191. AddUAV(std::move(pUAV));
  1192. }
  1193. }
  1194. // Load CBuffer records.
  1195. if (pCBuffers != nullptr) {
  1196. for (unsigned i = 0; i < pCBuffers->getNumOperands(); i++) {
  1197. unique_ptr<DxilCBuffer> pCB(new DxilCBuffer);
  1198. m_pMDHelper->LoadDxilCBuffer(pCBuffers->getOperand(i), *pCB);
  1199. AddCBuffer(std::move(pCB));
  1200. }
  1201. }
  1202. // Load Sampler records.
  1203. if (pSamplers != nullptr) {
  1204. for (unsigned i = 0; i < pSamplers->getNumOperands(); i++) {
  1205. unique_ptr<DxilSampler> pSampler(new DxilSampler);
  1206. m_pMDHelper->LoadDxilSampler(pSamplers->getOperand(i), *pSampler);
  1207. AddSampler(std::move(pSampler));
  1208. }
  1209. }
  1210. }
  1211. static MDTuple *CreateResourcesLinkInfo(std::vector<DxilModule::ResourceLinkInfo> &LinkInfoList,
  1212. unsigned size, LLVMContext &Ctx) {
  1213. DXASSERT(size == LinkInfoList.size(), "link info size must match resource size");
  1214. if (LinkInfoList.empty())
  1215. return nullptr;
  1216. vector<Metadata *> MDVals;
  1217. for (size_t i = 0; i < size; i++) {
  1218. MDVals.emplace_back(ValueAsMetadata::get(LinkInfoList[i].ResRangeID));
  1219. }
  1220. return MDNode::get(Ctx, MDVals);
  1221. }
  1222. void DxilModule::EmitDxilResourcesLinkInfo() {
  1223. // Emit SRV base records.
  1224. MDTuple *pTupleSRVs =
  1225. CreateResourcesLinkInfo(m_SRVsLinkInfo, m_SRVs.size(), m_Ctx);
  1226. // Emit UAV base records.
  1227. MDTuple *pTupleUAVs =
  1228. CreateResourcesLinkInfo(m_UAVsLinkInfo, m_UAVs.size(), m_Ctx);
  1229. // Emit CBuffer base records.
  1230. MDTuple *pTupleCBuffers =
  1231. CreateResourcesLinkInfo(m_CBuffersLinkInfo, m_CBuffers.size(), m_Ctx);
  1232. // Emit Sampler records.
  1233. MDTuple *pTupleSamplers =
  1234. CreateResourcesLinkInfo(m_SamplersLinkInfo, m_Samplers.size(), m_Ctx);
  1235. if (pTupleSRVs != nullptr || pTupleUAVs != nullptr ||
  1236. pTupleCBuffers != nullptr || pTupleSamplers != nullptr) {
  1237. m_pMDHelper->EmitDxilResourceLinkInfoTuple(pTupleSRVs, pTupleUAVs,
  1238. pTupleCBuffers, pTupleSamplers);
  1239. }
  1240. }
  1241. static void
  1242. LoadResourcesLinkInfo(const llvm::MDTuple *pMD,
  1243. std::vector<DxilModule::ResourceLinkInfo> &LinkInfoList,
  1244. unsigned size, DxilMDHelper *pMDHelper) {
  1245. if (!pMD) {
  1246. IFTBOOL(size == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1247. return;
  1248. }
  1249. unsigned operandSize = pMD->getNumOperands();
  1250. IFTBOOL(operandSize == size, DXC_E_INCORRECT_DXIL_METADATA);
  1251. for (unsigned i = 0; i < operandSize; i++) {
  1252. Constant *rangeID =
  1253. dyn_cast<Constant>(pMDHelper->ValueMDToValue(pMD->getOperand(i)));
  1254. LinkInfoList.emplace_back(DxilModule::ResourceLinkInfo{rangeID});
  1255. }
  1256. }
  1257. void DxilModule::LoadDxilResourcesLinkInfo() {
  1258. const llvm::MDTuple *pSRVs, *pUAVs, *pCBuffers, *pSamplers;
  1259. m_pMDHelper->LoadDxilResourceLinkInfoTuple(pSRVs, pUAVs, pCBuffers,
  1260. pSamplers);
  1261. // Load SRV base records.
  1262. LoadResourcesLinkInfo(pSRVs, m_SRVsLinkInfo, m_SRVs.size(),
  1263. m_pMDHelper.get());
  1264. // Load UAV base records.
  1265. LoadResourcesLinkInfo(pUAVs, m_UAVsLinkInfo, m_UAVs.size(),
  1266. m_pMDHelper.get());
  1267. // Load CBuffer records.
  1268. LoadResourcesLinkInfo(pCBuffers, m_CBuffersLinkInfo, m_CBuffers.size(),
  1269. m_pMDHelper.get());
  1270. // Load Sampler records.
  1271. LoadResourcesLinkInfo(pSamplers, m_SamplersLinkInfo, m_Samplers.size(),
  1272. m_pMDHelper.get());
  1273. }
  1274. MDTuple *DxilModule::EmitDxilShaderProperties() {
  1275. vector<Metadata *> MDVals;
  1276. // DXIL shader flags.
  1277. uint64_t Flags = m_ShaderFlags.GetShaderFlagsRaw();
  1278. if (Flags != 0) {
  1279. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilShaderFlagsTag));
  1280. MDVals.emplace_back(m_pMDHelper->Uint64ToConstMD(Flags));
  1281. }
  1282. // Compute shader.
  1283. if (m_pSM->IsCS()) {
  1284. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  1285. vector<Metadata *> NumThreadVals;
  1286. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[0]));
  1287. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[1]));
  1288. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[2]));
  1289. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  1290. }
  1291. // Geometry shader.
  1292. if (m_pSM->IsGS()) {
  1293. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  1294. MDTuple *pMDTuple = m_pMDHelper->EmitDxilGSState(m_InputPrimitive,
  1295. m_MaxVertexCount,
  1296. GetActiveStreamMask(),
  1297. m_StreamPrimitiveTopology,
  1298. m_NumGSInstances);
  1299. MDVals.emplace_back(pMDTuple);
  1300. }
  1301. // Domain shader.
  1302. if (m_pSM->IsDS()) {
  1303. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  1304. MDTuple *pMDTuple = m_pMDHelper->EmitDxilDSState(m_TessellatorDomain,
  1305. m_InputControlPointCount);
  1306. MDVals.emplace_back(pMDTuple);
  1307. }
  1308. // Hull shader.
  1309. if (m_pSM->IsHS()) {
  1310. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  1311. MDTuple *pMDTuple = m_pMDHelper->EmitDxilHSState(m_pPatchConstantFunc,
  1312. m_InputControlPointCount,
  1313. m_OutputControlPointCount,
  1314. m_TessellatorDomain,
  1315. m_TessellatorPartitioning,
  1316. m_TessellatorOutputPrimitive,
  1317. m_MaxTessellationFactor);
  1318. MDVals.emplace_back(pMDTuple);
  1319. }
  1320. if (!MDVals.empty())
  1321. return MDNode::get(m_Ctx, MDVals);
  1322. else
  1323. return nullptr;
  1324. }
  1325. void DxilModule::LoadDxilShaderProperties(const MDOperand &MDO) {
  1326. if (MDO.get() == nullptr)
  1327. return;
  1328. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1329. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1330. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1331. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  1332. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  1333. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  1334. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1335. switch (Tag) {
  1336. case DxilMDHelper::kDxilShaderFlagsTag:
  1337. m_ShaderFlags.SetShaderFlagsRaw(DxilMDHelper::ConstMDToUint64(MDO));
  1338. break;
  1339. case DxilMDHelper::kDxilNumThreadsTag: {
  1340. MDNode *pNode = cast<MDNode>(MDO.get());
  1341. m_NumThreads[0] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(0));
  1342. m_NumThreads[1] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(1));
  1343. m_NumThreads[2] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(2));
  1344. break;
  1345. }
  1346. case DxilMDHelper::kDxilGSStateTag: {
  1347. m_pMDHelper->LoadDxilGSState(MDO, m_InputPrimitive, m_MaxVertexCount, m_ActiveStreamMask,
  1348. m_StreamPrimitiveTopology, m_NumGSInstances);
  1349. break;
  1350. }
  1351. case DxilMDHelper::kDxilDSStateTag:
  1352. m_pMDHelper->LoadDxilDSState(MDO, m_TessellatorDomain, m_InputControlPointCount);
  1353. break;
  1354. case DxilMDHelper::kDxilHSStateTag:
  1355. m_pMDHelper->LoadDxilHSState(MDO,
  1356. m_pPatchConstantFunc,
  1357. m_InputControlPointCount,
  1358. m_OutputControlPointCount,
  1359. m_TessellatorDomain,
  1360. m_TessellatorPartitioning,
  1361. m_TessellatorOutputPrimitive,
  1362. m_MaxTessellationFactor);
  1363. break;
  1364. default:
  1365. DXASSERT(false, "Unknown extended shader properties tag");
  1366. break;
  1367. }
  1368. }
  1369. }
  1370. void DxilModule::StripDebugRelatedCode() {
  1371. // Remove all users of global resources.
  1372. for (GlobalVariable &GV : m_pModule->globals()) {
  1373. if (GV.hasInternalLinkage())
  1374. continue;
  1375. if (GV.getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace)
  1376. continue;
  1377. for (auto git = GV.user_begin(); git != GV.user_end();) {
  1378. User *U = *(git++);
  1379. // Try to remove load of GV.
  1380. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  1381. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1382. Instruction *LIUser = cast<Instruction>(*(it++));
  1383. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1384. Value *Ptr = SI->getPointerOperand();
  1385. SI->eraseFromParent();
  1386. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1387. if (Ptr->user_empty())
  1388. PtrInst->eraseFromParent();
  1389. }
  1390. }
  1391. }
  1392. if (LI->user_empty())
  1393. LI->eraseFromParent();
  1394. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
  1395. for (auto GEPIt = GEP->user_begin(); GEPIt != GEP->user_end();) {
  1396. User *GEPU = *(GEPIt++);
  1397. // Try to remove load of GEP.
  1398. if (LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
  1399. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1400. Instruction *LIUser = cast<Instruction>(*(it++));
  1401. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1402. Value *Ptr = SI->getPointerOperand();
  1403. SI->eraseFromParent();
  1404. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1405. if (Ptr->user_empty())
  1406. PtrInst->eraseFromParent();
  1407. }
  1408. }
  1409. if (LI->user_empty())
  1410. LI->eraseFromParent();
  1411. }
  1412. }
  1413. }
  1414. if (GEP->user_empty())
  1415. GEP->eraseFromParent();
  1416. }
  1417. }
  1418. }
  1419. }
  1420. DebugInfoFinder &DxilModule::GetOrCreateDebugInfoFinder() {
  1421. if (m_pDebugInfoFinder == nullptr) {
  1422. m_pDebugInfoFinder = std::make_unique<llvm::DebugInfoFinder>();
  1423. m_pDebugInfoFinder->processModule(*m_pModule);
  1424. }
  1425. return *m_pDebugInfoFinder;
  1426. }
  1427. hlsl::DxilModule *hlsl::DxilModule::TryGetDxilModule(llvm::Module *pModule) {
  1428. LLVMContext &Ctx = pModule->getContext();
  1429. std::string diagStr;
  1430. raw_string_ostream diagStream(diagStr);
  1431. hlsl::DxilModule *pDxilModule = nullptr;
  1432. // TODO: add detail error in DxilMDHelper.
  1433. try {
  1434. pDxilModule = &pModule->GetOrCreateDxilModule();
  1435. } catch (const ::hlsl::Exception &hlslException) {
  1436. diagStream << "load dxil metadata failed -";
  1437. try {
  1438. const char *msg = hlslException.what();
  1439. if (msg == nullptr || *msg == '\0')
  1440. diagStream << " error code " << hlslException.hr << "\n";
  1441. else
  1442. diagStream << msg;
  1443. } catch (...) {
  1444. diagStream << " unable to retrieve error message.\n";
  1445. }
  1446. Ctx.diagnose(DxilErrorDiagnosticInfo(diagStream.str().c_str()));
  1447. } catch (...) {
  1448. Ctx.diagnose(DxilErrorDiagnosticInfo("load dxil metadata failed - unknown error.\n"));
  1449. }
  1450. return pDxilModule;
  1451. }
  1452. // Check if the instruction has fast math flags configured to indicate
  1453. // the instruction is precise.
  1454. // Precise fast math flags means none of the fast math flags are set.
  1455. bool DxilModule::HasPreciseFastMathFlags(const Instruction *inst) {
  1456. return isa<FPMathOperator>(inst) && !inst->getFastMathFlags().any();
  1457. }
  1458. // Set fast math flags configured to indicate the instruction is precise.
  1459. void DxilModule::SetPreciseFastMathFlags(llvm::Instruction *inst) {
  1460. assert(isa<FPMathOperator>(inst));
  1461. inst->copyFastMathFlags(FastMathFlags());
  1462. }
  1463. // True if fast math flags are preserved across serialization/deserialization
  1464. // of the dxil module.
  1465. //
  1466. // We need to check for this when querying fast math flags for preciseness
  1467. // otherwise we will be overly conservative by reporting instructions precise
  1468. // because their fast math flags were not preserved.
  1469. //
  1470. // Currently we restrict it to the instruction types that have fast math
  1471. // preserved in the bitcode. We can expand this by converting fast math
  1472. // flags to dx.precise metadata during serialization and back to fast
  1473. // math flags during deserialization.
  1474. bool DxilModule::PreservesFastMathFlags(const llvm::Instruction *inst) {
  1475. return
  1476. isa<FPMathOperator>(inst) && (isa<BinaryOperator>(inst) || isa<FCmpInst>(inst));
  1477. }
  1478. bool DxilModule::IsPrecise(const Instruction *inst) const {
  1479. if (m_ShaderFlags.GetDisableMathRefactoring())
  1480. return true;
  1481. else if (DxilMDHelper::IsMarkedPrecise(inst))
  1482. return true;
  1483. else if (PreservesFastMathFlags(inst))
  1484. return HasPreciseFastMathFlags(inst);
  1485. else
  1486. return false;
  1487. }
  1488. } // namespace hlsl
  1489. namespace llvm {
  1490. hlsl::DxilModule &Module::GetOrCreateDxilModule(bool skipInit) {
  1491. std::unique_ptr<hlsl::DxilModule> M;
  1492. if (!HasDxilModule()) {
  1493. M = std::make_unique<hlsl::DxilModule>(this);
  1494. if (!skipInit) {
  1495. M->LoadDxilMetadata();
  1496. }
  1497. SetDxilModule(M.release());
  1498. }
  1499. return GetDxilModule();
  1500. }
  1501. void Module::ResetDxilModule() {
  1502. if (HasDxilModule()) {
  1503. delete TheDxilModule;
  1504. TheDxilModule = nullptr;
  1505. }
  1506. }
  1507. }