DxilModule.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  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 "llvm/IR/Constants.h"
  17. #include "llvm/IR/Function.h"
  18. #include "llvm/IR/Instructions.h"
  19. #include "llvm/IR/LLVMContext.h"
  20. #include "llvm/IR/Metadata.h"
  21. #include "llvm/IR/Module.h"
  22. #include "llvm/IR/DebugInfo.h"
  23. #include "llvm/IR/DiagnosticInfo.h"
  24. #include "llvm/IR/DiagnosticPrinter.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. #include <unordered_set>
  27. using namespace llvm;
  28. using std::string;
  29. using std::vector;
  30. using std::unique_ptr;
  31. namespace {
  32. class DxilErrorDiagnosticInfo : public DiagnosticInfo {
  33. private:
  34. const char *m_message;
  35. public:
  36. DxilErrorDiagnosticInfo(const char *str)
  37. : DiagnosticInfo(DK_FirstPluginKind, DiagnosticSeverity::DS_Error),
  38. m_message(str) { }
  39. __override void print(DiagnosticPrinter &DP) const {
  40. DP << m_message;
  41. }
  42. };
  43. } // anon namespace
  44. namespace hlsl {
  45. //------------------------------------------------------------------------------
  46. //
  47. // DxilModule methods.
  48. //
  49. DxilModule::DxilModule(Module *pModule)
  50. : m_Ctx(pModule->getContext())
  51. , m_pModule(pModule)
  52. , m_pOP(std::make_unique<OP>(pModule->getContext(), pModule))
  53. , m_pTypeSystem(std::make_unique<DxilTypeSystem>(pModule))
  54. , m_pViewIdState(std::make_unique<DxilViewIdState>(this))
  55. , m_pMDHelper(std::make_unique<DxilMDHelper>(pModule, std::make_unique<DxilExtraPropertyHelper>(pModule)))
  56. , m_pDebugInfoFinder(nullptr)
  57. , m_pEntryFunc(nullptr)
  58. , m_EntryName("")
  59. , m_pPatchConstantFunc(nullptr)
  60. , m_pSM(nullptr)
  61. , m_DxilMajor(DXIL::kDxilMajor)
  62. , m_DxilMinor(DXIL::kDxilMinor)
  63. , m_InputPrimitive(DXIL::InputPrimitive::Undefined)
  64. , m_MaxVertexCount(0)
  65. , m_StreamPrimitiveTopology(DXIL::PrimitiveTopology::Undefined)
  66. , m_ActiveStreamMask(0)
  67. , m_NumGSInstances(1)
  68. , m_InputControlPointCount(0)
  69. , m_TessellatorDomain(DXIL::TessellatorDomain::Undefined)
  70. , m_OutputControlPointCount(0)
  71. , m_TessellatorPartitioning(DXIL::TessellatorPartitioning::Undefined)
  72. , m_TessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive::Undefined)
  73. , m_MaxTessellationFactor(0.f)
  74. , m_RootSignature(nullptr) {
  75. DXASSERT_NOMSG(m_pModule != nullptr);
  76. m_NumThreads[0] = m_NumThreads[1] = m_NumThreads[2] = 0;
  77. #if defined(_DEBUG) || defined(DBG)
  78. // Pin LLVM dump methods.
  79. void (__thiscall Module::*pfnModuleDump)() const = &Module::dump;
  80. void (__thiscall Type::*pfnTypeDump)() const = &Type::dump;
  81. void (__thiscall Function::*pfnViewCFGOnly)() const = &Function::viewCFGOnly;
  82. m_pUnused = (char *)&pfnModuleDump - (char *)&pfnTypeDump;
  83. m_pUnused -= (size_t)&pfnViewCFGOnly;
  84. #endif
  85. }
  86. DxilModule::~DxilModule() {
  87. }
  88. DxilModule::ShaderFlags::ShaderFlags():
  89. m_bDisableOptimizations(false)
  90. , m_bDisableMathRefactoring(false)
  91. , m_bEnableDoublePrecision(false)
  92. , m_bForceEarlyDepthStencil(false)
  93. , m_bEnableRawAndStructuredBuffers(false)
  94. , m_bEnableMinPrecision(false)
  95. , m_bEnableDoubleExtensions(false)
  96. , m_bEnableMSAD(false)
  97. , m_bAllResourcesBound(false)
  98. , m_bViewportAndRTArrayIndex(false)
  99. , m_bInnerCoverage(false)
  100. , m_bStencilRef(false)
  101. , m_bTiledResources(false)
  102. , m_bUAVLoadAdditionalFormats(false)
  103. , m_bLevel9ComparisonFiltering(false)
  104. , m_bCSRawAndStructuredViaShader4X(false)
  105. , m_b64UAVs(false)
  106. , m_UAVsAtEveryStage(false)
  107. , m_bROVS(false)
  108. , m_bWaveOps(false)
  109. , m_bInt64Ops(false)
  110. , m_align0(0)
  111. , m_align1(0)
  112. {}
  113. LLVMContext &DxilModule::GetCtx() const { return m_Ctx; }
  114. Module *DxilModule::GetModule() const { return m_pModule; }
  115. OP *DxilModule::GetOP() const { return m_pOP.get(); }
  116. void DxilModule::SetShaderModel(const ShaderModel *pSM) {
  117. DXASSERT(m_pSM == nullptr || (pSM != nullptr && *m_pSM == *pSM), "shader model must not change for the module");
  118. DXASSERT(pSM != nullptr && pSM->IsValidForDxil(), "shader model must be valid");
  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_InputSignature.reset(new DxilSignature(shaderKind, DXIL::SignatureKind::Input));
  124. m_OutputSignature.reset(new DxilSignature(shaderKind, DXIL::SignatureKind::Output));
  125. m_PatchConstantSignature.reset(new DxilSignature(shaderKind, DXIL::SignatureKind::PatchConstant));
  126. m_RootSignature.reset(new RootSignatureHandle());
  127. }
  128. const ShaderModel *DxilModule::GetShaderModel() const {
  129. return m_pSM;
  130. }
  131. void DxilModule::GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const {
  132. DxilMajor = m_DxilMajor;
  133. DxilMinor = m_DxilMinor;
  134. }
  135. Function *DxilModule::GetEntryFunction() {
  136. return m_pEntryFunc;
  137. }
  138. const Function *DxilModule::GetEntryFunction() const {
  139. return m_pEntryFunc;
  140. }
  141. void DxilModule::SetEntryFunction(Function *pEntryFunc) {
  142. m_pEntryFunc = pEntryFunc;
  143. }
  144. const string &DxilModule::GetEntryFunctionName() const {
  145. return m_EntryName;
  146. }
  147. void DxilModule::SetEntryFunctionName(const string &name) {
  148. m_EntryName = name;
  149. }
  150. llvm::Function *DxilModule::GetPatchConstantFunction() {
  151. return m_pPatchConstantFunc;
  152. }
  153. const llvm::Function *DxilModule::GetPatchConstantFunction() const {
  154. return m_pPatchConstantFunc;
  155. }
  156. void DxilModule::SetPatchConstantFunction(llvm::Function *pFunc) {
  157. m_pPatchConstantFunc = pFunc;
  158. }
  159. unsigned DxilModule::ShaderFlags::GetGlobalFlags() const {
  160. unsigned Flags = 0;
  161. Flags |= m_bDisableOptimizations ? DXIL::kDisableOptimizations : 0;
  162. Flags |= m_bDisableMathRefactoring ? DXIL::kDisableMathRefactoring : 0;
  163. Flags |= m_bEnableDoublePrecision ? DXIL::kEnableDoublePrecision : 0;
  164. Flags |= m_bForceEarlyDepthStencil ? DXIL::kForceEarlyDepthStencil : 0;
  165. Flags |= m_bEnableRawAndStructuredBuffers ? DXIL::kEnableRawAndStructuredBuffers : 0;
  166. Flags |= m_bEnableMinPrecision ? DXIL::kEnableMinPrecision : 0;
  167. Flags |= m_bEnableDoubleExtensions ? DXIL::kEnableDoubleExtensions : 0;
  168. Flags |= m_bEnableMSAD ? DXIL::kEnableMSAD : 0;
  169. Flags |= m_bAllResourcesBound ? DXIL::kAllResourcesBound : 0;
  170. return Flags;
  171. }
  172. uint64_t DxilModule::ShaderFlags::GetFeatureInfo() const {
  173. uint64_t Flags = 0;
  174. Flags |= m_bEnableDoublePrecision ? hlsl::ShaderFeatureInfo_Doubles : 0;
  175. Flags |= m_bEnableMinPrecision ? hlsl::ShaderFeatureInfo_MininumPrecision : 0;
  176. Flags |= m_bEnableDoubleExtensions ? hlsl::ShaderFeatureInfo_11_1_DoubleExtensions : 0;
  177. Flags |= m_bWaveOps ? hlsl::ShaderFeatureInfo_WaveOps : 0;
  178. Flags |= m_bInt64Ops ? hlsl::ShaderFeatureInfo_Int64Ops : 0;
  179. Flags |= m_bROVS ? hlsl::ShaderFeatureInfo_ROVs : 0;
  180. Flags |= m_bViewportAndRTArrayIndex ? hlsl::ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer : 0;
  181. Flags |= m_bInnerCoverage ? hlsl::ShaderFeatureInfo_InnerCoverage : 0;
  182. Flags |= m_bStencilRef ? hlsl::ShaderFeatureInfo_StencilRef : 0;
  183. Flags |= m_bTiledResources ? hlsl::ShaderFeatureInfo_TiledResources : 0;
  184. Flags |= m_bEnableMSAD ? hlsl::ShaderFeatureInfo_11_1_ShaderExtensions : 0;
  185. Flags |= m_bCSRawAndStructuredViaShader4X ? hlsl::ShaderFeatureInfo_ComputeShadersPlusRawAndStructuredBuffersViaShader4X : 0;
  186. Flags |= m_UAVsAtEveryStage ? hlsl::ShaderFeatureInfo_UAVsAtEveryStage : 0;
  187. Flags |= m_b64UAVs ? hlsl::ShaderFeatureInfo_64UAVs : 0;
  188. Flags |= m_bLevel9ComparisonFiltering ? hlsl::ShaderFeatureInfo_LEVEL9ComparisonFiltering : 0;
  189. Flags |= m_bUAVLoadAdditionalFormats ? hlsl::ShaderFeatureInfo_TypedUAVLoadAdditionalFormats : 0;
  190. Flags |= m_bViewID ? hlsl::ShaderFeatureInfo_ViewID : 0;
  191. return Flags;
  192. }
  193. uint64_t DxilModule::ShaderFlags::GetShaderFlagsRaw() const {
  194. union Cast {
  195. Cast(const DxilModule::ShaderFlags &flags) {
  196. shaderFlags = flags;
  197. }
  198. DxilModule::ShaderFlags shaderFlags;
  199. uint64_t rawData;
  200. };
  201. static_assert(sizeof(uint64_t) == sizeof(DxilModule::ShaderFlags),
  202. "size must match to make sure no undefined bits when cast");
  203. Cast rawCast(*this);
  204. return rawCast.rawData;
  205. }
  206. void DxilModule::ShaderFlags::SetShaderFlagsRaw(uint64_t data) {
  207. union Cast {
  208. Cast(uint64_t data) {
  209. rawData = data;
  210. }
  211. DxilModule::ShaderFlags shaderFlags;
  212. uint64_t rawData;
  213. };
  214. Cast rawCast(data);
  215. *this = rawCast.shaderFlags;
  216. }
  217. unsigned DxilModule::GetGlobalFlags() const {
  218. unsigned Flags = m_ShaderFlags.GetGlobalFlags();
  219. return Flags;
  220. }
  221. void DxilModule::CollectShaderFlags(ShaderFlags &Flags) {
  222. bool hasDouble = false;
  223. // ddiv dfma drcp d2i d2u i2d u2d.
  224. // fma has dxil op. Others should check IR instruction div/cast.
  225. bool hasDoubleExtension = false;
  226. bool has64Int = false;
  227. bool has16FloatInt = false;
  228. bool hasWaveOps = false;
  229. bool hasCheckAccessFully = false;
  230. bool hasMSAD = false;
  231. bool hasMulticomponentUAVLoads = false;
  232. bool hasInnerCoverage = false;
  233. bool hasViewID = false;
  234. Type *int16Ty = Type::getInt16Ty(GetCtx());
  235. Type *int64Ty = Type::getInt64Ty(GetCtx());
  236. for (Function &F : GetModule()->functions()) {
  237. for (BasicBlock &BB : F.getBasicBlockList()) {
  238. for (Instruction &I : BB.getInstList()) {
  239. // Skip none dxil function call.
  240. if (CallInst *CI = dyn_cast<CallInst>(&I)) {
  241. if (!OP::IsDxilOpFunc(CI->getCalledFunction()))
  242. continue;
  243. }
  244. Type *Ty = I.getType();
  245. bool isDouble = Ty->isDoubleTy();
  246. bool isHalf = Ty->isHalfTy();
  247. bool isInt16 = Ty == int16Ty;
  248. bool isInt64 = Ty == int64Ty;
  249. if (isa<ExtractElementInst>(&I) ||
  250. isa<InsertElementInst>(&I))
  251. continue;
  252. for (Value *operand : I.operands()) {
  253. Type *Ty = operand->getType();
  254. isDouble |= Ty->isDoubleTy();
  255. isHalf |= Ty->isHalfTy();
  256. isInt16 |= Ty == int16Ty;
  257. isInt64 |= Ty == int64Ty;
  258. }
  259. if (isDouble) {
  260. hasDouble = true;
  261. switch (I.getOpcode()) {
  262. case Instruction::FDiv:
  263. case Instruction::UIToFP:
  264. case Instruction::SIToFP:
  265. case Instruction::FPToUI:
  266. case Instruction::FPToSI:
  267. hasDoubleExtension = true;
  268. break;
  269. }
  270. }
  271. has16FloatInt |= isHalf;
  272. has16FloatInt |= isInt16;
  273. has64Int |= isInt64;
  274. if (CallInst *CI = dyn_cast<CallInst>(&I)) {
  275. if (!OP::IsDxilOpFunc(CI->getCalledFunction()))
  276. continue;
  277. Value *opcodeArg = CI->getArgOperand(DXIL::OperandIndex::kOpcodeIdx);
  278. ConstantInt *opcodeConst = dyn_cast<ConstantInt>(opcodeArg);
  279. DXASSERT(opcodeConst, "DXIL opcode arg must be immediate");
  280. unsigned opcode = opcodeConst->getLimitedValue();
  281. DXASSERT(opcode < static_cast<unsigned>(DXIL::OpCode::NumOpCodes),
  282. "invalid DXIL opcode");
  283. DXIL::OpCode dxilOp = static_cast<DXIL::OpCode>(opcode);
  284. if (hlsl::OP::IsDxilOpWave(dxilOp))
  285. hasWaveOps = true;
  286. switch (dxilOp) {
  287. case DXIL::OpCode::CheckAccessFullyMapped:
  288. hasCheckAccessFully = true;
  289. break;
  290. case DXIL::OpCode::Msad:
  291. hasMSAD = true;
  292. break;
  293. case DXIL::OpCode::BufferLoad:
  294. case DXIL::OpCode::TextureLoad: {
  295. Value *resHandle = CI->getArgOperand(DXIL::OperandIndex::kBufferStoreHandleOpIdx);
  296. CallInst *handleCall = cast<CallInst>(resHandle);
  297. if (ConstantInt *resClassArg =
  298. dyn_cast<ConstantInt>(handleCall->getArgOperand(
  299. DXIL::OperandIndex::kCreateHandleResClassOpIdx))) {
  300. DXIL::ResourceClass resClass = static_cast<DXIL::ResourceClass>(
  301. resClassArg->getLimitedValue());
  302. if (resClass == DXIL::ResourceClass::UAV) {
  303. // For DXIL, all uav load is multi component load.
  304. hasMulticomponentUAVLoads = true;
  305. }
  306. } else if (PHINode *resClassPhi = dyn_cast<
  307. PHINode>(handleCall->getArgOperand(
  308. DXIL::OperandIndex::kCreateHandleResClassOpIdx))) {
  309. unsigned numOperands = resClassPhi->getNumOperands();
  310. for (unsigned i = 0; i < numOperands; i++) {
  311. if (ConstantInt *resClassArg = dyn_cast<ConstantInt>(
  312. resClassPhi->getIncomingValue(i))) {
  313. DXIL::ResourceClass resClass =
  314. static_cast<DXIL::ResourceClass>(
  315. resClassArg->getLimitedValue());
  316. if (resClass == DXIL::ResourceClass::UAV) {
  317. // For DXIL, all uav load is multi component load.
  318. hasMulticomponentUAVLoads = true;
  319. break;
  320. }
  321. }
  322. }
  323. }
  324. } break;
  325. case DXIL::OpCode::Fma:
  326. hasDoubleExtension |= isDouble;
  327. break;
  328. case DXIL::OpCode::InnerCoverage:
  329. hasInnerCoverage = true;
  330. break;
  331. case DXIL::OpCode::ViewID:
  332. hasViewID = true;
  333. break;
  334. default:
  335. // Normal opcodes.
  336. break;
  337. }
  338. }
  339. }
  340. }
  341. }
  342. Flags.SetEnableDoublePrecision(hasDouble);
  343. Flags.SetInt64Ops(has64Int);
  344. Flags.SetEnableMinPrecision(has16FloatInt);
  345. Flags.SetEnableDoubleExtensions(hasDoubleExtension);
  346. Flags.SetWaveOps(hasWaveOps);
  347. Flags.SetTiledResources(hasCheckAccessFully);
  348. Flags.SetEnableMSAD(hasMSAD);
  349. Flags.SetUAVLoadAdditionalFormats(hasMulticomponentUAVLoads);
  350. Flags.SetViewID(hasViewID);
  351. const ShaderModel *SM = GetShaderModel();
  352. if (SM->IsPS()) {
  353. bool hasStencilRef = false;
  354. DxilSignature &outS = GetOutputSignature();
  355. for (auto &&E : outS.GetElements()) {
  356. if (E->GetKind() == Semantic::Kind::StencilRef) {
  357. hasStencilRef = true;
  358. } else if (E->GetKind() == Semantic::Kind::InnerCoverage) {
  359. hasInnerCoverage = true;
  360. }
  361. }
  362. Flags.SetStencilRef(hasStencilRef);
  363. Flags.SetInnerCoverage(hasInnerCoverage);
  364. }
  365. bool checkInputRTArrayIndex =
  366. SM->IsGS() || SM->IsDS() || SM->IsHS() || SM->IsPS();
  367. if (checkInputRTArrayIndex) {
  368. bool hasViewportArrayIndex = false;
  369. bool hasRenderTargetArrayIndex = false;
  370. DxilSignature &inS = GetInputSignature();
  371. for (auto &E : inS.GetElements()) {
  372. if (E->GetKind() == Semantic::Kind::ViewPortArrayIndex) {
  373. hasViewportArrayIndex = true;
  374. } else if (E->GetKind() == Semantic::Kind::RenderTargetArrayIndex) {
  375. hasRenderTargetArrayIndex = true;
  376. }
  377. }
  378. Flags.SetViewportAndRTArrayIndex(hasViewportArrayIndex |
  379. hasRenderTargetArrayIndex);
  380. }
  381. bool checkOutputRTArrayIndex =
  382. SM->IsVS() || SM->IsDS() || SM->IsHS() || SM->IsPS();
  383. if (checkOutputRTArrayIndex) {
  384. bool hasViewportArrayIndex = false;
  385. bool hasRenderTargetArrayIndex = false;
  386. DxilSignature &outS = GetOutputSignature();
  387. for (auto &E : outS.GetElements()) {
  388. if (E->GetKind() == Semantic::Kind::ViewPortArrayIndex) {
  389. hasViewportArrayIndex = true;
  390. } else if (E->GetKind() == Semantic::Kind::RenderTargetArrayIndex) {
  391. hasRenderTargetArrayIndex = true;
  392. }
  393. }
  394. Flags.SetViewportAndRTArrayIndex(hasViewportArrayIndex |
  395. hasRenderTargetArrayIndex);
  396. }
  397. unsigned NumUAVs = m_UAVs.size();
  398. const unsigned kSmallUAVCount = 8;
  399. if (NumUAVs > kSmallUAVCount)
  400. Flags.Set64UAVs(true);
  401. if (NumUAVs && !(SM->IsCS() || SM->IsPS()))
  402. Flags.SetUAVsAtEveryStage(true);
  403. bool hasRawAndStructuredBuffer = false;
  404. for (auto &UAV : m_UAVs) {
  405. if (UAV->IsROV())
  406. Flags.SetROVs(true);
  407. switch (UAV->GetKind()) {
  408. case DXIL::ResourceKind::RawBuffer:
  409. case DXIL::ResourceKind::StructuredBuffer:
  410. hasRawAndStructuredBuffer = true;
  411. break;
  412. default:
  413. // Not raw/structured.
  414. break;
  415. }
  416. }
  417. for (auto &SRV : m_SRVs) {
  418. switch (SRV->GetKind()) {
  419. case DXIL::ResourceKind::RawBuffer:
  420. case DXIL::ResourceKind::StructuredBuffer:
  421. hasRawAndStructuredBuffer = true;
  422. break;
  423. default:
  424. // Not raw/structured.
  425. break;
  426. }
  427. }
  428. Flags.SetEnableRawAndStructuredBuffers(hasRawAndStructuredBuffer);
  429. bool hasCSRawAndStructuredViaShader4X =
  430. hasRawAndStructuredBuffer && m_pSM->GetMajor() == 4 && m_pSM->IsCS();
  431. Flags.SetCSRawAndStructuredViaShader4X(hasCSRawAndStructuredViaShader4X);
  432. }
  433. void DxilModule::CollectShaderFlags() {
  434. CollectShaderFlags(m_ShaderFlags);
  435. }
  436. uint64_t DxilModule::ShaderFlags::GetShaderFlagsRawForCollection() {
  437. // This should be all the flags that can be set by DxilModule::CollectShaderFlags.
  438. ShaderFlags Flags;
  439. Flags.SetEnableDoublePrecision(true);
  440. Flags.SetInt64Ops(true);
  441. Flags.SetEnableMinPrecision(true);
  442. Flags.SetEnableDoubleExtensions(true);
  443. Flags.SetWaveOps(true);
  444. Flags.SetTiledResources(true);
  445. Flags.SetEnableMSAD(true);
  446. Flags.SetUAVLoadAdditionalFormats(true);
  447. Flags.SetStencilRef(true);
  448. Flags.SetInnerCoverage(true);
  449. Flags.SetViewportAndRTArrayIndex(true);
  450. Flags.Set64UAVs(true);
  451. Flags.SetUAVsAtEveryStage(true);
  452. Flags.SetEnableRawAndStructuredBuffers(true);
  453. Flags.SetCSRawAndStructuredViaShader4X(true);
  454. Flags.SetViewID(true);
  455. return Flags.GetShaderFlagsRaw();
  456. }
  457. DXIL::InputPrimitive DxilModule::GetInputPrimitive() const {
  458. return m_InputPrimitive;
  459. }
  460. void DxilModule::SetInputPrimitive(DXIL::InputPrimitive IP) {
  461. DXASSERT_NOMSG(m_InputPrimitive == DXIL::InputPrimitive::Undefined);
  462. DXASSERT_NOMSG(DXIL::InputPrimitive::Undefined < IP && IP < DXIL::InputPrimitive::LastEntry);
  463. m_InputPrimitive = IP;
  464. }
  465. unsigned DxilModule::GetMaxVertexCount() const {
  466. DXASSERT_NOMSG(m_MaxVertexCount != 0);
  467. return m_MaxVertexCount;
  468. }
  469. void DxilModule::SetMaxVertexCount(unsigned Count) {
  470. DXASSERT_NOMSG(m_MaxVertexCount == 0);
  471. m_MaxVertexCount = Count;
  472. }
  473. DXIL::PrimitiveTopology DxilModule::GetStreamPrimitiveTopology() const {
  474. return m_StreamPrimitiveTopology;
  475. }
  476. void DxilModule::SetStreamPrimitiveTopology(DXIL::PrimitiveTopology Topology) {
  477. m_StreamPrimitiveTopology = Topology;
  478. }
  479. bool DxilModule::HasMultipleOutputStreams() const {
  480. if (!m_pSM->IsGS()) {
  481. return false;
  482. } else {
  483. unsigned NumStreams = (m_ActiveStreamMask & 0x1) +
  484. ((m_ActiveStreamMask & 0x2) >> 1) +
  485. ((m_ActiveStreamMask & 0x4) >> 2) +
  486. ((m_ActiveStreamMask & 0x8) >> 3);
  487. DXASSERT_NOMSG(NumStreams <= DXIL::kNumOutputStreams);
  488. return NumStreams > 1;
  489. }
  490. }
  491. unsigned DxilModule::GetOutputStream() const {
  492. if (!m_pSM->IsGS()) {
  493. return 0;
  494. } else {
  495. DXASSERT_NOMSG(!HasMultipleOutputStreams());
  496. switch (m_ActiveStreamMask) {
  497. case 0x1: return 0;
  498. case 0x2: return 1;
  499. case 0x4: return 2;
  500. case 0x8: return 3;
  501. default: DXASSERT_NOMSG(false);
  502. }
  503. return (unsigned)(-1);
  504. }
  505. }
  506. unsigned DxilModule::GetGSInstanceCount() const {
  507. return m_NumGSInstances;
  508. }
  509. void DxilModule::SetGSInstanceCount(unsigned Count) {
  510. m_NumGSInstances = Count;
  511. }
  512. bool DxilModule::IsStreamActive(unsigned Stream) const {
  513. return (m_ActiveStreamMask & (1<<Stream)) != 0;
  514. }
  515. void DxilModule::SetStreamActive(unsigned Stream, bool bActive) {
  516. if (bActive) {
  517. m_ActiveStreamMask |= (1<<Stream);
  518. } else {
  519. m_ActiveStreamMask &= ~(1<<Stream);
  520. }
  521. }
  522. void DxilModule::SetActiveStreamMask(unsigned Mask) {
  523. m_ActiveStreamMask = Mask;
  524. }
  525. unsigned DxilModule::GetActiveStreamMask() const {
  526. return m_ActiveStreamMask;
  527. }
  528. unsigned DxilModule::GetInputControlPointCount() const {
  529. return m_InputControlPointCount;
  530. }
  531. void DxilModule::SetInputControlPointCount(unsigned NumICPs) {
  532. m_InputControlPointCount = NumICPs;
  533. }
  534. DXIL::TessellatorDomain DxilModule::GetTessellatorDomain() const {
  535. return m_TessellatorDomain;
  536. }
  537. void DxilModule::SetTessellatorDomain(DXIL::TessellatorDomain TessDomain) {
  538. m_TessellatorDomain = TessDomain;
  539. }
  540. unsigned DxilModule::GetOutputControlPointCount() const {
  541. return m_OutputControlPointCount;
  542. }
  543. void DxilModule::SetOutputControlPointCount(unsigned NumOCPs) {
  544. m_OutputControlPointCount = NumOCPs;
  545. }
  546. DXIL::TessellatorPartitioning DxilModule::GetTessellatorPartitioning() const {
  547. return m_TessellatorPartitioning;
  548. }
  549. void DxilModule::SetTessellatorPartitioning(DXIL::TessellatorPartitioning TessPartitioning) {
  550. m_TessellatorPartitioning = TessPartitioning;
  551. }
  552. DXIL::TessellatorOutputPrimitive DxilModule::GetTessellatorOutputPrimitive() const {
  553. return m_TessellatorOutputPrimitive;
  554. }
  555. void DxilModule::SetTessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive TessOutputPrimitive) {
  556. m_TessellatorOutputPrimitive = TessOutputPrimitive;
  557. }
  558. float DxilModule::GetMaxTessellationFactor() const {
  559. return m_MaxTessellationFactor;
  560. }
  561. void DxilModule::SetMaxTessellationFactor(float MaxTessellationFactor) {
  562. m_MaxTessellationFactor = MaxTessellationFactor;
  563. }
  564. template<typename T> unsigned
  565. DxilModule::AddResource(vector<unique_ptr<T> > &Vec, unique_ptr<T> pRes) {
  566. DXASSERT_NOMSG((unsigned)Vec.size() < UINT_MAX);
  567. unsigned Id = (unsigned)Vec.size();
  568. Vec.emplace_back(std::move(pRes));
  569. return Id;
  570. }
  571. unsigned DxilModule::AddCBuffer(unique_ptr<DxilCBuffer> pCB) {
  572. return AddResource<DxilCBuffer>(m_CBuffers, std::move(pCB));
  573. }
  574. DxilCBuffer &DxilModule::GetCBuffer(unsigned idx) {
  575. return *m_CBuffers[idx];
  576. }
  577. const DxilCBuffer &DxilModule::GetCBuffer(unsigned idx) const {
  578. return *m_CBuffers[idx];
  579. }
  580. const vector<unique_ptr<DxilCBuffer> > &DxilModule::GetCBuffers() const {
  581. return m_CBuffers;
  582. }
  583. unsigned DxilModule::AddSampler(unique_ptr<DxilSampler> pSampler) {
  584. return AddResource<DxilSampler>(m_Samplers, std::move(pSampler));
  585. }
  586. DxilSampler &DxilModule::GetSampler(unsigned idx) {
  587. return *m_Samplers[idx];
  588. }
  589. const DxilSampler &DxilModule::GetSampler(unsigned idx) const {
  590. return *m_Samplers[idx];
  591. }
  592. const vector<unique_ptr<DxilSampler> > &DxilModule::GetSamplers() const {
  593. return m_Samplers;
  594. }
  595. unsigned DxilModule::AddSRV(unique_ptr<DxilResource> pSRV) {
  596. return AddResource<DxilResource>(m_SRVs, std::move(pSRV));
  597. }
  598. DxilResource &DxilModule::GetSRV(unsigned idx) {
  599. return *m_SRVs[idx];
  600. }
  601. const DxilResource &DxilModule::GetSRV(unsigned idx) const {
  602. return *m_SRVs[idx];
  603. }
  604. const vector<unique_ptr<DxilResource> > &DxilModule::GetSRVs() const {
  605. return m_SRVs;
  606. }
  607. unsigned DxilModule::AddUAV(unique_ptr<DxilResource> pUAV) {
  608. return AddResource<DxilResource>(m_UAVs, std::move(pUAV));
  609. }
  610. DxilResource &DxilModule::GetUAV(unsigned idx) {
  611. return *m_UAVs[idx];
  612. }
  613. const DxilResource &DxilModule::GetUAV(unsigned idx) const {
  614. return *m_UAVs[idx];
  615. }
  616. const vector<unique_ptr<DxilResource> > &DxilModule::GetUAVs() const {
  617. return m_UAVs;
  618. }
  619. void DxilModule::LoadDxilResourceBaseFromMDNode(MDNode *MD, DxilResourceBase &R) {
  620. return m_pMDHelper->LoadDxilResourceBaseFromMDNode(MD, R);
  621. }
  622. void DxilModule::LoadDxilResourceFromMDNode(llvm::MDNode *MD, DxilResource &R) {
  623. return m_pMDHelper->LoadDxilResourceFromMDNode(MD, R);
  624. }
  625. void DxilModule::LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S) {
  626. return m_pMDHelper->LoadDxilSamplerFromMDNode(MD, S);
  627. }
  628. template <typename TResource>
  629. static void RemoveResources(std::vector<std::unique_ptr<TResource>> &vec,
  630. std::unordered_set<unsigned> &immResID) {
  631. for (std::vector<std::unique_ptr<TResource>>::iterator p = vec.begin(); p != vec.end();) {
  632. std::vector<std::unique_ptr<TResource>>::iterator c = p++;
  633. if (immResID.count((*c)->GetID()) == 0) {
  634. p = vec.erase(c);
  635. }
  636. }
  637. }
  638. static void CollectUsedResource(Value *resID,
  639. std::unordered_set<Value *> &usedResID) {
  640. if (usedResID.count(resID) > 0)
  641. return;
  642. usedResID.insert(resID);
  643. if (ConstantInt *cResID = dyn_cast<ConstantInt>(resID)) {
  644. // Do nothing
  645. } else if (ZExtInst *ZEI = dyn_cast<ZExtInst>(resID)) {
  646. if (ZEI->getSrcTy()->isIntegerTy()) {
  647. IntegerType *ITy = cast<IntegerType>(ZEI->getSrcTy());
  648. if (ITy->getBitWidth() == 1) {
  649. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 0));
  650. usedResID.insert(ConstantInt::get(ZEI->getDestTy(), 1));
  651. }
  652. }
  653. } else if (SelectInst *SI = dyn_cast<SelectInst>(resID)) {
  654. CollectUsedResource(SI->getTrueValue(), usedResID);
  655. CollectUsedResource(SI->getFalseValue(), usedResID);
  656. } else {
  657. PHINode *Phi = cast<PHINode>(resID);
  658. for (Use &U : Phi->incoming_values()) {
  659. CollectUsedResource(U.get(), usedResID);
  660. }
  661. }
  662. }
  663. static void ConvertUsedResource(std::unordered_set<unsigned> &immResID,
  664. std::unordered_set<Value *> &usedResID) {
  665. for (Value *V : usedResID) {
  666. if (ConstantInt *cResID = dyn_cast<ConstantInt>(V)) {
  667. immResID.insert(cResID->getLimitedValue());
  668. }
  669. }
  670. }
  671. void DxilModule::RemoveFunction(llvm::Function *F) {
  672. DXASSERT_NOMSG(F != nullptr);
  673. if (m_pTypeSystem.get()->GetFunctionAnnotation(F))
  674. m_pTypeSystem.get()->EraseFunctionAnnotation(F);
  675. m_pOP->RemoveFunction(F);
  676. }
  677. void DxilModule::RemoveUnusedResources() {
  678. hlsl::OP *hlslOP = GetOP();
  679. Function *createHandleFunc = hlslOP->GetOpFunc(DXIL::OpCode::CreateHandle, Type::getVoidTy(GetCtx()));
  680. if (createHandleFunc->user_empty()) {
  681. m_CBuffers.clear();
  682. m_UAVs.clear();
  683. m_SRVs.clear();
  684. m_Samplers.clear();
  685. createHandleFunc->eraseFromParent();
  686. return;
  687. }
  688. std::unordered_set<Value *> usedUAVID;
  689. std::unordered_set<Value *> usedSRVID;
  690. std::unordered_set<Value *> usedSamplerID;
  691. std::unordered_set<Value *> usedCBufID;
  692. // Collect used ID.
  693. for (User *U : createHandleFunc->users()) {
  694. CallInst *CI = cast<CallInst>(U);
  695. Value *vResClass =
  696. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
  697. ConstantInt *cResClass = cast<ConstantInt>(vResClass);
  698. DXIL::ResourceClass resClass =
  699. static_cast<DXIL::ResourceClass>(cResClass->getLimitedValue());
  700. // Skip unused resource handle.
  701. if (CI->user_empty())
  702. continue;
  703. Value *resID =
  704. CI->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
  705. switch (resClass) {
  706. case DXIL::ResourceClass::CBuffer:
  707. CollectUsedResource(resID, usedCBufID);
  708. break;
  709. case DXIL::ResourceClass::Sampler:
  710. CollectUsedResource(resID, usedSamplerID);
  711. break;
  712. case DXIL::ResourceClass::SRV:
  713. CollectUsedResource(resID, usedSRVID);
  714. break;
  715. case DXIL::ResourceClass::UAV:
  716. CollectUsedResource(resID, usedUAVID);
  717. break;
  718. default:
  719. DXASSERT(0, "invalid res class");
  720. break;
  721. }
  722. }
  723. std::unordered_set<unsigned> immUAVID;
  724. std::unordered_set<unsigned> immSRVID;
  725. std::unordered_set<unsigned> immSamplerID;
  726. std::unordered_set<unsigned> immCBufID;
  727. ConvertUsedResource(immUAVID, usedUAVID);
  728. RemoveResources(m_UAVs, immUAVID);
  729. ConvertUsedResource(immSRVID, usedSRVID);
  730. ConvertUsedResource(immSamplerID, usedSamplerID);
  731. ConvertUsedResource(immCBufID, usedCBufID);
  732. RemoveResources(m_SRVs, immSRVID);
  733. RemoveResources(m_Samplers, immSamplerID);
  734. RemoveResources(m_CBuffers, immCBufID);
  735. }
  736. DxilSignature &DxilModule::GetInputSignature() {
  737. return *m_InputSignature;
  738. }
  739. const DxilSignature &DxilModule::GetInputSignature() const {
  740. return *m_InputSignature;
  741. }
  742. DxilSignature &DxilModule::GetOutputSignature() {
  743. return *m_OutputSignature;
  744. }
  745. const DxilSignature &DxilModule::GetOutputSignature() const {
  746. return *m_OutputSignature;
  747. }
  748. DxilSignature &DxilModule::GetPatchConstantSignature() {
  749. return *m_PatchConstantSignature;
  750. }
  751. const DxilSignature &DxilModule::GetPatchConstantSignature() const {
  752. return *m_PatchConstantSignature;
  753. }
  754. const RootSignatureHandle &DxilModule::GetRootSignature() const {
  755. return *m_RootSignature;
  756. }
  757. void DxilModule::StripRootSignatureFromMetadata() {
  758. NamedMDNode *pRootSignatureNamedMD = GetModule()->getNamedMetadata(DxilMDHelper::kDxilRootSignatureMDName);
  759. if (pRootSignatureNamedMD) {
  760. GetModule()->eraseNamedMetadata(pRootSignatureNamedMD);
  761. }
  762. }
  763. void DxilModule::ResetInputSignature(DxilSignature *pValue) {
  764. m_InputSignature.reset(pValue);
  765. }
  766. void DxilModule::ResetOutputSignature(DxilSignature *pValue) {
  767. m_OutputSignature.reset(pValue);
  768. }
  769. void DxilModule::ResetPatchConstantSignature(DxilSignature *pValue) {
  770. m_PatchConstantSignature.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. void DxilModule::ResetTypeSystem(DxilTypeSystem *pValue) {
  782. m_pTypeSystem.reset(pValue);
  783. }
  784. void DxilModule::ResetOP(hlsl::OP *hlslOP) {
  785. m_pOP.reset(hlslOP);
  786. }
  787. void DxilModule::EmitLLVMUsed() {
  788. if (m_LLVMUsed.empty())
  789. return;
  790. vector<llvm::Constant*> GVs;
  791. Type *pI8PtrType = Type::getInt8PtrTy(m_Ctx, DXIL::kDefaultAddrSpace);
  792. GVs.resize(m_LLVMUsed.size());
  793. for (size_t i = 0, e = m_LLVMUsed.size(); i != e; i++) {
  794. Constant *pConst = cast<Constant>(&*m_LLVMUsed[i]);
  795. PointerType * pPtrType = dyn_cast<PointerType>(pConst->getType());
  796. if (pPtrType->getPointerAddressSpace() != DXIL::kDefaultAddrSpace) {
  797. // Cast pointer to addrspace 0, as LLVMUsed elements must have the same type.
  798. GVs[i] = ConstantExpr::getAddrSpaceCast(pConst, pI8PtrType);
  799. } else {
  800. GVs[i] = ConstantExpr::getPointerCast(pConst, pI8PtrType);
  801. }
  802. }
  803. ArrayType *pATy = ArrayType::get(pI8PtrType, GVs.size());
  804. StringRef llvmUsedName = "llvm.used";
  805. if (GlobalVariable *oldGV = m_pModule->getGlobalVariable(llvmUsedName)) {
  806. oldGV->eraseFromParent();
  807. }
  808. GlobalVariable *pGV = new GlobalVariable(*m_pModule, pATy, false,
  809. GlobalValue::AppendingLinkage,
  810. ConstantArray::get(pATy, GVs),
  811. llvmUsedName);
  812. pGV->setSection("llvm.metadata");
  813. }
  814. vector<GlobalVariable* > &DxilModule::GetLLVMUsed() {
  815. return m_LLVMUsed;
  816. }
  817. // DXIL metadata serialization/deserialization.
  818. void DxilModule::EmitDxilMetadata() {
  819. m_pMDHelper->EmitDxilVersion(m_DxilMajor, m_DxilMinor);
  820. m_pMDHelper->EmitDxilShaderModel(m_pSM);
  821. MDTuple *pMDSignatures = m_pMDHelper->EmitDxilSignatures(*m_InputSignature,
  822. *m_OutputSignature,
  823. *m_PatchConstantSignature);
  824. MDTuple *pMDResources = EmitDxilResources();
  825. MDTuple *pMDProperties = EmitDxilShaderProperties();
  826. m_pMDHelper->EmitDxilTypeSystem(GetTypeSystem(), m_LLVMUsed);
  827. if (!m_pSM->IsCS()) {
  828. m_pMDHelper->EmitDxilViewIdState(GetViewIdState());
  829. }
  830. EmitLLVMUsed();
  831. MDTuple *pEntry = m_pMDHelper->EmitDxilEntryPointTuple(GetEntryFunction(), m_EntryName, pMDSignatures, pMDResources, pMDProperties);
  832. vector<MDNode *> Entries;
  833. Entries.emplace_back(pEntry);
  834. m_pMDHelper->EmitDxilEntryPoints(Entries);
  835. if (!m_RootSignature->IsEmpty()) {
  836. m_pMDHelper->EmitRootSignature(*m_RootSignature.get());
  837. }
  838. }
  839. bool DxilModule::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
  840. return DxilMDHelper::IsKnownNamedMetaData(Node);
  841. }
  842. void DxilModule::LoadDxilMetadata() {
  843. m_pMDHelper->LoadDxilVersion(m_DxilMajor, m_DxilMinor);
  844. const ShaderModel *loadedModule;
  845. m_pMDHelper->LoadDxilShaderModel(loadedModule);
  846. SetShaderModel(loadedModule);
  847. DXASSERT(m_InputSignature != nullptr, "else SetShaderModel didn't create input signature");
  848. const llvm::NamedMDNode *pEntries = m_pMDHelper->GetDxilEntryPoints();
  849. IFTBOOL(pEntries->getNumOperands() == 1, DXC_E_INCORRECT_DXIL_METADATA);
  850. Function *pEntryFunc;
  851. string EntryName;
  852. const llvm::MDOperand *pSignatures, *pResources, *pProperties;
  853. m_pMDHelper->GetDxilEntryPoint(pEntries->getOperand(0), pEntryFunc, EntryName, pSignatures, pResources, pProperties);
  854. SetEntryFunction(pEntryFunc);
  855. SetEntryFunctionName(EntryName);
  856. m_pMDHelper->LoadDxilSignatures(*pSignatures, *m_InputSignature,
  857. *m_OutputSignature, *m_PatchConstantSignature);
  858. LoadDxilResources(*pResources);
  859. LoadDxilShaderProperties(*pProperties);
  860. m_pMDHelper->LoadDxilTypeSystem(*m_pTypeSystem.get());
  861. m_pMDHelper->LoadRootSignature(*m_RootSignature.get());
  862. m_pMDHelper->LoadDxilViewIdState(*m_pViewIdState.get());
  863. }
  864. MDTuple *DxilModule::EmitDxilResources() {
  865. // Emit SRV records.
  866. MDTuple *pTupleSRVs = nullptr;
  867. if (!m_SRVs.empty()) {
  868. vector<Metadata *> MDVals;
  869. for (size_t i = 0; i < m_SRVs.size(); i++) {
  870. MDVals.emplace_back(m_pMDHelper->EmitDxilSRV(*m_SRVs[i]));
  871. }
  872. pTupleSRVs = MDNode::get(m_Ctx, MDVals);
  873. }
  874. // Emit UAV records.
  875. MDTuple *pTupleUAVs = nullptr;
  876. if (!m_UAVs.empty()) {
  877. vector<Metadata *> MDVals;
  878. for (size_t i = 0; i < m_UAVs.size(); i++) {
  879. MDVals.emplace_back(m_pMDHelper->EmitDxilUAV(*m_UAVs[i]));
  880. }
  881. pTupleUAVs = MDNode::get(m_Ctx, MDVals);
  882. }
  883. // Emit CBuffer records.
  884. MDTuple *pTupleCBuffers = nullptr;
  885. if (!m_CBuffers.empty()) {
  886. vector<Metadata *> MDVals;
  887. for (size_t i = 0; i < m_CBuffers.size(); i++) {
  888. MDVals.emplace_back(m_pMDHelper->EmitDxilCBuffer(*m_CBuffers[i]));
  889. }
  890. pTupleCBuffers = MDNode::get(m_Ctx, MDVals);
  891. }
  892. // Emit Sampler records.
  893. MDTuple *pTupleSamplers = nullptr;
  894. if (!m_Samplers.empty()) {
  895. vector<Metadata *> MDVals;
  896. for (size_t i = 0; i < m_Samplers.size(); i++) {
  897. MDVals.emplace_back(m_pMDHelper->EmitDxilSampler(*m_Samplers[i]));
  898. }
  899. pTupleSamplers = MDNode::get(m_Ctx, MDVals);
  900. }
  901. if (pTupleSRVs != nullptr || pTupleUAVs != nullptr || pTupleCBuffers != nullptr || pTupleSamplers != nullptr) {
  902. return m_pMDHelper->EmitDxilResourceTuple(pTupleSRVs, pTupleUAVs, pTupleCBuffers, pTupleSamplers);
  903. } else {
  904. return nullptr;
  905. }
  906. }
  907. void DxilModule::LoadDxilResources(const llvm::MDOperand &MDO) {
  908. if (MDO.get() == nullptr)
  909. return;
  910. const llvm::MDTuple *pSRVs, *pUAVs, *pCBuffers, *pSamplers;
  911. m_pMDHelper->GetDxilResources(MDO, pSRVs, pUAVs, pCBuffers, pSamplers);
  912. // Load SRV records.
  913. if (pSRVs != nullptr) {
  914. for (unsigned i = 0; i < pSRVs->getNumOperands(); i++) {
  915. unique_ptr<DxilResource> pSRV(new DxilResource);
  916. m_pMDHelper->LoadDxilSRV(pSRVs->getOperand(i), *pSRV);
  917. AddSRV(std::move(pSRV));
  918. }
  919. }
  920. // Load UAV records.
  921. if (pUAVs != nullptr) {
  922. for (unsigned i = 0; i < pUAVs->getNumOperands(); i++) {
  923. unique_ptr<DxilResource> pUAV(new DxilResource);
  924. m_pMDHelper->LoadDxilUAV(pUAVs->getOperand(i), *pUAV);
  925. AddUAV(std::move(pUAV));
  926. }
  927. }
  928. // Load CBuffer records.
  929. if (pCBuffers != nullptr) {
  930. for (unsigned i = 0; i < pCBuffers->getNumOperands(); i++) {
  931. unique_ptr<DxilCBuffer> pCB(new DxilCBuffer);
  932. m_pMDHelper->LoadDxilCBuffer(pCBuffers->getOperand(i), *pCB);
  933. AddCBuffer(std::move(pCB));
  934. }
  935. }
  936. // Load Sampler records.
  937. if (pSamplers != nullptr) {
  938. for (unsigned i = 0; i < pSamplers->getNumOperands(); i++) {
  939. unique_ptr<DxilSampler> pSampler(new DxilSampler);
  940. m_pMDHelper->LoadDxilSampler(pSamplers->getOperand(i), *pSampler);
  941. AddSampler(std::move(pSampler));
  942. }
  943. }
  944. }
  945. MDTuple *DxilModule::EmitDxilShaderProperties() {
  946. vector<Metadata *> MDVals;
  947. // DXIL shader flags.
  948. uint64_t Flags = m_ShaderFlags.GetShaderFlagsRaw();
  949. if (Flags != 0) {
  950. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilShaderFlagsTag));
  951. MDVals.emplace_back(m_pMDHelper->Uint64ToConstMD(Flags));
  952. }
  953. // Compute shader.
  954. if (m_pSM->IsCS()) {
  955. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilNumThreadsTag));
  956. vector<Metadata *> NumThreadVals;
  957. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[0]));
  958. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[1]));
  959. NumThreadVals.emplace_back(m_pMDHelper->Uint32ToConstMD(m_NumThreads[2]));
  960. MDVals.emplace_back(MDNode::get(m_Ctx, NumThreadVals));
  961. }
  962. // Geometry shader.
  963. if (m_pSM->IsGS()) {
  964. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilGSStateTag));
  965. MDTuple *pMDTuple = m_pMDHelper->EmitDxilGSState(m_InputPrimitive,
  966. m_MaxVertexCount,
  967. GetActiveStreamMask(),
  968. m_StreamPrimitiveTopology,
  969. m_NumGSInstances);
  970. MDVals.emplace_back(pMDTuple);
  971. }
  972. // Domain shader.
  973. if (m_pSM->IsDS()) {
  974. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilDSStateTag));
  975. MDTuple *pMDTuple = m_pMDHelper->EmitDxilDSState(m_TessellatorDomain,
  976. m_InputControlPointCount);
  977. MDVals.emplace_back(pMDTuple);
  978. }
  979. // Hull shader.
  980. if (m_pSM->IsHS()) {
  981. MDVals.emplace_back(m_pMDHelper->Uint32ToConstMD(DxilMDHelper::kDxilHSStateTag));
  982. MDTuple *pMDTuple = m_pMDHelper->EmitDxilHSState(m_pPatchConstantFunc,
  983. m_InputControlPointCount,
  984. m_OutputControlPointCount,
  985. m_TessellatorDomain,
  986. m_TessellatorPartitioning,
  987. m_TessellatorOutputPrimitive,
  988. m_MaxTessellationFactor);
  989. MDVals.emplace_back(pMDTuple);
  990. }
  991. if (!MDVals.empty())
  992. return MDNode::get(m_Ctx, MDVals);
  993. else
  994. return nullptr;
  995. }
  996. void DxilModule::LoadDxilShaderProperties(const MDOperand &MDO) {
  997. if (MDO.get() == nullptr)
  998. return;
  999. const MDTuple *pTupleMD = dyn_cast<MDTuple>(MDO.get());
  1000. IFTBOOL(pTupleMD != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1001. IFTBOOL((pTupleMD->getNumOperands() & 0x1) == 0, DXC_E_INCORRECT_DXIL_METADATA);
  1002. for (unsigned iNode = 0; iNode < pTupleMD->getNumOperands(); iNode += 2) {
  1003. unsigned Tag = DxilMDHelper::ConstMDToUint32(pTupleMD->getOperand(iNode));
  1004. const MDOperand &MDO = pTupleMD->getOperand(iNode + 1);
  1005. IFTBOOL(MDO.get() != nullptr, DXC_E_INCORRECT_DXIL_METADATA);
  1006. switch (Tag) {
  1007. case DxilMDHelper::kDxilShaderFlagsTag:
  1008. m_ShaderFlags.SetShaderFlagsRaw(DxilMDHelper::ConstMDToUint64(MDO));
  1009. break;
  1010. case DxilMDHelper::kDxilNumThreadsTag: {
  1011. MDNode *pNode = cast<MDNode>(MDO.get());
  1012. m_NumThreads[0] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(0));
  1013. m_NumThreads[1] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(1));
  1014. m_NumThreads[2] = DxilMDHelper::ConstMDToUint32(pNode->getOperand(2));
  1015. break;
  1016. }
  1017. case DxilMDHelper::kDxilGSStateTag: {
  1018. m_pMDHelper->LoadDxilGSState(MDO, m_InputPrimitive, m_MaxVertexCount, m_ActiveStreamMask,
  1019. m_StreamPrimitiveTopology, m_NumGSInstances);
  1020. break;
  1021. }
  1022. case DxilMDHelper::kDxilDSStateTag:
  1023. m_pMDHelper->LoadDxilDSState(MDO, m_TessellatorDomain, m_InputControlPointCount);
  1024. break;
  1025. case DxilMDHelper::kDxilHSStateTag:
  1026. m_pMDHelper->LoadDxilHSState(MDO,
  1027. m_pPatchConstantFunc,
  1028. m_InputControlPointCount,
  1029. m_OutputControlPointCount,
  1030. m_TessellatorDomain,
  1031. m_TessellatorPartitioning,
  1032. m_TessellatorOutputPrimitive,
  1033. m_MaxTessellationFactor);
  1034. break;
  1035. default:
  1036. DXASSERT(false, "Unknown extended shader properties tag");
  1037. break;
  1038. }
  1039. }
  1040. }
  1041. void DxilModule::StripDebugRelatedCode() {
  1042. // Remove all users of global resources.
  1043. for (GlobalVariable &GV : m_pModule->globals()) {
  1044. if (GV.hasInternalLinkage())
  1045. continue;
  1046. if (GV.getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace)
  1047. continue;
  1048. for (auto git = GV.user_begin(); git != GV.user_end();) {
  1049. User *U = *(git++);
  1050. // Try to remove load of GV.
  1051. if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
  1052. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1053. Instruction *LIUser = cast<Instruction>(*(it++));
  1054. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1055. Value *Ptr = SI->getPointerOperand();
  1056. SI->eraseFromParent();
  1057. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1058. if (Ptr->user_empty())
  1059. PtrInst->eraseFromParent();
  1060. }
  1061. }
  1062. }
  1063. if (LI->user_empty())
  1064. LI->eraseFromParent();
  1065. } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
  1066. for (auto GEPIt = GEP->user_begin(); GEPIt != GEP->user_end();) {
  1067. User *GEPU = *(GEPIt++);
  1068. // Try to remove load of GEP.
  1069. if (LoadInst *LI = dyn_cast<LoadInst>(GEPU)) {
  1070. for (auto it = LI->user_begin(); it != LI->user_end();) {
  1071. Instruction *LIUser = cast<Instruction>(*(it++));
  1072. if (StoreInst *SI = dyn_cast<StoreInst>(LIUser)) {
  1073. Value *Ptr = SI->getPointerOperand();
  1074. SI->eraseFromParent();
  1075. if (Instruction *PtrInst = dyn_cast<Instruction>(Ptr)) {
  1076. if (Ptr->user_empty())
  1077. PtrInst->eraseFromParent();
  1078. }
  1079. }
  1080. if (LI->user_empty())
  1081. LI->eraseFromParent();
  1082. }
  1083. }
  1084. }
  1085. if (GEP->user_empty())
  1086. GEP->eraseFromParent();
  1087. }
  1088. }
  1089. }
  1090. }
  1091. DebugInfoFinder &DxilModule::GetOrCreateDebugInfoFinder() {
  1092. if (m_pDebugInfoFinder == nullptr) {
  1093. m_pDebugInfoFinder = std::make_unique<llvm::DebugInfoFinder>();
  1094. m_pDebugInfoFinder->processModule(*m_pModule);
  1095. }
  1096. return *m_pDebugInfoFinder;
  1097. }
  1098. hlsl::DxilModule *hlsl::DxilModule::TryGetDxilModule(llvm::Module *pModule) {
  1099. LLVMContext &Ctx = pModule->getContext();
  1100. std::string diagStr;
  1101. raw_string_ostream diagStream(diagStr);
  1102. hlsl::DxilModule *pDxilModule = nullptr;
  1103. // TODO: add detail error in DxilMDHelper.
  1104. try {
  1105. pDxilModule = &pModule->GetOrCreateDxilModule();
  1106. } catch (const ::hlsl::Exception &hlslException) {
  1107. diagStream << "load dxil metadata failed -";
  1108. try {
  1109. const char *msg = hlslException.what();
  1110. if (msg == nullptr || *msg == '\0')
  1111. diagStream << " error code " << hlslException.hr << "\n";
  1112. else
  1113. diagStream << msg;
  1114. } catch (...) {
  1115. diagStream << " unable to retrieve error message.\n";
  1116. }
  1117. Ctx.diagnose(DxilErrorDiagnosticInfo(diagStream.str().c_str()));
  1118. } catch (...) {
  1119. Ctx.diagnose(DxilErrorDiagnosticInfo("load dxil metadata failed - unknown error.\n"));
  1120. }
  1121. return pDxilModule;
  1122. }
  1123. } // namespace hlsl
  1124. namespace llvm {
  1125. hlsl::DxilModule &Module::GetOrCreateDxilModule(bool skipInit) {
  1126. std::unique_ptr<hlsl::DxilModule> M;
  1127. if (!HasDxilModule()) {
  1128. M = std::make_unique<hlsl::DxilModule>(this);
  1129. if (!skipInit) {
  1130. M->LoadDxilMetadata();
  1131. }
  1132. SetDxilModule(M.release());
  1133. }
  1134. return GetDxilModule();
  1135. }
  1136. void Module::ResetDxilModule() {
  1137. if (HasDxilModule()) {
  1138. delete TheDxilModule;
  1139. TheDxilModule = nullptr;
  1140. }
  1141. }
  1142. }