2
0

DxilModule.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547
  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. void print(DiagnosticPrinter &DP) const override {
  42. DP << m_message;
  43. }
  44. };
  45. } // anon namespace
  46. namespace hlsl {
  47. namespace DXIL {
  48. // Define constant variables exposed in DxilConstants.h
  49. // TODO: revisit data layout descriptions for the following:
  50. // - x64 pointers?
  51. // - Keep elf manging(m:e)?
  52. // For legacy data layout, everything less than 32 align to 32.
  53. const char* kLegacyLayoutString = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f:64:64-n8:16:32:64";
  54. // New data layout with native low precision types
  55. const char* kNewLayoutString = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64";
  56. // Function Attributes
  57. // TODO: consider generating attributes from hctdb
  58. const char* kFP32DenormKindString = "fp32-denorm-mode";
  59. const char* kFP32DenormValueAnyString = "any";
  60. const char* kFP32DenormValuePreserveString = "preserve";
  61. const char* kFP32DenormValueFtzString = "ftz";
  62. }
  63. //------------------------------------------------------------------------------
  64. //
  65. // DxilModule methods.
  66. //
  67. DxilModule::DxilModule(Module *pModule)
  68. : m_Ctx(pModule->getContext())
  69. , m_pModule(pModule)
  70. , m_pOP(llvm::make_unique<OP>(pModule->getContext(), pModule))
  71. , m_pTypeSystem(llvm::make_unique<DxilTypeSystem>(pModule))
  72. , m_pViewIdState(llvm::make_unique<DxilViewIdState>(this))
  73. , m_pMDHelper(llvm::make_unique<DxilMDHelper>(pModule, llvm::make_unique<DxilExtraPropertyHelper>(pModule)))
  74. , m_pDebugInfoFinder(nullptr)
  75. , m_pEntryFunc(nullptr)
  76. , m_EntryName("")
  77. , m_pPatchConstantFunc(nullptr)
  78. , m_pSM(nullptr)
  79. , m_DxilMajor(DXIL::kDxilMajor)
  80. , m_DxilMinor(DXIL::kDxilMinor)
  81. , m_ValMajor(1)
  82. , m_ValMinor(0)
  83. , m_InputPrimitive(DXIL::InputPrimitive::Undefined)
  84. , m_MaxVertexCount(0)
  85. , m_StreamPrimitiveTopology(DXIL::PrimitiveTopology::Undefined)
  86. , m_ActiveStreamMask(0)
  87. , m_NumGSInstances(1)
  88. , m_InputControlPointCount(0)
  89. , m_TessellatorDomain(DXIL::TessellatorDomain::Undefined)
  90. , m_OutputControlPointCount(0)
  91. , m_TessellatorPartitioning(DXIL::TessellatorPartitioning::Undefined)
  92. , m_TessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive::Undefined)
  93. , m_MaxTessellationFactor(0.f)
  94. , m_RootSignature(nullptr)
  95. , m_bUseMinPrecision(true) // use min precision by default
  96. , m_bDisableOptimizations(false)
  97. , m_bAllResourcesBound(false)
  98. , m_AutoBindingSpace(UINT_MAX) {
  99. DXASSERT_NOMSG(m_pModule != nullptr);
  100. m_NumThreads[0] = m_NumThreads[1] = m_NumThreads[2] = 0;
  101. #if defined(_DEBUG) || defined(DBG)
  102. // Pin LLVM dump methods.
  103. void (__thiscall Module::*pfnModuleDump)() const = &Module::dump;
  104. void (__thiscall Type::*pfnTypeDump)() const = &Type::dump;
  105. void (__thiscall Function::*pfnViewCFGOnly)() const = &Function::viewCFGOnly;
  106. m_pUnused = (char *)&pfnModuleDump - (char *)&pfnTypeDump;
  107. m_pUnused -= (size_t)&pfnViewCFGOnly;
  108. #endif
  109. }
  110. DxilModule::~DxilModule() {
  111. }
  112. LLVMContext &DxilModule::GetCtx() const { return m_Ctx; }
  113. Module *DxilModule::GetModule() const { return m_pModule; }
  114. OP *DxilModule::GetOP() const { return m_pOP.get(); }
  115. void DxilModule::SetShaderModel(const ShaderModel *pSM) {
  116. DXASSERT(m_pSM == nullptr || (pSM != nullptr && *m_pSM == *pSM), "shader model must not change for the module");
  117. DXASSERT(pSM != nullptr && pSM->IsValidForDxil(), "shader model must be valid");
  118. DXASSERT(pSM->IsValidForModule(), "shader model must be valid for top-level module use");
  119. m_pSM = pSM;
  120. m_pSM->GetDxilVersion(m_DxilMajor, m_DxilMinor);
  121. m_pMDHelper->SetShaderModel(m_pSM);
  122. DXIL::ShaderKind shaderKind = pSM->GetKind();
  123. m_EntrySignature = llvm::make_unique<DxilEntrySignature>(shaderKind, GetUseMinPrecision());
  124. m_RootSignature.reset(new RootSignatureHandle());
  125. }
  126. const ShaderModel *DxilModule::GetShaderModel() const {
  127. return m_pSM;
  128. }
  129. void DxilModule::GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const {
  130. DxilMajor = m_DxilMajor;
  131. DxilMinor = m_DxilMinor;
  132. }
  133. void DxilModule::SetValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
  134. m_ValMajor = ValMajor;
  135. m_ValMinor = ValMinor;
  136. }
  137. bool DxilModule::UpgradeValidatorVersion(unsigned ValMajor, unsigned ValMinor) {
  138. // Don't upgrade if validation was disabled.
  139. if (m_ValMajor == 0 && m_ValMinor == 0) {
  140. return false;
  141. }
  142. if (ValMajor > m_ValMajor || (ValMajor == m_ValMajor && ValMinor > m_ValMinor)) {
  143. // Module requires higher validator version than previously set
  144. SetValidatorVersion(ValMajor, ValMinor);
  145. return true;
  146. }
  147. return false;
  148. }
  149. void DxilModule::GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
  150. ValMajor = m_ValMajor;
  151. ValMinor = m_ValMinor;
  152. }
  153. bool DxilModule::GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const {
  154. if (!m_pSM)
  155. return false;
  156. m_pSM->GetMinValidatorVersion(ValMajor, ValMinor);
  157. if (ValMajor == 1 && ValMinor == 0 && (m_ShaderFlags.GetFeatureInfo() & hlsl::ShaderFeatureInfo_ViewID))
  158. ValMinor = 1;
  159. return true;
  160. }
  161. bool DxilModule::UpgradeToMinValidatorVersion() {
  162. unsigned ValMajor = 1, ValMinor = 0;
  163. if (GetMinValidatorVersion(ValMajor, ValMinor)) {
  164. return UpgradeValidatorVersion(ValMajor, ValMinor);
  165. }
  166. return false;
  167. }
  168. Function *DxilModule::GetEntryFunction() {
  169. return m_pEntryFunc;
  170. }
  171. const Function *DxilModule::GetEntryFunction() const {
  172. return m_pEntryFunc;
  173. }
  174. void DxilModule::SetEntryFunction(Function *pEntryFunc) {
  175. m_pEntryFunc = pEntryFunc;
  176. }
  177. const string &DxilModule::GetEntryFunctionName() const {
  178. return m_EntryName;
  179. }
  180. void DxilModule::SetEntryFunctionName(const string &name) {
  181. m_EntryName = name;
  182. }
  183. llvm::Function *DxilModule::GetPatchConstantFunction() {
  184. return m_pPatchConstantFunc;
  185. }
  186. const llvm::Function *DxilModule::GetPatchConstantFunction() const {
  187. return m_pPatchConstantFunc;
  188. }
  189. void DxilModule::SetPatchConstantFunction(llvm::Function *pFunc) {
  190. m_pPatchConstantFunc = pFunc;
  191. }
  192. unsigned DxilModule::GetGlobalFlags() const {
  193. unsigned Flags = m_ShaderFlags.GetGlobalFlags();
  194. return Flags;
  195. }
  196. void DxilModule::CollectShaderFlagsForModule(ShaderFlags &Flags) {
  197. for (Function &F : GetModule()->functions()) {
  198. ShaderFlags funcFlags = ShaderFlags::CollectShaderFlags(&F, this);
  199. Flags.CombineShaderFlags(funcFlags);
  200. };
  201. const ShaderModel *SM = GetShaderModel();
  202. if (SM->IsPS()) {
  203. bool hasStencilRef = false;
  204. DxilSignature &outS = GetOutputSignature();
  205. for (auto &&E : outS.GetElements()) {
  206. if (E->GetKind() == Semantic::Kind::StencilRef) {
  207. hasStencilRef = true;
  208. } else if (E->GetKind() == Semantic::Kind::InnerCoverage) {
  209. Flags.SetInnerCoverage(true);
  210. }
  211. }
  212. Flags.SetStencilRef(hasStencilRef);
  213. }
  214. bool checkInputRTArrayIndex =
  215. SM->IsGS() || SM->IsDS() || SM->IsHS() || SM->IsPS();
  216. if (checkInputRTArrayIndex) {
  217. bool hasViewportArrayIndex = false;
  218. bool hasRenderTargetArrayIndex = false;
  219. DxilSignature &inS = GetInputSignature();
  220. for (auto &E : inS.GetElements()) {
  221. if (E->GetKind() == Semantic::Kind::ViewPortArrayIndex) {
  222. hasViewportArrayIndex = true;
  223. } else if (E->GetKind() == Semantic::Kind::RenderTargetArrayIndex) {
  224. hasRenderTargetArrayIndex = true;
  225. }
  226. }
  227. Flags.SetViewportAndRTArrayIndex(hasViewportArrayIndex |
  228. hasRenderTargetArrayIndex);
  229. }
  230. bool checkOutputRTArrayIndex =
  231. SM->IsVS() || SM->IsDS() || SM->IsHS() || SM->IsPS();
  232. if (checkOutputRTArrayIndex) {
  233. bool hasViewportArrayIndex = false;
  234. bool hasRenderTargetArrayIndex = false;
  235. DxilSignature &outS = GetOutputSignature();
  236. for (auto &E : outS.GetElements()) {
  237. if (E->GetKind() == Semantic::Kind::ViewPortArrayIndex) {
  238. hasViewportArrayIndex = true;
  239. } else if (E->GetKind() == Semantic::Kind::RenderTargetArrayIndex) {
  240. hasRenderTargetArrayIndex = true;
  241. }
  242. }
  243. Flags.SetViewportAndRTArrayIndex(hasViewportArrayIndex |
  244. hasRenderTargetArrayIndex);
  245. }
  246. unsigned NumUAVs = m_UAVs.size();
  247. const unsigned kSmallUAVCount = 8;
  248. if (NumUAVs > kSmallUAVCount)
  249. Flags.Set64UAVs(true);
  250. if (NumUAVs && !(SM->IsCS() || SM->IsPS()))
  251. Flags.SetUAVsAtEveryStage(true);
  252. bool hasRawAndStructuredBuffer = false;
  253. for (auto &UAV : m_UAVs) {
  254. if (UAV->IsROV())
  255. Flags.SetROVs(true);
  256. switch (UAV->GetKind()) {
  257. case DXIL::ResourceKind::RawBuffer:
  258. case DXIL::ResourceKind::StructuredBuffer:
  259. hasRawAndStructuredBuffer = true;
  260. break;
  261. default:
  262. // Not raw/structured.
  263. break;
  264. }
  265. }
  266. for (auto &SRV : m_SRVs) {
  267. switch (SRV->GetKind()) {
  268. case DXIL::ResourceKind::RawBuffer:
  269. case DXIL::ResourceKind::StructuredBuffer:
  270. hasRawAndStructuredBuffer = true;
  271. break;
  272. default:
  273. // Not raw/structured.
  274. break;
  275. }
  276. }
  277. Flags.SetEnableRawAndStructuredBuffers(hasRawAndStructuredBuffer);
  278. bool hasCSRawAndStructuredViaShader4X =
  279. hasRawAndStructuredBuffer && m_pSM->GetMajor() == 4 && m_pSM->IsCS();
  280. Flags.SetCSRawAndStructuredViaShader4X(hasCSRawAndStructuredViaShader4X);
  281. }
  282. void DxilModule::CollectShaderFlagsForModule() {
  283. CollectShaderFlagsForModule(m_ShaderFlags);
  284. }
  285. DXIL::InputPrimitive DxilModule::GetInputPrimitive() const {
  286. return m_InputPrimitive;
  287. }
  288. void DxilModule::SetInputPrimitive(DXIL::InputPrimitive IP) {
  289. DXASSERT_NOMSG(m_InputPrimitive == DXIL::InputPrimitive::Undefined);
  290. DXASSERT_NOMSG(DXIL::InputPrimitive::Undefined < IP && IP < DXIL::InputPrimitive::LastEntry);
  291. m_InputPrimitive = IP;
  292. }
  293. unsigned DxilModule::GetMaxVertexCount() const {
  294. DXASSERT_NOMSG(m_MaxVertexCount != 0);
  295. return m_MaxVertexCount;
  296. }
  297. void DxilModule::SetMaxVertexCount(unsigned Count) {
  298. DXASSERT_NOMSG(m_MaxVertexCount == 0);
  299. m_MaxVertexCount = Count;
  300. }
  301. DXIL::PrimitiveTopology DxilModule::GetStreamPrimitiveTopology() const {
  302. return m_StreamPrimitiveTopology;
  303. }
  304. void DxilModule::SetStreamPrimitiveTopology(DXIL::PrimitiveTopology Topology) {
  305. m_StreamPrimitiveTopology = Topology;
  306. }
  307. bool DxilModule::HasMultipleOutputStreams() const {
  308. if (!m_pSM->IsGS()) {
  309. return false;
  310. } else {
  311. unsigned NumStreams = (m_ActiveStreamMask & 0x1) +
  312. ((m_ActiveStreamMask & 0x2) >> 1) +
  313. ((m_ActiveStreamMask & 0x4) >> 2) +
  314. ((m_ActiveStreamMask & 0x8) >> 3);
  315. DXASSERT_NOMSG(NumStreams <= DXIL::kNumOutputStreams);
  316. return NumStreams > 1;
  317. }
  318. }
  319. unsigned DxilModule::GetOutputStream() const {
  320. if (!m_pSM->IsGS()) {
  321. return 0;
  322. } else {
  323. DXASSERT_NOMSG(!HasMultipleOutputStreams());
  324. switch (m_ActiveStreamMask) {
  325. case 0x1: return 0;
  326. case 0x2: return 1;
  327. case 0x4: return 2;
  328. case 0x8: return 3;
  329. default: DXASSERT_NOMSG(false);
  330. }
  331. return (unsigned)(-1);
  332. }
  333. }
  334. unsigned DxilModule::GetGSInstanceCount() const {
  335. return m_NumGSInstances;
  336. }
  337. void DxilModule::SetGSInstanceCount(unsigned Count) {
  338. m_NumGSInstances = Count;
  339. }
  340. bool DxilModule::IsStreamActive(unsigned Stream) const {
  341. return (m_ActiveStreamMask & (1<<Stream)) != 0;
  342. }
  343. void DxilModule::SetStreamActive(unsigned Stream, bool bActive) {
  344. if (bActive) {
  345. m_ActiveStreamMask |= (1<<Stream);
  346. } else {
  347. m_ActiveStreamMask &= ~(1<<Stream);
  348. }
  349. }
  350. void DxilModule::SetActiveStreamMask(unsigned Mask) {
  351. m_ActiveStreamMask = Mask;
  352. }
  353. unsigned DxilModule::GetActiveStreamMask() const {
  354. return m_ActiveStreamMask;
  355. }
  356. void DxilModule::SetUseMinPrecision(bool UseMinPrecision) {
  357. m_bUseMinPrecision = UseMinPrecision;
  358. }
  359. bool DxilModule::GetUseMinPrecision() const {
  360. return m_bUseMinPrecision;
  361. }
  362. void DxilModule::SetDisableOptimization(bool DisableOptimization) {
  363. m_bDisableOptimizations = DisableOptimization;
  364. }
  365. bool DxilModule::GetDisableOptimization() const {
  366. return m_bDisableOptimizations;
  367. }
  368. void DxilModule::SetAllResourcesBound(bool ResourcesBound) {
  369. m_bAllResourcesBound = ResourcesBound;
  370. }
  371. bool DxilModule::GetAllResourcesBound() const {
  372. return m_bAllResourcesBound;
  373. }
  374. unsigned DxilModule::GetInputControlPointCount() const {
  375. return m_InputControlPointCount;
  376. }
  377. void DxilModule::SetInputControlPointCount(unsigned NumICPs) {
  378. m_InputControlPointCount = NumICPs;
  379. }
  380. DXIL::TessellatorDomain DxilModule::GetTessellatorDomain() const {
  381. return m_TessellatorDomain;
  382. }
  383. void DxilModule::SetTessellatorDomain(DXIL::TessellatorDomain TessDomain) {
  384. m_TessellatorDomain = TessDomain;
  385. }
  386. unsigned DxilModule::GetOutputControlPointCount() const {
  387. return m_OutputControlPointCount;
  388. }
  389. void DxilModule::SetOutputControlPointCount(unsigned NumOCPs) {
  390. m_OutputControlPointCount = NumOCPs;
  391. }
  392. DXIL::TessellatorPartitioning DxilModule::GetTessellatorPartitioning() const {
  393. return m_TessellatorPartitioning;
  394. }
  395. void DxilModule::SetTessellatorPartitioning(DXIL::TessellatorPartitioning TessPartitioning) {
  396. m_TessellatorPartitioning = TessPartitioning;
  397. }
  398. DXIL::TessellatorOutputPrimitive DxilModule::GetTessellatorOutputPrimitive() const {
  399. return m_TessellatorOutputPrimitive;
  400. }
  401. void DxilModule::SetTessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive TessOutputPrimitive) {
  402. m_TessellatorOutputPrimitive = TessOutputPrimitive;
  403. }
  404. float DxilModule::GetMaxTessellationFactor() const {
  405. return m_MaxTessellationFactor;
  406. }
  407. void DxilModule::SetMaxTessellationFactor(float MaxTessellationFactor) {
  408. m_MaxTessellationFactor = MaxTessellationFactor;
  409. }
  410. void DxilModule::SetAutoBindingSpace(uint32_t Space) {
  411. m_AutoBindingSpace = Space;
  412. }
  413. uint32_t DxilModule::GetAutoBindingSpace() const {
  414. return m_AutoBindingSpace;
  415. }
  416. void DxilModule::SetShaderProperties(DxilFunctionProps *props) {
  417. if (!props)
  418. return;
  419. switch (props->shaderKind) {
  420. case DXIL::ShaderKind::Pixel: {
  421. auto &PS = props->ShaderProps.PS;
  422. m_ShaderFlags.SetForceEarlyDepthStencil(PS.EarlyDepthStencil);
  423. } break;
  424. case DXIL::ShaderKind::Compute: {
  425. auto &CS = props->ShaderProps.CS;
  426. for (size_t i = 0; i < _countof(m_NumThreads); ++i)
  427. m_NumThreads[i] = CS.numThreads[i];
  428. } break;
  429. case DXIL::ShaderKind::Domain: {
  430. auto &DS = props->ShaderProps.DS;
  431. SetTessellatorDomain(DS.domain);
  432. SetInputControlPointCount(DS.inputControlPoints);
  433. } break;
  434. case DXIL::ShaderKind::Hull: {
  435. auto &HS = props->ShaderProps.HS;
  436. SetPatchConstantFunction(HS.patchConstantFunc);
  437. SetTessellatorDomain(HS.domain);
  438. SetTessellatorPartitioning(HS.partition);
  439. SetTessellatorOutputPrimitive(HS.outputPrimitive);
  440. SetInputControlPointCount(HS.inputControlPoints);
  441. SetOutputControlPointCount(HS.outputControlPoints);
  442. SetMaxTessellationFactor(HS.maxTessFactor);
  443. } break;
  444. case DXIL::ShaderKind::Vertex:
  445. break;
  446. default: {
  447. DXASSERT(props->shaderKind == DXIL::ShaderKind::Geometry,
  448. "else invalid shader kind");
  449. auto &GS = props->ShaderProps.GS;
  450. SetInputPrimitive(GS.inputPrimitive);
  451. SetMaxVertexCount(GS.maxVertexCount);
  452. for (size_t i = 0; i < _countof(GS.streamPrimitiveTopologies); ++i) {
  453. if (GS.streamPrimitiveTopologies[i] !=
  454. DXIL::PrimitiveTopology::Undefined) {
  455. SetStreamActive(i, true);
  456. DXASSERT_NOMSG(GetStreamPrimitiveTopology() ==
  457. DXIL::PrimitiveTopology::Undefined ||
  458. GetStreamPrimitiveTopology() ==
  459. GS.streamPrimitiveTopologies[i]);
  460. SetStreamPrimitiveTopology(GS.streamPrimitiveTopologies[i]);
  461. }
  462. }
  463. SetGSInstanceCount(GS.instanceCount);
  464. } break;
  465. }
  466. }
  467. template<typename T> unsigned
  468. DxilModule::AddResource(vector<unique_ptr<T> > &Vec, unique_ptr<T> pRes) {
  469. DXASSERT_NOMSG((unsigned)Vec.size() < UINT_MAX);
  470. unsigned Id = (unsigned)Vec.size();
  471. Vec.emplace_back(std::move(pRes));
  472. return Id;
  473. }
  474. unsigned DxilModule::AddCBuffer(unique_ptr<DxilCBuffer> pCB) {
  475. return AddResource<DxilCBuffer>(m_CBuffers, std::move(pCB));
  476. }
  477. DxilCBuffer &DxilModule::GetCBuffer(unsigned idx) {
  478. return *m_CBuffers[idx];
  479. }
  480. const DxilCBuffer &DxilModule::GetCBuffer(unsigned idx) const {
  481. return *m_CBuffers[idx];
  482. }
  483. const vector<unique_ptr<DxilCBuffer> > &DxilModule::GetCBuffers() const {
  484. return m_CBuffers;
  485. }
  486. unsigned DxilModule::AddSampler(unique_ptr<DxilSampler> pSampler) {
  487. return AddResource<DxilSampler>(m_Samplers, std::move(pSampler));
  488. }
  489. DxilSampler &DxilModule::GetSampler(unsigned idx) {
  490. return *m_Samplers[idx];
  491. }
  492. const DxilSampler &DxilModule::GetSampler(unsigned idx) const {
  493. return *m_Samplers[idx];
  494. }
  495. const vector<unique_ptr<DxilSampler> > &DxilModule::GetSamplers() const {
  496. return m_Samplers;
  497. }
  498. unsigned DxilModule::AddSRV(unique_ptr<DxilResource> pSRV) {
  499. return AddResource<DxilResource>(m_SRVs, std::move(pSRV));
  500. }
  501. DxilResource &DxilModule::GetSRV(unsigned idx) {
  502. return *m_SRVs[idx];
  503. }
  504. const DxilResource &DxilModule::GetSRV(unsigned idx) const {
  505. return *m_SRVs[idx];
  506. }
  507. const vector<unique_ptr<DxilResource> > &DxilModule::GetSRVs() const {
  508. return m_SRVs;
  509. }
  510. unsigned DxilModule::AddUAV(unique_ptr<DxilResource> pUAV) {
  511. return AddResource<DxilResource>(m_UAVs, std::move(pUAV));
  512. }
  513. DxilResource &DxilModule::GetUAV(unsigned idx) {
  514. return *m_UAVs[idx];
  515. }
  516. const DxilResource &DxilModule::GetUAV(unsigned idx) const {
  517. return *m_UAVs[idx];
  518. }
  519. const vector<unique_ptr<DxilResource> > &DxilModule::GetUAVs() const {
  520. return m_UAVs;
  521. }
  522. void DxilModule::LoadDxilResourceBaseFromMDNode(MDNode *MD, DxilResourceBase &R) {
  523. return m_pMDHelper->LoadDxilResourceBaseFromMDNode(MD, R);
  524. }
  525. void DxilModule::LoadDxilResourceFromMDNode(llvm::MDNode *MD, DxilResource &R) {
  526. return m_pMDHelper->LoadDxilResourceFromMDNode(MD, R);
  527. }
  528. void DxilModule::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  529. return m_pMDHelper->LoadDxilSamplerFromMDNode(MD, S);
  530. }
  531. template <typename TResource>
  532. static void RemoveResources(std::vector<std::unique_ptr<TResource>> &vec,
  533. std::unordered_set<unsigned> &immResID) {
  534. for (auto p = vec.begin(); p != vec.end();) {
  535. auto c = p++;
  536. if (immResID.count((*c)->GetID()) == 0) {
  537. p = vec.erase(c);
  538. }
  539. }
  540. }
  541. static void CollectUsedResource(Value *resID,
  542. std::unordered_set<Value *> &usedResID) {
  543. if (usedResID.count(resID) > 0)
  544. return;
  545. usedResID.insert(resID);
  546. if (ConstantInt *cResID = dyn_cast<ConstantInt>(resID)) {
  547. // Do nothing
  548. } else if (ZExtInst *ZEI = dyn_cast<ZExtInst>(resID)) {
  549. if (ZEI->getSrcTy()->isIntegerTy()) {
  550. IntegerType *ITy = cast<IntegerType>(ZEI->getSrcTy());
  551. if (ITy->getBitWidth() == 1) {
  552. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 0));
  553. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 1));
  554. }
  555. }
  556. } else if (SelectInst *SI = dyn_cast<SelectInst>(resID)) {
  557. CollectUsedResource(SI->getTrueValue(), usedResID);
  558. CollectUsedResource(SI->getFalseValue(), usedResID);
  559. } else if (PHINode *Phi = dyn_cast<PHINode>(resID)) {
  560. for (Use &U : Phi->incoming_values()) {
  561. CollectUsedResource(U.get(), usedResID);
  562. }
  563. }
  564. // TODO: resID could be other types of instructions depending on the compiler optimization.
  565. }
  566. static void ConvertUsedResource(std::unordered_set<unsigned> &immResID,
  567. std::unordered_set<Value *> &usedResID) {
  568. for (Value *V : usedResID) {
  569. if (ConstantInt *cResID = dyn_cast<ConstantInt>(V)) {
  570. immResID.insert(cResID->getLimitedValue());
  571. }
  572. }
  573. }
  574. void DxilModule::RemoveFunction(llvm::Function *F) {
  575. DXASSERT_NOMSG(F != nullptr);
  576. m_DxilFunctionPropsMap.erase(F);
  577. m_DxilEntrySignatureMap.erase(F);
  578. if (m_pTypeSystem.get()->GetFunctionAnnotation(F))
  579. m_pTypeSystem.get()->EraseFunctionAnnotation(F);
  580. m_pOP->RemoveFunction(F);
  581. }
  582. void DxilModule::RemoveUnusedResources() {
  583. DXASSERT(!m_pSM->IsLib(), "this function not work on library");
  584. hlsl::OP *hlslOP = GetOP();
  585. Function *createHandleFunc = hlslOP->GetOpFunc(DXIL::OpCode::CreateHandle, Type::getVoidTy(GetCtx()));
  586. if (createHandleFunc->user_empty()) {
  587. m_CBuffers.clear();
  588. m_UAVs.clear();
  589. m_SRVs.clear();
  590. m_Samplers.clear();
  591. createHandleFunc->eraseFromParent();
  592. return;
  593. }
  594. std::unordered_set<Value *> usedUAVID;
  595. std::unordered_set<Value *> usedSRVID;
  596. std::unordered_set<Value *> usedSamplerID;
  597. std::unordered_set<Value *> usedCBufID;
  598. // Collect used ID.
  599. for (User *U : createHandleFunc->users()) {
  600. CallInst *CI = cast<CallInst>(U);
  601. Value *vResClass =
  602. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
  603. ConstantInt *cResClass = cast<ConstantInt>(vResClass);
  604. DXIL::ResourceClass resClass =
  605. static_cast<DXIL::ResourceClass>(cResClass->getLimitedValue());
  606. // Skip unused resource handle.
  607. if (CI->user_empty())
  608. continue;
  609. Value *resID =
  610. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
  611. switch (resClass) {
  612. case DXIL::ResourceClass::CBuffer:
  613. CollectUsedResource(resID, usedCBufID);
  614. break;
  615. case DXIL::ResourceClass::Sampler:
  616. CollectUsedResource(resID, usedSamplerID);
  617. break;
  618. case DXIL::ResourceClass::SRV:
  619. CollectUsedResource(resID, usedSRVID);
  620. break;
  621. case DXIL::ResourceClass::UAV:
  622. CollectUsedResource(resID, usedUAVID);
  623. break;
  624. default:
  625. DXASSERT(0, "invalid res class");
  626. break;
  627. }
  628. }
  629. std::unordered_set<unsigned> immUAVID;
  630. std::unordered_set<unsigned> immSRVID;
  631. std::unordered_set<unsigned> immSamplerID;
  632. std::unordered_set<unsigned> immCBufID;
  633. ConvertUsedResource(immUAVID, usedUAVID);
  634. RemoveResources(m_UAVs, immUAVID);
  635. ConvertUsedResource(immSRVID, usedSRVID);
  636. ConvertUsedResource(immSamplerID, usedSamplerID);
  637. ConvertUsedResource(immCBufID, usedCBufID);
  638. RemoveResources(m_SRVs, immSRVID);
  639. RemoveResources(m_Samplers, immSamplerID);
  640. RemoveResources(m_CBuffers, immCBufID);
  641. }
  642. namespace {
  643. template <typename TResource>
  644. static void RemoveResourceSymbols(std::vector<std::unique_ptr<TResource>> &vec) {
  645. unsigned resID = 0;
  646. for (std::vector<std::unique_ptr<TResource>>::iterator p = vec.begin(); p != vec.end();) {
  647. std::vector<std::unique_ptr<TResource>>::iterator c = p++;
  648. GlobalVariable *GV = cast<GlobalVariable>((*c)->GetGlobalSymbol());
  649. GV->removeDeadConstantUsers();
  650. if (GV->user_empty()) {
  651. p = vec.erase(c);
  652. GV->eraseFromParent();
  653. continue;
  654. }
  655. if ((*c)->GetID() != resID) {
  656. (*c)->SetID(resID);
  657. }
  658. resID++;
  659. }
  660. }
  661. }
  662. void DxilModule::RemoveUnusedResourceSymbols() {
  663. RemoveResourceSymbols(m_SRVs);
  664. RemoveResourceSymbols(m_UAVs);
  665. RemoveResourceSymbols(m_CBuffers);
  666. RemoveResourceSymbols(m_Samplers);
  667. }
  668. DxilSignature &DxilModule::GetInputSignature() {
  669. return m_EntrySignature->InputSignature;
  670. }
  671. const DxilSignature &DxilModule::GetInputSignature() const {
  672. return m_EntrySignature->InputSignature;
  673. }
  674. DxilSignature &DxilModule::GetOutputSignature() {
  675. return m_EntrySignature->OutputSignature;
  676. }
  677. const DxilSignature &DxilModule::GetOutputSignature() const {
  678. return m_EntrySignature->OutputSignature;
  679. }
  680. DxilSignature &DxilModule::GetPatchConstantSignature() {
  681. return m_EntrySignature->PatchConstantSignature;
  682. }
  683. const DxilSignature &DxilModule::GetPatchConstantSignature() const {
  684. return m_EntrySignature->PatchConstantSignature;
  685. }
  686. const RootSignatureHandle &DxilModule::GetRootSignature() const {
  687. return *m_RootSignature;
  688. }
  689. bool DxilModule::HasDxilEntrySignature(const llvm::Function *F) const {
  690. return m_DxilEntrySignatureMap.find(F) != m_DxilEntrySignatureMap.end();
  691. }
  692. DxilEntrySignature &DxilModule::GetDxilEntrySignature(const llvm::Function *F) {
  693. DXASSERT(m_DxilEntrySignatureMap.count(F) != 0, "cannot find F in map");
  694. return *m_DxilEntrySignatureMap[F];
  695. }
  696. void DxilModule::ReplaceDxilEntrySignature(llvm::Function *F,
  697. llvm::Function *NewF) {
  698. DXASSERT(m_DxilEntrySignatureMap.count(F) != 0, "cannot find F in map");
  699. std::unique_ptr<DxilEntrySignature> Sig =
  700. std::move(m_DxilEntrySignatureMap[F]);
  701. m_DxilEntrySignatureMap.erase(F);
  702. m_DxilEntrySignatureMap[NewF] = std::move(Sig);
  703. }
  704. bool DxilModule::HasDxilFunctionProps(const llvm::Function *F) const {
  705. return m_DxilFunctionPropsMap.find(F) != m_DxilFunctionPropsMap.end();
  706. }
  707. DxilFunctionProps &DxilModule::GetDxilFunctionProps(const llvm::Function *F) {
  708. return const_cast<DxilFunctionProps &>(
  709. static_cast<const DxilModule *>(this)->GetDxilFunctionProps(F));
  710. }
  711. const DxilFunctionProps &
  712. DxilModule::GetDxilFunctionProps(const llvm::Function *F) const {
  713. DXASSERT(m_DxilFunctionPropsMap.count(F) != 0, "cannot find F in map");
  714. return *(m_DxilFunctionPropsMap.find(F))->second.get();
  715. }
  716. void DxilModule::AddDxilFunctionProps(
  717. const llvm::Function *F, std::unique_ptr<DxilFunctionProps> &info) {
  718. DXASSERT(m_DxilFunctionPropsMap.count(F) == 0,
  719. "F already in map, info will be overwritten");
  720. DXASSERT_NOMSG(info->shaderKind != DXIL::ShaderKind::Invalid);
  721. m_DxilFunctionPropsMap[F] = std::move(info);
  722. }
  723. void DxilModule::ReplaceDxilFunctionProps(llvm::Function *F,
  724. llvm::Function *NewF) {
  725. DXASSERT(m_DxilFunctionPropsMap.count(F) != 0, "cannot find F in map");
  726. std::unique_ptr<DxilFunctionProps> props =
  727. std::move(m_DxilFunctionPropsMap[F]);
  728. m_DxilFunctionPropsMap.erase(F);
  729. m_DxilFunctionPropsMap[NewF] = std::move(props);
  730. }
  731. void DxilModule::SetPatchConstantFunctionForHS(llvm::Function *hullShaderFunc, llvm::Function *patchConstantFunc) {
  732. auto propIter = m_DxilFunctionPropsMap.find(hullShaderFunc);
  733. DXASSERT(propIter != m_DxilFunctionPropsMap.end(), "Hull shader must already have function props!");
  734. DxilFunctionProps &props = *(propIter->second);
  735. DXASSERT(props.IsHS(), "else hullShaderFunc is not a Hull Shader");
  736. if (props.ShaderProps.HS.patchConstantFunc)
  737. m_PatchConstantFunctions.erase(props.ShaderProps.HS.patchConstantFunc);
  738. props.ShaderProps.HS.patchConstantFunc = patchConstantFunc;
  739. if (patchConstantFunc)
  740. m_PatchConstantFunctions.insert(patchConstantFunc);
  741. }
  742. bool DxilModule::IsGraphicsShader(const llvm::Function *F) const {
  743. return HasDxilFunctionProps(F) && GetDxilFunctionProps(F).IsGraphics();
  744. }
  745. bool DxilModule::IsPatchConstantShader(const llvm::Function *F) const {
  746. return m_PatchConstantFunctions.count(F) != 0;
  747. }
  748. bool DxilModule::IsComputeShader(const llvm::Function *F) const {
  749. return HasDxilFunctionProps(F) && GetDxilFunctionProps(F).IsCS();
  750. }
  751. bool DxilModule::IsEntryThatUsesSignatures(const llvm::Function *F) const {
  752. auto propIter = m_DxilFunctionPropsMap.find(F);
  753. if (propIter != m_DxilFunctionPropsMap.end()) {
  754. DxilFunctionProps &props = *(propIter->second);
  755. return props.IsGraphics() || props.IsCS();
  756. }
  757. // Otherwise, return true if patch constant function
  758. return IsPatchConstantShader(F);
  759. }
  760. void DxilModule::StripRootSignatureFromMetadata() {
  761. NamedMDNode *pRootSignatureNamedMD = GetModule()->getNamedMetadata(DxilMDHelper::kDxilRootSignatureMDName);
  762. if (pRootSignatureNamedMD) {
  763. GetModule()->eraseNamedMetadata(pRootSignatureNamedMD);
  764. }
  765. }
  766. void DxilModule::UpdateValidatorVersionMetadata() {
  767. m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
  768. }
  769. void DxilModule::ResetEntrySignature(DxilEntrySignature *pValue) {
  770. m_EntrySignature.reset(pValue);
  771. }
  772. void DxilModule::ResetRootSignature(RootSignatureHandle *pValue) {
  773. m_RootSignature.reset(pValue);
  774. }
  775. DxilTypeSystem &DxilModule::GetTypeSystem() {
  776. return *m_pTypeSystem;
  777. }
  778. DxilViewIdState &DxilModule::GetViewIdState() {
  779. return *m_pViewIdState;
  780. }
  781. const DxilViewIdState &DxilModule::GetViewIdState() const {
  782. return *m_pViewIdState;
  783. }
  784. void DxilModule::ResetTypeSystem(DxilTypeSystem *pValue) {
  785. m_pTypeSystem.reset(pValue);
  786. }
  787. void DxilModule::ResetOP(hlsl::OP *hlslOP) { m_pOP.reset(hlslOP); }
  788. void DxilModule::ResetFunctionPropsMap(DxilFunctionPropsMap &&propsMap) {
  789. m_DxilFunctionPropsMap = std::move(propsMap);
  790. }
  791. void DxilModule::ResetEntrySignatureMap(DxilEntrySignatureMap &&SigMap) {
  792. m_DxilEntrySignatureMap = std::move(SigMap);
  793. }
  794. static const StringRef llvmUsedName = "llvm.used";
  795. void DxilModule::EmitLLVMUsed() {
  796. if (GlobalVariable *oldGV = m_pModule->getGlobalVariable(llvmUsedName)) {
  797. oldGV->eraseFromParent();
  798. }
  799. if (m_LLVMUsed.empty())
  800. return;
  801. vector<llvm::Constant *> GVs;
  802. Type *pI8PtrType = Type::getInt8PtrTy(m_Ctx, DXIL::kDefaultAddrSpace);
  803. GVs.resize(m_LLVMUsed.size());
  804. for (size_t i = 0, e = m_LLVMUsed.size(); i != e; i++) {
  805. Constant *pConst = cast<Constant>(&*m_LLVMUsed[i]);
  806. PointerType *pPtrType = dyn_cast<PointerType>(pConst->getType());
  807. if (pPtrType->getPointerAddressSpace() != DXIL::kDefaultAddrSpace) {
  808. // Cast pointer to addrspace 0, as LLVMUsed elements must have the same
  809. // type.
  810. GVs[i] = ConstantExpr::getAddrSpaceCast(pConst, pI8PtrType);
  811. } else {
  812. GVs[i] = ConstantExpr::getPointerCast(pConst, pI8PtrType);
  813. }
  814. }
  815. ArrayType *pATy = ArrayType::get(pI8PtrType, GVs.size());
  816. GlobalVariable *pGV =
  817. new GlobalVariable(*m_pModule, pATy, false, GlobalValue::AppendingLinkage,
  818. ConstantArray::get(pATy, GVs), llvmUsedName);
  819. pGV->setSection("llvm.metadata");
  820. }
  821. void DxilModule::ClearLLVMUsed() {
  822. if (GlobalVariable *oldGV = m_pModule->getGlobalVariable(llvmUsedName)) {
  823. oldGV->eraseFromParent();
  824. }
  825. if (m_LLVMUsed.empty())
  826. return;
  827. for (size_t i = 0, e = m_LLVMUsed.size(); i != e; i++) {
  828. Constant *pConst = cast<Constant>(&*m_LLVMUsed[i]);
  829. pConst->removeDeadConstantUsers();
  830. }
  831. m_LLVMUsed.clear();
  832. }
  833. vector<GlobalVariable* > &DxilModule::GetLLVMUsed() {
  834. return m_LLVMUsed;
  835. }
  836. // DXIL metadata serialization/deserialization.
  837. void DxilModule::ClearDxilMetadata(Module &M) {
  838. // Delete: DXIL version, validator version, DXIL shader model,
  839. // entry point tuples (shader properties, signatures, resources)
  840. // type system, view ID state, LLVM used, entry point tuples,
  841. // root signature, function properties.
  842. // Other cases for libs pending.
  843. // LLVM used is a global variable - handle separately.
  844. Module::named_metadata_iterator
  845. b = M.named_metadata_begin(),
  846. e = M.named_metadata_end();
  847. SmallVector<NamedMDNode*, 8> nodes;
  848. for (; b != e; ++b) {
  849. StringRef name = b->getName();
  850. if (name == DxilMDHelper::kDxilVersionMDName ||
  851. name == DxilMDHelper::kDxilValidatorVersionMDName ||
  852. name == DxilMDHelper::kDxilShaderModelMDName ||
  853. name == DxilMDHelper::kDxilEntryPointsMDName ||
  854. name == DxilMDHelper::kDxilRootSignatureMDName ||
  855. name == DxilMDHelper::kDxilResourcesMDName ||
  856. name == DxilMDHelper::kDxilTypeSystemMDName ||
  857. name == DxilMDHelper::kDxilViewIdStateMDName ||
  858. name == DxilMDHelper::kDxilFunctionPropertiesMDName || // used in libraries
  859. name == DxilMDHelper::kDxilEntrySignaturesMDName || // used in libraries
  860. name == DxilMDHelper::kDxilResourcesLinkInfoMDName || // used in libraries
  861. name.startswith(DxilMDHelper::kDxilTypeSystemHelperVariablePrefix)) {
  862. nodes.push_back(b);
  863. }
  864. }
  865. for (size_t i = 0; i < nodes.size(); ++i) {
  866. M.eraseNamedMetadata(nodes[i]);
  867. }
  868. }
  869. void DxilModule::EmitDxilMetadata() {
  870. m_pMDHelper->EmitDxilVersion(m_DxilMajor, m_DxilMinor);
  871. m_pMDHelper->EmitValidatorVersion(m_ValMajor, m_ValMinor);
  872. m_pMDHelper->EmitDxilShaderModel(m_pSM);
  873. MDTuple *pMDProperties = EmitDxilShaderProperties();
  874. MDTuple *pMDSignatures = m_pMDHelper->EmitDxilSignatures(*m_EntrySignature);
  875. MDTuple *pMDResources = EmitDxilResources();
  876. if (pMDResources)
  877. m_pMDHelper->EmitDxilResources(pMDResources);
  878. m_pMDHelper->EmitDxilTypeSystem(GetTypeSystem(), m_LLVMUsed);
  879. if (!m_pSM->IsLib() && !m_pSM->IsCS() &&
  880. ((m_ValMajor == 0 && m_ValMinor == 0) ||
  881. (m_ValMajor > 1 || (m_ValMajor == 1 && m_ValMinor >= 1)))) {
  882. m_pMDHelper->EmitDxilViewIdState(GetViewIdState());
  883. }
  884. EmitLLVMUsed();
  885. MDTuple *pEntry = m_pMDHelper->EmitDxilEntryPointTuple(GetEntryFunction(), m_EntryName, pMDSignatures, pMDResources, pMDProperties);
  886. vector<MDNode *> Entries;
  887. Entries.emplace_back(pEntry);
  888. m_pMDHelper->EmitDxilEntryPoints(Entries);
  889. if (!m_RootSignature->IsEmpty()) {
  890. m_pMDHelper->EmitRootSignature(*m_RootSignature.get());
  891. }
  892. if (m_pSM->IsLib()) {
  893. NamedMDNode *fnProps = m_pModule->getOrInsertNamedMetadata(
  894. DxilMDHelper::kDxilFunctionPropertiesMDName);
  895. // Sort functions by name to keep metadata deterministic
  896. vector<const Function *> funcOrder;
  897. funcOrder.reserve(std::max(m_DxilFunctionPropsMap.size(),
  898. m_DxilEntrySignatureMap.size()));
  899. std::transform( m_DxilFunctionPropsMap.begin(),
  900. m_DxilFunctionPropsMap.end(),
  901. std::back_inserter(funcOrder),
  902. [](auto &p) -> const Function* { return p.first; } );
  903. std::sort(funcOrder.begin(), funcOrder.end(), [](const Function *F1, const Function *F2) {
  904. return F1->getName() < F2->getName();
  905. });
  906. for (auto F : funcOrder) {
  907. MDTuple *pProps = m_pMDHelper->EmitDxilFunctionProps(&GetDxilFunctionProps(F), F);
  908. fnProps->addOperand(pProps);
  909. }
  910. funcOrder.clear();
  911. NamedMDNode *entrySigs = m_pModule->getOrInsertNamedMetadata(
  912. DxilMDHelper::kDxilEntrySignaturesMDName);
  913. // Sort functions by name to keep metadata deterministic
  914. std::transform( m_DxilEntrySignatureMap.begin(),
  915. m_DxilEntrySignatureMap.end(),
  916. std::back_inserter(funcOrder),
  917. [](auto &p) -> const Function* { return p.first; } );
  918. std::sort(funcOrder.begin(), funcOrder.end(), [](const Function *F1, const Function *F2) {
  919. return F1->getName() < F2->getName();
  920. });
  921. for (auto F : funcOrder) {
  922. DxilEntrySignature *Sig = &GetDxilEntrySignature(F);
  923. MDTuple *pSig = m_pMDHelper->EmitDxilSignatures(*Sig);
  924. entrySigs->addOperand(
  925. MDTuple::get(m_Ctx, {ValueAsMetadata::get(const_cast<Function*>(F)), pSig}));
  926. }
  927. }
  928. }
  929. bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
  930. return DxilMDHelper::IsKnownNamedMetaData(Node);
  931. }
  932. void DxilModule::LoadDxilMetadata() {
  933. m_pMDHelper->LoadDxilVersion(m_DxilMajor, m_DxilMinor);
  934. m_pMDHelper->LoadValidatorVersion(m_ValMajor, m_ValMinor);
  935. const ShaderModel *loadedModule;
  936. m_pMDHelper->LoadDxilShaderModel(loadedModule);
  937. SetShaderModel(loadedModule);
  938. DXASSERT(m_EntrySignature != nullptr, "else SetShaderModel didn't create entry signature");
  939. const llvm::NamedMDNode *pEntries = m_pMDHelper->GetDxilEntryPoints();
  940. IFTBOOL(pEntries->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  941. Function *pEntryFunc;
  942. string EntryName;
  943. const llvm::MDOperand *pSignatures, *pResources, *pProperties;
  944. m_pMDHelper->GetDxilEntryPoint(pEntries->getOperand(0), pEntryFunc, EntryName, pSignatures, pResources, pProperties);
  945. SetEntryFunction(pEntryFunc);
  946. SetEntryFunctionName(EntryName);
  947. LoadDxilShaderProperties(*pProperties);
  948. m_pMDHelper->LoadDxilSignatures(*pSignatures, *m_EntrySignature);
  949. LoadDxilResources(*pResources);
  950. m_pMDHelper->LoadDxilTypeSystem(*m_pTypeSystem.get());
  951. m_pMDHelper->LoadRootSignature(*m_RootSignature.get());
  952. m_pMDHelper->LoadDxilViewIdState(*m_pViewIdState.get());
  953. if (loadedModule->IsLib()) {
  954. NamedMDNode *fnProps = m_pModule->getNamedMetadata(
  955. DxilMDHelper::kDxilFunctionPropertiesMDName);
  956. size_t propIdx = 0;
  957. while (propIdx < fnProps->getNumOperands()) {
  958. MDTuple *pProps = dyn_cast<MDTuple>(fnProps->getOperand(propIdx++));
  959. std::unique_ptr<hlsl::DxilFunctionProps> props =
  960. llvm::make_unique<hlsl::DxilFunctionProps>();
  961. Function *F = m_pMDHelper->LoadDxilFunctionProps(pProps, props.get());
  962. if (props->IsHS() && props->ShaderProps.HS.patchConstantFunc) {
  963. // Add patch constant function to m_PatchConstantFunctions
  964. m_PatchConstantFunctions.insert(props->ShaderProps.HS.patchConstantFunc);
  965. }
  966. m_DxilFunctionPropsMap[F] = std::move(props);
  967. }
  968. NamedMDNode *entrySigs = m_pModule->getOrInsertNamedMetadata(
  969. DxilMDHelper::kDxilEntrySignaturesMDName);
  970. size_t sigIdx = 0;
  971. while (sigIdx < entrySigs->getNumOperands()) {
  972. MDTuple *pSig = dyn_cast<MDTuple>(entrySigs->getOperand(sigIdx++));
  973. unsigned idx = 0;
  974. Function *F = dyn_cast<Function>(
  975. dyn_cast<ValueAsMetadata>(pSig->getOperand(idx++))->getValue());
  976. // Entry must have props.
  977. IFTBOOL(m_DxilFunctionPropsMap.count(F), DXC_E_INCORRECT_DXIL_METADATA);
  978. DXIL::ShaderKind shaderKind = m_DxilFunctionPropsMap[F]->shaderKind;
  979. std::unique_ptr<hlsl::DxilEntrySignature> Sig =
  980. llvm::make_unique<hlsl::DxilEntrySignature>(shaderKind, GetUseMinPrecision());
  981. m_pMDHelper->LoadDxilSignatures(pSig->getOperand(idx), *Sig);
  982. m_DxilEntrySignatureMap[F] = std::move(Sig);
  983. }
  984. }
  985. }
  986. MDTuple *DxilModule::EmitDxilResources() {
  987. // Emit SRV records.
  988. MDTuple *pTupleSRVs = nullptr;
  989. if (!m_SRVs.empty()) {
  990. vector<Metadata *> MDVals;
  991. for (size_t i = 0; i < m_SRVs.size(); i++) {
  992. MDVals.emplace_back(m_pMDHelper->EmitDxilSRV(*m_SRVs[i]));
  993. }
  994. pTupleSRVs = MDNode::get(m_Ctx, MDVals);
  995. }
  996. // Emit UAV records.
  997. MDTuple *pTupleUAVs = nullptr;
  998. if (!m_UAVs.empty()) {
  999. vector<Metadata *> MDVals;
  1000. for (size_t i = 0; i < m_UAVs.size(); i++) {
  1001. MDVals.emplace_back(m_pMDHelper->EmitDxilUAV(*m_UAVs[i]));
  1002. }
  1003. pTupleUAVs = MDNode::get(m_Ctx, MDVals);
  1004. }
  1005. // Emit CBuffer records.
  1006. MDTuple *pTupleCBuffers = nullptr;
  1007. if (!m_CBuffers.empty()) {
  1008. vector<Metadata *> MDVals;
  1009. for (size_t i = 0; i < m_CBuffers.size(); i++) {
  1010. MDVals.emplace_back(m_pMDHelper->EmitDxilCBuffer(*m_CBuffers[i]));
  1011. }
  1012. pTupleCBuffers = MDNode::get(m_Ctx, MDVals);
  1013. }
  1014. // Emit Sampler records.
  1015. MDTuple *pTupleSamplers = nullptr;
  1016. if (!m_Samplers.empty()) {
  1017. vector<Metadata *> MDVals;
  1018. for (size_t i = 0; i < m_Samplers.size(); i++) {
  1019. MDVals.emplace_back(m_pMDHelper->EmitDxilSampler(*m_Samplers[i]));
  1020. }
  1021. pTupleSamplers = MDNode::get(m_Ctx, MDVals);
  1022. }
  1023. if (pTupleSRVs != nullptr || pTupleUAVs != nullptr || pTupleCBuffers != nullptr || pTupleSamplers != nullptr) {
  1024. return m_pMDHelper->EmitDxilResourceTuple(pTupleSRVs, pTupleUAVs, pTupleCBuffers, pTupleSamplers);
  1025. } else {
  1026. return nullptr;
  1027. }
  1028. }
  1029. void DxilModule::ReEmitDxilResources() {
  1030. ClearDxilMetadata(*m_pModule);
  1031. if (!m_pSM->IsCS() && !m_pSM->IsLib())
  1032. m_pViewIdState->Compute();
  1033. EmitDxilMetadata();
  1034. }
  1035. void DxilModule::LoadDxilResources(const llvm::MDOperand &MDO) {
  1036. if (MDO.get() == nullptr)
  1037. return;
  1038. const llvm::MDTuple *pSRVs, *pUAVs, *pCBuffers, *pSamplers;
  1039. m_pMDHelper->GetDxilResources(MDO, pSRVs, pUAVs, pCBuffers, pSamplers);
  1040. // Load SRV records.
  1041. if (pSRVs != nullptr) {
  1042. for (unsigned i = 0; i < pSRVs->getNumOperands(); i++) {
  1043. unique_ptr<DxilResource> pSRV(new DxilResource);
  1044. m_pMDHelper->LoadDxilSRV(pSRVs->getOperand(i), *pSRV);
  1045. AddSRV(std::move(pSRV));
  1046. }
  1047. }
  1048. // Load UAV records.
  1049. if (pUAVs != nullptr) {
  1050. for (unsigned i = 0; i < pUAVs->getNumOperands(); i++) {
  1051. unique_ptr<DxilResource> pUAV(new DxilResource);
  1052. m_pMDHelper->LoadDxilUAV(pUAVs->getOperand(i), *pUAV);
  1053. AddUAV(std::move(pUAV));
  1054. }
  1055. }
  1056. // Load CBuffer records.
  1057. if (pCBuffers != nullptr) {
  1058. for (unsigned i = 0; i < pCBuffers->getNumOperands(); i++) {
  1059. unique_ptr<DxilCBuffer> pCB(new DxilCBuffer);
  1060. m_pMDHelper->LoadDxilCBuffer(pCBuffers->getOperand(i), *pCB);
  1061. AddCBuffer(std::move(pCB));
  1062. }
  1063. }
  1064. // Load Sampler records.
  1065. if (pSamplers != nullptr) {
  1066. for (unsigned i = 0; i < pSamplers->getNumOperands(); i++) {
  1067. unique_ptr<DxilSampler> pSampler(new DxilSampler);
  1068. m_pMDHelper->LoadDxilSampler(pSamplers->getOperand(i), *pSampler);
  1069. AddSampler(std::move(pSampler));
  1070. }
  1071. }
  1072. }
  1073. MDTuple *DxilModule::EmitDxilShaderProperties() {
  1074. vector<Metadata *> MDVals;
  1075. // DXIL shader flags.
  1076. uint64_t flag = m_ShaderFlags.GetShaderFlagsRaw();
  1077. if (flag != 0) {
  1078. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilShaderFlagsTag));
  1079. MDVals.emplace_back(m_pMDHelper->Uint64ToConstMD(flag));
  1080. }
  1081. // Compute shader.
  1082. if (m_pSM->IsCS()) {
  1083. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  1084. vector<Metadata *> NumThreadVals;
  1085. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[0]));
  1086. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[1]));
  1087. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[2]));
  1088. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  1089. }
  1090. // Geometry shader.
  1091. if (m_pSM->IsGS()) {
  1092. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  1093. MDTuple *pMDTuple = m_pMDHelper->EmitDxilGSState(m_InputPrimitive,
  1094. m_MaxVertexCount,
  1095. GetActiveStreamMask(),
  1096. m_StreamPrimitiveTopology,
  1097. m_NumGSInstances);
  1098. MDVals.emplace_back(pMDTuple);
  1099. }
  1100. // Domain shader.
  1101. if (m_pSM->IsDS()) {
  1102. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  1103. MDTuple *pMDTuple = m_pMDHelper->EmitDxilDSState(m_TessellatorDomain,
  1104. m_InputControlPointCount);
  1105. MDVals.emplace_back(pMDTuple);
  1106. }
  1107. // Hull shader.
  1108. if (m_pSM->IsHS()) {
  1109. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  1110. MDTuple *pMDTuple = m_pMDHelper->EmitDxilHSState(m_pPatchConstantFunc,
  1111. m_InputControlPointCount,
  1112. m_OutputControlPointCount,
  1113. m_TessellatorDomain,
  1114. m_TessellatorPartitioning,
  1115. m_TessellatorOutputPrimitive,
  1116. m_MaxTessellationFactor);
  1117. MDVals.emplace_back(pMDTuple);
  1118. }
  1119. if (GetAutoBindingSpace() != UINT_MAX && m_pSM->IsSMAtLeast(6, 3)) {
  1120. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilAutoBindingSpaceTag));
  1121. MDVals.emplace_back(MDNode::get(m_Ctx, { m_pMDHelper->Uint32ToConstMD(GetAutoBindingSpace()) }));
  1122. }
  1123. if (!MDVals.empty())
  1124. return MDNode::get(m_Ctx, MDVals);
  1125. else
  1126. return nullptr;
  1127. }
  1128. void DxilModule::LoadDxilShaderProperties(const MDOperand &MDO) {
  1129. if (MDO.get() == nullptr)
  1130. return;
  1131. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1132. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1133. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1134. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  1135. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  1136. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  1137. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1138. switch (Tag) {
  1139. case DxilMDHelper::kDxilShaderFlagsTag:
  1140. m_ShaderFlags.SetShaderFlagsRaw(DxilMDHelper::ConstMDToUint64(MDO));
  1141. m_bUseMinPrecision = !m_ShaderFlags.GetUseNativeLowPrecision();
  1142. m_bDisableOptimizations = m_ShaderFlags.GetDisableOptimizations();
  1143. m_bAllResourcesBound = m_ShaderFlags.GetAllResourcesBound();
  1144. break;
  1145. case DxilMDHelper::kDxilNumThreadsTag: {
  1146. MDNode *pNode = cast<MDNode>(MDO.get());
  1147. m_NumThreads[0] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(0));
  1148. m_NumThreads[1] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(1));
  1149. m_NumThreads[2] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(2));
  1150. break;
  1151. }
  1152. case DxilMDHelper::kDxilGSStateTag: {
  1153. m_pMDHelper->LoadDxilGSState(MDO, m_InputPrimitive, m_MaxVertexCount, m_ActiveStreamMask,
  1154. m_StreamPrimitiveTopology, m_NumGSInstances);
  1155. break;
  1156. }
  1157. case DxilMDHelper::kDxilDSStateTag:
  1158. m_pMDHelper->LoadDxilDSState(MDO, m_TessellatorDomain, m_InputControlPointCount);
  1159. break;
  1160. case DxilMDHelper::kDxilHSStateTag:
  1161. m_pMDHelper->LoadDxilHSState(MDO,
  1162. m_pPatchConstantFunc,
  1163. m_InputControlPointCount,
  1164. m_OutputControlPointCount,
  1165. m_TessellatorDomain,
  1166. m_TessellatorPartitioning,
  1167. m_TessellatorOutputPrimitive,
  1168. m_MaxTessellationFactor);
  1169. break;
  1170. case DxilMDHelper::kDxilAutoBindingSpaceTag: {
  1171. MDNode *pNode = cast<MDNode>(MDO.get());
  1172. SetAutoBindingSpace(DxilMDHelper::ConstMDToUint32(pNode->getOperand(0)));
  1173. break;
  1174. }
  1175. default:
  1176. DXASSERT(false, "Unknown extended shader properties tag");
  1177. break;
  1178. }
  1179. }
  1180. }
  1181. void DxilModule::StripDebugRelatedCode() {
  1182. // Remove all users of global resources.
  1183. for (GlobalVariable &GV : m_pModule->globals()) {
  1184. if (GV.hasInternalLinkage())
  1185. continue;
  1186. if (GV.getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace)
  1187. continue;
  1188. for (auto git = GV.user_begin(); git != GV.user_end();) {
  1189. User *U = *(git++);
  1190. // Try to remove load of GV.
  1191. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  1192. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1193. Instruction *LIUser = cast<Instruction>(*(it++));
  1194. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1195. Value *Ptr = SI->getPointerOperand();
  1196. SI->eraseFromParent();
  1197. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1198. if (Ptr->user_empty())
  1199. PtrInst->eraseFromParent();
  1200. }
  1201. }
  1202. }
  1203. if (LI->user_empty())
  1204. LI->eraseFromParent();
  1205. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
  1206. for (auto GEPIt = GEP->user_begin(); GEPIt != GEP->user_end();) {
  1207. User *GEPU = *(GEPIt++);
  1208. // Try to remove load of GEP.
  1209. if (LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
  1210. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1211. Instruction *LIUser = cast<Instruction>(*(it++));
  1212. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1213. Value *Ptr = SI->getPointerOperand();
  1214. SI->eraseFromParent();
  1215. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1216. if (Ptr->user_empty())
  1217. PtrInst->eraseFromParent();
  1218. }
  1219. }
  1220. if (LI->user_empty())
  1221. LI->eraseFromParent();
  1222. }
  1223. }
  1224. }
  1225. if (GEP->user_empty())
  1226. GEP->eraseFromParent();
  1227. }
  1228. }
  1229. }
  1230. // Remove dx.source metadata.
  1231. if (NamedMDNode *contents = m_pModule->getNamedMetadata(
  1232. DxilMDHelper::kDxilSourceContentsMDName)) {
  1233. contents->eraseFromParent();
  1234. }
  1235. if (NamedMDNode *defines =
  1236. m_pModule->getNamedMetadata(DxilMDHelper::kDxilSourceDefinesMDName)) {
  1237. defines->eraseFromParent();
  1238. }
  1239. if (NamedMDNode *mainFileName = m_pModule->getNamedMetadata(
  1240. DxilMDHelper::kDxilSourceMainFileNameMDName)) {
  1241. mainFileName->eraseFromParent();
  1242. }
  1243. if (NamedMDNode *arguments =
  1244. m_pModule->getNamedMetadata(DxilMDHelper::kDxilSourceArgsMDName)) {
  1245. arguments->eraseFromParent();
  1246. }
  1247. }
  1248. DebugInfoFinder &DxilModule::GetOrCreateDebugInfoFinder() {
  1249. if (m_pDebugInfoFinder == nullptr) {
  1250. m_pDebugInfoFinder = llvm::make_unique<llvm::DebugInfoFinder>();
  1251. m_pDebugInfoFinder->processModule(*m_pModule);
  1252. }
  1253. return *m_pDebugInfoFinder;
  1254. }
  1255. hlsl::DxilModule *hlsl::DxilModule::TryGetDxilModule(llvm::Module *pModule) {
  1256. LLVMContext &Ctx = pModule->getContext();
  1257. std::string diagStr;
  1258. raw_string_ostream diagStream(diagStr);
  1259. hlsl::DxilModule *pDxilModule = nullptr;
  1260. // TODO: add detail error in DxilMDHelper.
  1261. try {
  1262. pDxilModule = &pModule->GetOrCreateDxilModule();
  1263. } catch (const ::hlsl::Exception &hlslException) {
  1264. diagStream << "load dxil metadata failed -";
  1265. try {
  1266. const char *msg = hlslException.what();
  1267. if (msg == nullptr || *msg == '\0')
  1268. diagStream << " error code " << hlslException.hr << "\n";
  1269. else
  1270. diagStream << msg;
  1271. } catch (...) {
  1272. diagStream << " unable to retrieve error message.\n";
  1273. }
  1274. Ctx.diagnose(DxilErrorDiagnosticInfo(diagStream.str().c_str()));
  1275. } catch (...) {
  1276. Ctx.diagnose(DxilErrorDiagnosticInfo("load dxil metadata failed - unknown error.\n"));
  1277. }
  1278. return pDxilModule;
  1279. }
  1280. // Check if the instruction has fast math flags configured to indicate
  1281. // the instruction is precise.
  1282. // Precise fast math flags means none of the fast math flags are set.
  1283. bool DxilModule::HasPreciseFastMathFlags(const Instruction *inst) {
  1284. return isa<FPMathOperator>(inst) && !inst->getFastMathFlags().any();
  1285. }
  1286. // Set fast math flags configured to indicate the instruction is precise.
  1287. void DxilModule::SetPreciseFastMathFlags(llvm::Instruction *inst) {
  1288. assert(isa<FPMathOperator>(inst));
  1289. inst->copyFastMathFlags(FastMathFlags());
  1290. }
  1291. // True if fast math flags are preserved across serialization/deserialization
  1292. // of the dxil module.
  1293. //
  1294. // We need to check for this when querying fast math flags for preciseness
  1295. // otherwise we will be overly conservative by reporting instructions precise
  1296. // because their fast math flags were not preserved.
  1297. //
  1298. // Currently we restrict it to the instruction types that have fast math
  1299. // preserved in the bitcode. We can expand this by converting fast math
  1300. // flags to dx.precise metadata during serialization and back to fast
  1301. // math flags during deserialization.
  1302. bool DxilModule::PreservesFastMathFlags(const llvm::Instruction *inst) {
  1303. return
  1304. isa<FPMathOperator>(inst) && (isa<BinaryOperator>(inst) || isa<FCmpInst>(inst));
  1305. }
  1306. bool DxilModule::IsPrecise(const Instruction *inst) const {
  1307. if (m_ShaderFlags.GetDisableMathRefactoring())
  1308. return true;
  1309. else if (DxilMDHelper::IsMarkedPrecise(inst))
  1310. return true;
  1311. else if (PreservesFastMathFlags(inst))
  1312. return HasPreciseFastMathFlags(inst);
  1313. else
  1314. return false;
  1315. }
  1316. } // namespace hlsl
  1317. namespace llvm {
  1318. hlsl::DxilModule &Module::GetOrCreateDxilModule(bool skipInit) {
  1319. std::unique_ptr<hlsl::DxilModule> M;
  1320. if (!HasDxilModule()) {
  1321. M = llvm::make_unique<hlsl::DxilModule>(this);
  1322. if (!skipInit) {
  1323. M->LoadDxilMetadata();
  1324. }
  1325. SetDxilModule(M.release());
  1326. }
  1327. return GetDxilModule();
  1328. }
  1329. void Module::ResetDxilModule() {
  1330. if (HasDxilModule()) {
  1331. delete TheDxilModule;
  1332. TheDxilModule = nullptr;
  1333. }
  1334. }
  1335. }