dxcdisassembler.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // dxcdisassembler.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. // Implements Disassembler. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/Support/WinIncludes.h"
  12. #include "dxc/dxcapi.h"
  13. #include "dxc/Support/Global.h"
  14. #include "dxc/HLSL/DxilShaderModel.h"
  15. #include "dxc/HLSL/DxilModule.h"
  16. #include "dxc/HLSL/DxilResource.h"
  17. #include "dxc/HLSL/HLMatrixLowerHelper.h"
  18. #include "dxc/HLSL/DxilConstants.h"
  19. #include "dxc/HLSL/DxilOperations.h"
  20. #include "llvm/IR/DiagnosticInfo.h"
  21. #include "llvm/IR/DiagnosticPrinter.h"
  22. #include "llvm/IR/AssemblyAnnotationWriter.h"
  23. #include "llvm/Support/FormattedStream.h"
  24. #include "llvm/Support/Format.h"
  25. #include "dxc/HLSL/DxilPipelineStateValidation.h"
  26. #include "dxc/HLSL/DxilContainer.h"
  27. #include "dxc/HLSL/DxilUtil.h"
  28. #include "dxcutil.h"
  29. using namespace llvm;
  30. using namespace hlsl;
  31. namespace {
  32. // Disassemble helper functions.
  33. void PrintDiagnosticHandler(const DiagnosticInfo &DI, void *Context) {
  34. DiagnosticPrinter *printer = reinterpret_cast<DiagnosticPrinter *>(Context);
  35. DI.print(*printer);
  36. }
  37. template <typename T>
  38. const T *ByteOffset(LPCVOID p, uint32_t byteOffset) {
  39. return reinterpret_cast<const T *>((const uint8_t *)p + byteOffset);
  40. }
  41. bool SigElementHasStream(const DxilProgramSignatureElement &pSignature) {
  42. return pSignature.Stream != 0;
  43. }
  44. void PrintSignature(LPCSTR pName, const DxilProgramSignature *pSignature,
  45. bool bIsInput, raw_string_ostream &OS,
  46. StringRef comment) {
  47. OS << comment << "\n"
  48. << comment << " " << pName << " signature:\n"
  49. << comment << "\n"
  50. << comment
  51. << " Name Index Mask Register SysValue Format Used\n"
  52. << comment
  53. << " -------------------- ----- ------ -------- -------- ------- ------\n";
  54. if (pSignature->ParamCount == 0) {
  55. OS << comment << " no parameters\n";
  56. return;
  57. }
  58. const DxilProgramSignatureElement *pSigBegin =
  59. ByteOffset<DxilProgramSignatureElement>(pSignature,
  60. pSignature->ParamOffset);
  61. const DxilProgramSignatureElement *pSigEnd =
  62. pSigBegin + pSignature->ParamCount;
  63. bool bHasStreams = std::any_of(pSigBegin, pSigEnd, SigElementHasStream);
  64. for (const DxilProgramSignatureElement *pSig = pSigBegin; pSig != pSigEnd;
  65. ++pSig) {
  66. OS << comment << " ";
  67. const char *pSemanticName =
  68. ByteOffset<char>(pSignature, pSig->SemanticName);
  69. if (bHasStreams) {
  70. OS << "m" << pSig->Stream << ":";
  71. OS << left_justify(pSemanticName, 17);
  72. } else {
  73. OS << left_justify(pSemanticName, 20);
  74. }
  75. OS << ' ' << format("%5u", pSig->SemanticIndex);
  76. char Mask[4];
  77. memset(Mask, ' ', sizeof(Mask));
  78. if (pSig->Mask & DxilProgramSigMaskX)
  79. Mask[0] = 'x';
  80. if (pSig->Mask & DxilProgramSigMaskY)
  81. Mask[1] = 'y';
  82. if (pSig->Mask & DxilProgramSigMaskZ)
  83. Mask[2] = 'z';
  84. if (pSig->Mask & DxilProgramSigMaskW)
  85. Mask[3] = 'w';
  86. if (pSig->Register == -1) {
  87. OS << " N/A";
  88. if (!_stricmp(pSemanticName, "SV_Depth"))
  89. OS << " oDepth";
  90. else if (0 == _stricmp(pSemanticName, "SV_DepthGreaterEqual"))
  91. OS << " oDepthGE";
  92. else if (0 == _stricmp(pSemanticName, "SV_DepthLessEqual"))
  93. OS << " oDepthLE";
  94. else if (0 == _stricmp(pSemanticName, "SV_Coverage"))
  95. OS << " oMask";
  96. else if (0 == _stricmp(pSemanticName, "SV_StencilRef"))
  97. OS << " oStencilRef";
  98. else if (pSig->SystemValue == DxilProgramSigSemantic::PrimitiveID)
  99. OS << " primID";
  100. else
  101. OS << " special";
  102. } else {
  103. OS << " " << Mask[0] << Mask[1] << Mask[2] << Mask[3];
  104. OS << ' ' << format("%8u", pSig->Register);
  105. }
  106. LPCSTR pSysValue = "NONE";
  107. switch (pSig->SystemValue) {
  108. case DxilProgramSigSemantic::ClipDistance:
  109. pSysValue = "CLIPDST";
  110. break;
  111. case DxilProgramSigSemantic::CullDistance:
  112. pSysValue = "CULLDST";
  113. break;
  114. case DxilProgramSigSemantic::Position:
  115. pSysValue = "POS";
  116. break;
  117. case DxilProgramSigSemantic::RenderTargetArrayIndex:
  118. pSysValue = "RTINDEX";
  119. break;
  120. case DxilProgramSigSemantic::ViewPortArrayIndex:
  121. pSysValue = "VPINDEX";
  122. break;
  123. case DxilProgramSigSemantic::VertexID:
  124. pSysValue = "VERTID";
  125. break;
  126. case DxilProgramSigSemantic::PrimitiveID:
  127. pSysValue = "PRIMID";
  128. break;
  129. case DxilProgramSigSemantic::InstanceID:
  130. pSysValue = "INSTID";
  131. break;
  132. case DxilProgramSigSemantic::IsFrontFace:
  133. pSysValue = "FFACE";
  134. break;
  135. case DxilProgramSigSemantic::SampleIndex:
  136. pSysValue = "SAMPLE";
  137. break;
  138. case DxilProgramSigSemantic::Target:
  139. pSysValue = "TARGET";
  140. break;
  141. case DxilProgramSigSemantic::Depth:
  142. pSysValue = "DEPTH";
  143. break;
  144. case DxilProgramSigSemantic::DepthGE:
  145. pSysValue = "DEPTHGE";
  146. break;
  147. case DxilProgramSigSemantic::DepthLE:
  148. pSysValue = "DEPTHLE";
  149. break;
  150. case DxilProgramSigSemantic::Coverage:
  151. pSysValue = "COVERAGE";
  152. break;
  153. case DxilProgramSigSemantic::InnerCoverage:
  154. pSysValue = "INNERCOV";
  155. break;
  156. case DxilProgramSigSemantic::StencilRef:
  157. pSysValue = "STENCILREF";
  158. break;
  159. case DxilProgramSigSemantic::FinalQuadEdgeTessfactor:
  160. pSysValue = "QUADEDGE";
  161. break;
  162. case DxilProgramSigSemantic::FinalQuadInsideTessfactor:
  163. pSysValue = "QUADINT";
  164. break;
  165. case DxilProgramSigSemantic::FinalTriEdgeTessfactor:
  166. pSysValue = "TRIEDGE";
  167. break;
  168. case DxilProgramSigSemantic::FinalTriInsideTessfactor:
  169. pSysValue = "TRIINT";
  170. break;
  171. case DxilProgramSigSemantic::FinalLineDetailTessfactor:
  172. pSysValue = "LINEDET";
  173. break;
  174. case DxilProgramSigSemantic::FinalLineDensityTessfactor:
  175. pSysValue = "LINEDEN";
  176. break;
  177. case DxilProgramSigSemantic::Barycentrics:
  178. pSysValue = "BARYCEN";
  179. }
  180. OS << right_justify(pSysValue, 9);
  181. LPCSTR pFormat = "unknown";
  182. switch (pSig->CompType) {
  183. case DxilProgramSigCompType::Float32:
  184. pFormat = "float";
  185. break;
  186. case DxilProgramSigCompType::SInt32:
  187. pFormat = "int";
  188. break;
  189. case DxilProgramSigCompType::UInt32:
  190. pFormat = "uint";
  191. break;
  192. case DxilProgramSigCompType::UInt16:
  193. pFormat = "uint16";
  194. break;
  195. case DxilProgramSigCompType::SInt16:
  196. pFormat = "int16";
  197. break;
  198. case DxilProgramSigCompType::Float16:
  199. pFormat = "fp16";
  200. break;
  201. case DxilProgramSigCompType::UInt64:
  202. pFormat = "uint64";
  203. break;
  204. case DxilProgramSigCompType::SInt64:
  205. pFormat = "int64";
  206. break;
  207. case DxilProgramSigCompType::Float64:
  208. pFormat = "double";
  209. break;
  210. }
  211. OS << right_justify(pFormat, 8);
  212. memset(Mask, ' ', sizeof(Mask));
  213. BYTE rwMask = pSig->AlwaysReads_Mask;
  214. if (!bIsInput)
  215. rwMask = ~rwMask;
  216. if (rwMask & DxilProgramSigMaskX)
  217. Mask[0] = 'x';
  218. if (rwMask & DxilProgramSigMaskY)
  219. Mask[1] = 'y';
  220. if (rwMask & DxilProgramSigMaskZ)
  221. Mask[2] = 'z';
  222. if (rwMask & DxilProgramSigMaskW)
  223. Mask[3] = 'w';
  224. if (pSig->Register == -1)
  225. OS << (rwMask ? " YES" : " NO");
  226. else
  227. OS << " " << Mask[0] << Mask[1] << Mask[2] << Mask[3];
  228. OS << "\n";
  229. }
  230. OS << comment << "\n";
  231. }
  232. void PintCompMaskNameCompact(raw_string_ostream &OS, unsigned CompMask) {
  233. char Mask[5];
  234. memset(Mask, '\0', sizeof(Mask));
  235. unsigned idx = 0;
  236. if (CompMask & DxilProgramSigMaskX)
  237. Mask[idx++] = 'x';
  238. if (CompMask & DxilProgramSigMaskY)
  239. Mask[idx++] = 'y';
  240. if (CompMask & DxilProgramSigMaskZ)
  241. Mask[idx++] = 'z';
  242. if (CompMask & DxilProgramSigMaskW)
  243. Mask[idx++] = 'w';
  244. OS << right_justify(Mask, 4);
  245. }
  246. void PrintDxilSignature(LPCSTR pName, const DxilSignature &Signature,
  247. raw_string_ostream &OS, StringRef comment) {
  248. const std::vector<std::unique_ptr<DxilSignatureElement>> &sigElts =
  249. Signature.GetElements();
  250. if (sigElts.size() == 0)
  251. return;
  252. // TODO: Print all the data in DxilSignature.
  253. OS << comment << "\n"
  254. << comment << " " << pName << " signature:\n"
  255. << comment << "\n"
  256. << comment << " Name Index InterpMode DynIdx\n"
  257. << comment
  258. << " -------------------- ----- ---------------------- ------\n";
  259. for (auto &sigElt : sigElts) {
  260. OS << comment << " ";
  261. OS << left_justify(sigElt->GetName(), 20);
  262. auto &indexVec = sigElt->GetSemanticIndexVec();
  263. unsigned index = 0;
  264. if (!indexVec.empty()) {
  265. index = sigElt->GetSemanticIndexVec()[0];
  266. }
  267. OS << ' ' << format("%5u", index);
  268. sigElt->GetInterpolationMode()->GetName();
  269. OS << ' ' << right_justify(sigElt->GetInterpolationMode()->GetName(), 22);
  270. OS << " ";
  271. PintCompMaskNameCompact(OS, sigElt->GetDynIdxCompMask());
  272. OS << "\n";
  273. }
  274. }
  275. PCSTR g_pFeatureInfoNames[] = {
  276. "Double-precision floating point",
  277. "Raw and Structured buffers",
  278. "UAVs at every shader stage",
  279. "64 UAV slots",
  280. "Minimum-precision data types",
  281. "Double-precision extensions for 11.1",
  282. "Shader extensions for 11.1",
  283. "Comparison filtering for feature level 9",
  284. "Tiled resources",
  285. "PS Output Stencil Ref",
  286. "PS Inner Coverage",
  287. "Typed UAV Load Additional Formats",
  288. "Raster Ordered UAVs",
  289. "SV_RenderTargetArrayIndex or SV_ViewportArrayIndex from any shader "
  290. "feeding rasterizer",
  291. "Wave level operations",
  292. "64-Bit integer",
  293. "View Instancing",
  294. "Barycentrics",
  295. "Use native low precision"
  296. };
  297. static_assert(_countof(g_pFeatureInfoNames) == ShaderFeatureInfoCount, "g_pFeatureInfoNames needs to be updated");
  298. void PrintFeatureInfo(const DxilShaderFeatureInfo *pFeatureInfo,
  299. raw_string_ostream &OS, StringRef comment) {
  300. uint64_t featureFlags = pFeatureInfo->FeatureFlags;
  301. if (!featureFlags)
  302. return;
  303. OS << comment << "\n";
  304. OS << comment << " Note: shader requires additional functionality:\n";
  305. for (unsigned i = 0; i < ShaderFeatureInfoCount; i++) {
  306. if (featureFlags & (((uint64_t)1) << i))
  307. OS << comment << " " << g_pFeatureInfoNames[i] << "\n";
  308. }
  309. OS << comment << "\n";
  310. }
  311. void PrintResourceFormat(DxilResourceBase &res, unsigned alignment,
  312. raw_string_ostream &OS) {
  313. switch (res.GetClass()) {
  314. case DxilResourceBase::Class::CBuffer:
  315. case DxilResourceBase::Class::Sampler:
  316. OS << right_justify("NA", alignment);
  317. break;
  318. case DxilResourceBase::Class::UAV:
  319. case DxilResourceBase::Class::SRV:
  320. switch (res.GetKind()) {
  321. case DxilResource::Kind::RawBuffer:
  322. OS << right_justify("byte", alignment);
  323. break;
  324. case DxilResource::Kind::StructuredBuffer:
  325. OS << right_justify("struct", alignment);
  326. break;
  327. default:
  328. DxilResource *pRes = static_cast<DxilResource *>(&res);
  329. CompType &&compType = pRes->GetCompType();
  330. const char *compName = compType.GetName();
  331. // TODO: add vector size.
  332. OS << right_justify(compName, alignment);
  333. break;
  334. }
  335. }
  336. }
  337. void PrintResourceDim(DxilResourceBase &res, unsigned alignment,
  338. raw_string_ostream &OS) {
  339. switch (res.GetClass()) {
  340. case DxilResourceBase::Class::CBuffer:
  341. case DxilResourceBase::Class::Sampler:
  342. OS << right_justify("NA", alignment);
  343. break;
  344. case DxilResourceBase::Class::UAV:
  345. case DxilResourceBase::Class::SRV:
  346. switch (res.GetKind()) {
  347. case DxilResource::Kind::RawBuffer:
  348. case DxilResource::Kind::StructuredBuffer:
  349. if (res.GetClass() == DxilResourceBase::Class::SRV)
  350. OS << right_justify("r/o", alignment);
  351. else {
  352. DxilResource &dxilRes = static_cast<DxilResource &>(res);
  353. if (!dxilRes.HasCounter())
  354. OS << right_justify("r/w", alignment);
  355. else
  356. OS << right_justify("r/w+cnt", alignment);
  357. }
  358. break;
  359. case DxilResource::Kind::TypedBuffer:
  360. OS << right_justify("buf", alignment);
  361. break;
  362. case DxilResource::Kind::Texture2DMS:
  363. case DxilResource::Kind::Texture2DMSArray: {
  364. DxilResource *pRes = static_cast<DxilResource *>(&res);
  365. std::string dimName = res.GetResDimName();
  366. if (pRes->GetSampleCount())
  367. dimName += pRes->GetSampleCount();
  368. OS << right_justify(dimName, alignment);
  369. } break;
  370. default:
  371. OS << right_justify(res.GetResDimName(), alignment);
  372. break;
  373. }
  374. break;
  375. }
  376. }
  377. void PrintResourceBinding(DxilResourceBase &res, raw_string_ostream &OS,
  378. StringRef comment) {
  379. OS << comment << " " << left_justify(res.GetGlobalName(), 31);
  380. OS << right_justify(res.GetResClassName(), 10);
  381. PrintResourceFormat(res, 8, OS);
  382. PrintResourceDim(res, 12, OS);
  383. std::string ID = res.GetResIDPrefix();
  384. ID += std::to_string(res.GetID());
  385. OS << right_justify(ID, 8);
  386. std::string bind = res.GetResBindPrefix();
  387. bind += std::to_string(res.GetLowerBound());
  388. if (res.GetSpaceID())
  389. bind += ",space" + std::to_string(res.GetSpaceID());
  390. OS << right_justify(bind, 15);
  391. if (res.GetRangeSize() != UINT_MAX)
  392. OS << right_justify(std::to_string(res.GetRangeSize()), 6) << "\n";
  393. else
  394. OS << right_justify("unbounded", 6) << "\n";
  395. }
  396. void PrintResourceBindings(DxilModule &M, raw_string_ostream &OS,
  397. StringRef comment) {
  398. OS << comment << "\n"
  399. << comment << " Resource Bindings:\n"
  400. << comment << "\n"
  401. << comment
  402. << " Name Type Format Dim "
  403. "ID HLSL Bind Count\n"
  404. << comment
  405. << " ------------------------------ ---------- ------- ----------- "
  406. "------- -------------- ------\n";
  407. for (auto &res : M.GetCBuffers()) {
  408. PrintResourceBinding(*res.get(), OS, comment);
  409. }
  410. for (auto &res : M.GetSamplers()) {
  411. PrintResourceBinding(*res.get(), OS, comment);
  412. }
  413. for (auto &res : M.GetSRVs()) {
  414. PrintResourceBinding(*res.get(), OS, comment);
  415. }
  416. for (auto &res : M.GetUAVs()) {
  417. PrintResourceBinding(*res.get(), OS, comment);
  418. }
  419. OS << comment << "\n";
  420. }
  421. void PrintOutputsDependentOnViewId(
  422. llvm::raw_ostream &OS, llvm::StringRef comment, llvm::StringRef SetName,
  423. unsigned NumOutputs,
  424. const DxilViewIdState::OutputsDependentOnViewIdType
  425. &OutputsDependentOnViewId) {
  426. OS << comment << " " << SetName << " dependent on ViewId: { ";
  427. bool bFirst = true;
  428. for (unsigned i = 0; i < NumOutputs; i++) {
  429. if (OutputsDependentOnViewId[i]) {
  430. if (!bFirst)
  431. OS << ", ";
  432. OS << i;
  433. bFirst = false;
  434. }
  435. }
  436. OS << " }\n";
  437. }
  438. void PrintInputsContributingToOutputs(
  439. llvm::raw_ostream &OS, llvm::StringRef comment,
  440. llvm::StringRef InputSetName, llvm::StringRef OutputSetName,
  441. const DxilViewIdState::InputsContributingToOutputType
  442. &InputsContributingToOutputs) {
  443. OS << comment << " " << InputSetName << " contributing to computation of "
  444. << OutputSetName << ":\n";
  445. for (auto &it : InputsContributingToOutputs) {
  446. unsigned outIdx = it.first;
  447. auto &Inputs = it.second;
  448. OS << comment << " output " << outIdx << " depends on inputs: { ";
  449. bool bFirst = true;
  450. for (unsigned i : Inputs) {
  451. if (!bFirst)
  452. OS << ", ";
  453. OS << i;
  454. bFirst = false;
  455. }
  456. OS << " }\n";
  457. }
  458. }
  459. void PrintViewIdState(DxilModule &M, raw_string_ostream &OS,
  460. StringRef comment) {
  461. if (!M.GetModule()->getNamedMetadata("dx.viewIdState"))
  462. return;
  463. const ShaderModel *pSM = M.GetShaderModel();
  464. DxilViewIdState &VID = M.GetViewIdState();
  465. OS << comment << "\n";
  466. OS << comment << " ViewId state:\n";
  467. OS << comment << "\n";
  468. OS << comment << " Number of inputs: " << VID.getNumInputSigScalars();
  469. if (!pSM->IsGS()) {
  470. OS << ", outputs: " << VID.getNumOutputSigScalars(0);
  471. } else {
  472. OS << ", outputs per stream: { " << VID.getNumOutputSigScalars(0) << ", "
  473. << VID.getNumOutputSigScalars(1) << ", " << VID.getNumOutputSigScalars(2)
  474. << ", " << VID.getNumOutputSigScalars(3) << " }";
  475. }
  476. if (pSM->IsHS() || pSM->IsDS()) {
  477. OS << ", patchconst: " << VID.getNumPCSigScalars();
  478. }
  479. OS << "\n";
  480. if (!pSM->IsGS()) {
  481. PrintOutputsDependentOnViewId(OS, comment, "Outputs",
  482. VID.getNumOutputSigScalars(0),
  483. VID.getOutputsDependentOnViewId(0));
  484. } else {
  485. for (unsigned i = 0; i < 4; i++) {
  486. if (VID.getNumOutputSigScalars(i) > 0) {
  487. std::string OutputsName =
  488. std::string("Outputs for Stream ") + std::to_string(i);
  489. PrintOutputsDependentOnViewId(OS, comment, OutputsName,
  490. VID.getNumOutputSigScalars(i),
  491. VID.getOutputsDependentOnViewId(i));
  492. }
  493. }
  494. }
  495. if (pSM->IsHS()) {
  496. PrintOutputsDependentOnViewId(OS, comment, "PCOutputs",
  497. VID.getNumPCSigScalars(),
  498. VID.getPCOutputsDependentOnViewId());
  499. }
  500. if (!pSM->IsGS()) {
  501. PrintInputsContributingToOutputs(OS, comment, "Inputs", "Outputs",
  502. VID.getInputsContributingToOutputs(0));
  503. } else {
  504. for (unsigned i = 0; i < 4; i++) {
  505. if (VID.getNumOutputSigScalars(i) > 0) {
  506. std::string OutputsName =
  507. std::string("Outputs for Stream ") + std::to_string(i);
  508. PrintInputsContributingToOutputs(OS, comment, "Inputs", OutputsName,
  509. VID.getInputsContributingToOutputs(i));
  510. }
  511. }
  512. }
  513. if (pSM->IsHS()) {
  514. PrintInputsContributingToOutputs(OS, comment, "Inputs", "PCOutputs",
  515. VID.getInputsContributingToPCOutputs());
  516. } else if (pSM->IsDS()) {
  517. PrintInputsContributingToOutputs(OS, comment, "PCInputs", "Outputs",
  518. VID.getPCInputsContributingToOutputs());
  519. }
  520. OS << comment << "\n";
  521. }
  522. void PrintStructLayout(StructType *ST, DxilTypeSystem &typeSys,
  523. raw_string_ostream &OS, StringRef comment,
  524. StringRef varName, unsigned offset,
  525. unsigned indent, unsigned arraySize,
  526. unsigned sizeOfStruct = 0);
  527. void PrintTypeAndName(llvm::Type *Ty, DxilFieldAnnotation &annotation,
  528. std::string &StreamStr, unsigned arraySize, bool minPrecision) {
  529. raw_string_ostream Stream(StreamStr);
  530. while (Ty->isArrayTy())
  531. Ty = Ty->getArrayElementType();
  532. const char *compTyName = annotation.GetCompType().GetHLSLName(minPrecision);
  533. if (annotation.HasMatrixAnnotation()) {
  534. const DxilMatrixAnnotation &Matrix = annotation.GetMatrixAnnotation();
  535. switch (Matrix.Orientation) {
  536. case MatrixOrientation::RowMajor:
  537. Stream << "row_major ";
  538. break;
  539. case MatrixOrientation::ColumnMajor:
  540. Stream << "column_major ";
  541. break;
  542. }
  543. Stream << compTyName << Matrix.Rows << "x" << Matrix.Cols;
  544. } else if (Ty->isVectorTy())
  545. Stream << compTyName << Ty->getVectorNumElements();
  546. else
  547. Stream << compTyName;
  548. Stream << " " << annotation.GetFieldName();
  549. if (arraySize)
  550. Stream << "[" << arraySize << "]";
  551. Stream << ";";
  552. Stream.flush();
  553. }
  554. void PrintFieldLayout(llvm::Type *Ty, DxilFieldAnnotation &annotation,
  555. DxilTypeSystem &typeSys, raw_string_ostream &OS,
  556. StringRef comment, unsigned offset,
  557. unsigned indent, unsigned offsetIndent,
  558. unsigned sizeToPrint = 0) {
  559. offset += annotation.GetCBufferOffset();
  560. if (Ty->isStructTy() && !annotation.HasMatrixAnnotation()) {
  561. PrintStructLayout(cast<StructType>(Ty), typeSys, OS, comment,
  562. annotation.GetFieldName(), offset, indent, offsetIndent);
  563. } else {
  564. llvm::Type *EltTy = Ty;
  565. unsigned arraySize = 0;
  566. unsigned arrayLevel = 0;
  567. if (!HLMatrixLower::IsMatrixType(EltTy) && EltTy->isArrayTy()) {
  568. arraySize = 1;
  569. while (!HLMatrixLower::IsMatrixType(EltTy) && EltTy->isArrayTy()) {
  570. arraySize *= EltTy->getArrayNumElements();
  571. EltTy = EltTy->getArrayElementType();
  572. arrayLevel++;
  573. }
  574. }
  575. if (annotation.HasMatrixAnnotation()) {
  576. const DxilMatrixAnnotation &Matrix = annotation.GetMatrixAnnotation();
  577. switch (Matrix.Orientation) {
  578. case MatrixOrientation::RowMajor:
  579. arraySize /= Matrix.Rows;
  580. break;
  581. case MatrixOrientation::ColumnMajor:
  582. arraySize /= Matrix.Cols;
  583. break;
  584. }
  585. if (EltTy->isVectorTy()) {
  586. EltTy = EltTy->getVectorElementType();
  587. } else if (EltTy->isStructTy()) {
  588. unsigned col, row;
  589. EltTy = HLMatrixLower::GetMatrixInfo(EltTy, col, row);
  590. }
  591. if (arrayLevel == 1)
  592. arraySize = 0;
  593. }
  594. std::string StreamStr;
  595. if (!HLMatrixLower::IsMatrixType(EltTy) && EltTy->isStructTy()) {
  596. std::string NameTypeStr = annotation.GetFieldName();
  597. raw_string_ostream Stream(NameTypeStr);
  598. if (arraySize)
  599. Stream << "[" << std::to_string(arraySize) << "]";
  600. Stream << ";";
  601. Stream.flush();
  602. PrintStructLayout(cast<StructType>(EltTy), typeSys, OS, comment,
  603. NameTypeStr, offset, indent, offsetIndent);
  604. } else {
  605. (OS << comment).indent(indent);
  606. std::string NameTypeStr;
  607. PrintTypeAndName(Ty, annotation, NameTypeStr, arraySize, typeSys.UseMinPrecision());
  608. OS << left_justify(NameTypeStr, offsetIndent);
  609. // Offset
  610. OS << comment << " Offset:" << right_justify(std::to_string(offset), 5);
  611. if (sizeToPrint)
  612. OS << " Size: " << right_justify(std::to_string(sizeToPrint), 5);
  613. OS << "\n";
  614. }
  615. }
  616. }
  617. void PrintStructLayout(StructType *ST, DxilTypeSystem &typeSys,
  618. raw_string_ostream &OS, StringRef comment,
  619. StringRef varName, unsigned offset,
  620. unsigned indent, unsigned offsetIndent,
  621. unsigned sizeOfStruct) {
  622. DxilStructAnnotation *annotation = typeSys.GetStructAnnotation(ST);
  623. (OS << comment).indent(indent) << "struct " << ST->getName() << "\n";
  624. (OS << comment).indent(indent) << "{\n";
  625. OS << comment << "\n";
  626. unsigned fieldIndent = indent + 4;
  627. if (!annotation) {
  628. if (!sizeOfStruct) {
  629. (OS << comment).indent(indent) << "/* empty struct */\n";
  630. } else {
  631. (OS << comment).indent(indent) << "[" << sizeOfStruct << " x i8] (type annotation not present)\n";
  632. }
  633. } else {
  634. for (unsigned i = 0; i < ST->getNumElements(); i++) {
  635. PrintFieldLayout(ST->getElementType(i), annotation->GetFieldAnnotation(i),
  636. typeSys, OS, comment, offset, fieldIndent,
  637. offsetIndent - 4);
  638. }
  639. }
  640. (OS << comment).indent(indent) << "\n";
  641. // The 2 in offsetIndent-indent-2 is for "} ".
  642. (OS << comment).indent(indent)
  643. << "} " << left_justify(varName, offsetIndent - 2);
  644. OS << comment << " Offset:" << right_justify(std::to_string(offset), 5);
  645. if (sizeOfStruct)
  646. OS << " Size: " << right_justify(std::to_string(sizeOfStruct), 5);
  647. ;
  648. OS << "\n";
  649. OS << comment << "\n";
  650. }
  651. void PrintStructBufferDefinition(DxilResource *buf,
  652. DxilTypeSystem &typeSys,
  653. const DataLayout &DL,
  654. raw_string_ostream &OS,
  655. StringRef comment) {
  656. const unsigned offsetIndent = 50;
  657. OS << comment << " Resource bind info for " << buf->GetGlobalName() << "\n";
  658. OS << comment << " {\n";
  659. OS << comment << "\n";
  660. llvm::Type *RetTy = buf->GetRetType();
  661. // Skip none struct type.
  662. if (!RetTy->isStructTy() || HLMatrixLower::IsMatrixType(RetTy)) {
  663. Value *GV = buf->GetGlobalSymbol();
  664. llvm::Type *Ty = GV->getType()->getPointerElementType();
  665. // For resource array, use element type.
  666. if (Ty->isArrayTy())
  667. Ty = Ty->getArrayElementType();
  668. // Get the struct buffer type like this %class.StructuredBuffer = type {
  669. // %struct.mat }.
  670. StructType *ST = cast<StructType>(Ty);
  671. DxilStructAnnotation *annotation = typeSys.GetStructAnnotation(ST);
  672. if (nullptr == annotation) {
  673. OS << comment << " [" << DL.getTypeAllocSize(ST)
  674. << " x i8] (type annotation not present)\n";
  675. } else {
  676. DxilFieldAnnotation &fieldAnnotation = annotation->GetFieldAnnotation(0);
  677. fieldAnnotation.SetFieldName("$Element");
  678. PrintFieldLayout(RetTy, fieldAnnotation, typeSys, OS, comment,
  679. /*offset*/ 0, /*indent*/ 3, offsetIndent,
  680. DL.getTypeAllocSize(ST));
  681. }
  682. OS << comment << "\n";
  683. } else {
  684. StructType *ST = cast<StructType>(RetTy);
  685. // TODO: struct buffer has different layout.
  686. // Cannot use cbuffer layout here.
  687. DxilStructAnnotation *annotation = typeSys.GetStructAnnotation(ST);
  688. if (nullptr == annotation) {
  689. OS << comment << " [" << DL.getTypeAllocSize(ST)
  690. << " x i8] (type annotation not present)\n";
  691. } else {
  692. PrintStructLayout(ST, typeSys, OS, comment, "$Element;",
  693. /*offset*/ 0, /*indent*/ 3, offsetIndent,
  694. DL.getTypeAllocSize(ST));
  695. }
  696. }
  697. OS << comment << " }\n";
  698. OS << comment << "\n";
  699. }
  700. void PrintTBufferDefinition(DxilResource *buf, DxilTypeSystem &typeSys,
  701. raw_string_ostream &OS, StringRef comment) {
  702. const unsigned offsetIndent = 50;
  703. Value *GV = buf->GetGlobalSymbol();
  704. llvm::Type *Ty = GV->getType()->getPointerElementType();
  705. // For TextureBuffer<> buf[2], the array size is in Resource binding count
  706. // part.
  707. if (Ty->isArrayTy())
  708. Ty = Ty->getArrayElementType();
  709. DxilStructAnnotation *annotation =
  710. typeSys.GetStructAnnotation(cast<StructType>(Ty));
  711. OS << comment << " tbuffer " << buf->GetGlobalName() << "\n";
  712. OS << comment << " {\n";
  713. OS << comment << "\n";
  714. if (nullptr == annotation) {
  715. OS << comment << " (type annotation not present)\n";
  716. OS << comment << "\n";
  717. } else {
  718. PrintStructLayout(cast<StructType>(Ty), typeSys, OS, comment,
  719. buf->GetGlobalName(), /*offset*/ 0, /*indent*/ 3,
  720. offsetIndent, annotation->GetCBufferSize());
  721. }
  722. OS << comment << " }\n";
  723. OS << comment << "\n";
  724. }
  725. void PrintCBufferDefinition(DxilCBuffer *buf, DxilTypeSystem &typeSys,
  726. raw_string_ostream &OS, StringRef comment) {
  727. const unsigned offsetIndent = 50;
  728. Value *GV = buf->GetGlobalSymbol();
  729. llvm::Type *Ty = GV->getType()->getPointerElementType();
  730. // For ConstantBuffer<> buf[2], the array size is in Resource binding count
  731. // part.
  732. if (Ty->isArrayTy())
  733. Ty = Ty->getArrayElementType();
  734. DxilStructAnnotation *annotation =
  735. typeSys.GetStructAnnotation(cast<StructType>(Ty));
  736. OS << comment << " cbuffer " << buf->GetGlobalName() << "\n";
  737. OS << comment << " {\n";
  738. OS << comment << "\n";
  739. if (nullptr == annotation) {
  740. OS << comment << " [" << buf->GetSize()
  741. << " x i8] (type annotation not present)\n";
  742. OS << comment << "\n";
  743. } else {
  744. PrintStructLayout(cast<StructType>(Ty), typeSys, OS, comment,
  745. buf->GetGlobalName(), /*offset*/ 0, /*indent*/ 3,
  746. offsetIndent, buf->GetSize());
  747. }
  748. OS << comment << " }\n";
  749. OS << comment << "\n";
  750. }
  751. void PrintBufferDefinitions(DxilModule &M, raw_string_ostream &OS,
  752. StringRef comment) {
  753. OS << comment << "\n"
  754. << comment << " Buffer Definitions:\n"
  755. << comment << "\n";
  756. DxilTypeSystem &typeSys = M.GetTypeSystem();
  757. for (auto &CBuf : M.GetCBuffers())
  758. PrintCBufferDefinition(CBuf.get(), typeSys, OS, comment);
  759. const DataLayout &layout = M.GetModule()->getDataLayout();
  760. for (auto &res : M.GetSRVs()) {
  761. if (res->IsStructuredBuffer())
  762. PrintStructBufferDefinition(res.get(), typeSys, layout, OS, comment);
  763. else if (res->IsTBuffer())
  764. PrintTBufferDefinition(res.get(), typeSys, OS, comment);
  765. }
  766. for (auto &res : M.GetUAVs()) {
  767. if (res->IsStructuredBuffer())
  768. PrintStructBufferDefinition(res.get(), typeSys, layout, OS, comment);
  769. }
  770. }
  771. /* <py::lines('OPCODE-SIGS')>hctdb_instrhelp.get_opsigs()</py>*/
  772. // OPCODE-SIGS:BEGIN
  773. static const char *OpCodeSignatures[] = {
  774. "(index)", // TempRegLoad
  775. "(index,value)", // TempRegStore
  776. "(regIndex,index,component)", // MinPrecXRegLoad
  777. "(regIndex,index,component,value)", // MinPrecXRegStore
  778. "(inputSigId,rowIndex,colIndex,gsVertexAxis)", // LoadInput
  779. "(outputSigId,rowIndex,colIndex,value)", // StoreOutput
  780. "(value)", // FAbs
  781. "(value)", // Saturate
  782. "(value)", // IsNaN
  783. "(value)", // IsInf
  784. "(value)", // IsFinite
  785. "(value)", // IsNormal
  786. "(value)", // Cos
  787. "(value)", // Sin
  788. "(value)", // Tan
  789. "(value)", // Acos
  790. "(value)", // Asin
  791. "(value)", // Atan
  792. "(value)", // Hcos
  793. "(value)", // Hsin
  794. "(value)", // Htan
  795. "(value)", // Exp
  796. "(value)", // Frc
  797. "(value)", // Log
  798. "(value)", // Sqrt
  799. "(value)", // Rsqrt
  800. "(value)", // Round_ne
  801. "(value)", // Round_ni
  802. "(value)", // Round_pi
  803. "(value)", // Round_z
  804. "(value)", // Bfrev
  805. "(value)", // Countbits
  806. "(value)", // FirstbitLo
  807. "(value)", // FirstbitHi
  808. "(value)", // FirstbitSHi
  809. "(a,b)", // FMax
  810. "(a,b)", // FMin
  811. "(a,b)", // IMax
  812. "(a,b)", // IMin
  813. "(a,b)", // UMax
  814. "(a,b)", // UMin
  815. "(a,b)", // IMul
  816. "(a,b)", // UMul
  817. "(a,b)", // UDiv
  818. "(a,b)", // UAddc
  819. "(a,b)", // USubb
  820. "(a,b,c)", // FMad
  821. "(a,b,c)", // Fma
  822. "(a,b,c)", // IMad
  823. "(a,b,c)", // UMad
  824. "(a,b,c)", // Msad
  825. "(a,b,c)", // Ibfe
  826. "(a,b,c)", // Ubfe
  827. "(width,offset,value,replacedValue)", // Bfi
  828. "(ax,ay,bx,by)", // Dot2
  829. "(ax,ay,az,bx,by,bz)", // Dot3
  830. "(ax,ay,az,aw,bx,by,bz,bw)", // Dot4
  831. "(resourceClass,rangeId,index,nonUniformIndex)", // CreateHandle
  832. "(handle,byteOffset,alignment)", // CBufferLoad
  833. "(handle,regIndex)", // CBufferLoadLegacy
  834. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)", // Sample
  835. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,bias,clamp)", // SampleBias
  836. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD)", // SampleLevel
  837. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,ddx0,ddx1,ddx2,ddy0,ddy1,ddy2,clamp)", // SampleGrad
  838. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue,clamp)", // SampleCmp
  839. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,compareValue)", // SampleCmpLevelZero
  840. "(srv,mipLevelOrSampleCount,coord0,coord1,coord2,offset0,offset1,offset2)", // TextureLoad
  841. "(srv,coord0,coord1,coord2,value0,value1,value2,value3,mask)", // TextureStore
  842. "(srv,index,wot)", // BufferLoad
  843. "(uav,coord0,coord1,value0,value1,value2,value3,mask)", // BufferStore
  844. "(uav,inc)", // BufferUpdateCounter
  845. "(status)", // CheckAccessFullyMapped
  846. "(handle,mipLevel)", // GetDimensions
  847. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,channel)", // TextureGather
  848. "(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,channel,compareVale)", // TextureGatherCmp
  849. "(srv,index)", // Texture2DMSGetSamplePosition
  850. "(index)", // RenderTargetGetSamplePosition
  851. "()", // RenderTargetGetSampleCount
  852. "(handle,atomicOp,offset0,offset1,offset2,newValue)", // AtomicBinOp
  853. "(handle,offset0,offset1,offset2,compareValue,newValue)", // AtomicCompareExchange
  854. "(barrierMode)", // Barrier
  855. "(handle,sampler,coord0,coord1,coord2,clamped)", // CalculateLOD
  856. "(condition)", // Discard
  857. "(value)", // DerivCoarseX
  858. "(value)", // DerivCoarseY
  859. "(value)", // DerivFineX
  860. "(value)", // DerivFineY
  861. "(inputSigId,inputRowIndex,inputColIndex,offsetX,offsetY)", // EvalSnapped
  862. "(inputSigId,inputRowIndex,inputColIndex,sampleIndex)", // EvalSampleIndex
  863. "(inputSigId,inputRowIndex,inputColIndex)", // EvalCentroid
  864. "()", // SampleIndex
  865. "()", // Coverage
  866. "()", // InnerCoverage
  867. "(component)", // ThreadId
  868. "(component)", // GroupId
  869. "(component)", // ThreadIdInGroup
  870. "()", // FlattenedThreadIdInGroup
  871. "(streamId)", // EmitStream
  872. "(streamId)", // CutStream
  873. "(streamId)", // EmitThenCutStream
  874. "()", // GSInstanceID
  875. "(lo,hi)", // MakeDouble
  876. "(value)", // SplitDouble
  877. "(inputSigId,row,col,index)", // LoadOutputControlPoint
  878. "(inputSigId,row,col)", // LoadPatchConstant
  879. "(component)", // DomainLocation
  880. "(outputSigID,row,col,value)", // StorePatchConstant
  881. "()", // OutputControlPointID
  882. "()", // PrimitiveID
  883. "()", // CycleCounterLegacy
  884. "()", // WaveIsFirstLane
  885. "()", // WaveGetLaneIndex
  886. "()", // WaveGetLaneCount
  887. "(cond)", // WaveAnyTrue
  888. "(cond)", // WaveAllTrue
  889. "(value)", // WaveActiveAllEqual
  890. "(cond)", // WaveActiveBallot
  891. "(value,lane)", // WaveReadLaneAt
  892. "(value)", // WaveReadLaneFirst
  893. "(value,op,sop)", // WaveActiveOp
  894. "(value,op)", // WaveActiveBit
  895. "(value,op,sop)", // WavePrefixOp
  896. "(value,quadLane)", // QuadReadLaneAt
  897. "(value,op)", // QuadOp
  898. "(value)", // BitcastI16toF16
  899. "(value)", // BitcastF16toI16
  900. "(value)", // BitcastI32toF32
  901. "(value)", // BitcastF32toI32
  902. "(value)", // BitcastI64toF64
  903. "(value)", // BitcastF64toI64
  904. "(value)", // LegacyF32ToF16
  905. "(value)", // LegacyF16ToF32
  906. "(value)", // LegacyDoubleToFloat
  907. "(value)", // LegacyDoubleToSInt32
  908. "(value)", // LegacyDoubleToUInt32
  909. "(value)", // WaveAllBitCount
  910. "(value)", // WavePrefixBitCount
  911. "(inputSigId,inputRowIndex,inputColIndex,VertexID)", // AttributeAtVertex
  912. "()", // ViewID
  913. "(srv,index,elementOffset,mask,alignment)", // RawBufferLoad
  914. "(uav,index,elementOffset,value0,value1,value2,value3,mask,alignment)", // RawBufferStore
  915. "()", // InstanceID
  916. "()", // InstanceIndex
  917. "()", // HitKind
  918. "()", // RayFlags
  919. "(col)", // DispatchRaysIndex
  920. "(col)", // DispatchRaysDimensions
  921. "(col)", // WorldRayOrigin
  922. "(col)", // WorldRayDirection
  923. "(col)", // ObjectRayOrigin
  924. "(col)", // ObjectRayDirection
  925. "(row,col)", // ObjectToWorld
  926. "(row,col)", // WorldToObject
  927. "()", // RayTMin
  928. "()", // RayTCurrent
  929. "()", // IgnoreHit
  930. "()", // AcceptHitAndEndSearch
  931. "(AccelerationStructure,RayFlags,InstanceInclusionMask,RayContributionToHitGroupIndex,MultiplierForGeometryContributionToShaderIndex,MissShaderIndex,Origin_X,Origin_Y,Origin_Z,TMin,Direction_X,Direction_Y,Direction_Z,TMax,payload)", // TraceRay
  932. "(THit,HitKind,Attributes)", // ReportHit
  933. "(ShaderIndex,Parameter)", // CallShader
  934. "(Resource)", // CreateHandleForLib
  935. "()" // PrimitiveIndex
  936. };
  937. // OPCODE-SIGS:END
  938. class DxcAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
  939. public:
  940. ~DxcAssemblyAnnotationWriter() {}
  941. void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
  942. const CallInst *CI = dyn_cast<const CallInst>(&V);
  943. if (!CI) {
  944. return;
  945. }
  946. // TODO: annotate high-level operations where possible as well
  947. if (CI->getNumArgOperands() == 0 ||
  948. !CI->getCalledFunction()->getName().startswith("dx.op.")) {
  949. return;
  950. }
  951. const ConstantInt *CInt = dyn_cast<const ConstantInt>(CI->getArgOperand(0));
  952. if (!CInt) {
  953. // At this point, we know this is malformed; ignore.
  954. return;
  955. }
  956. unsigned opcodeVal = CInt->getZExtValue();
  957. if (opcodeVal >= (unsigned)DXIL::OpCode::NumOpCodes) {
  958. OS << " ; invalid DXIL opcode #" << opcodeVal;
  959. return;
  960. }
  961. // TODO: if an argument references a resource, look it up and write the
  962. // name/binding
  963. DXIL::OpCode opcode = (DXIL::OpCode)opcodeVal;
  964. OS << " ; " << hlsl::OP::GetOpCodeName(opcode)
  965. << OpCodeSignatures[opcodeVal];
  966. }
  967. };
  968. void PrintPipelineStateValidationRuntimeInfo(const char *pBuffer,
  969. DXIL::ShaderKind shaderKind,
  970. raw_string_ostream &OS,
  971. StringRef comment) {
  972. OS << comment << "\n"
  973. << comment << " Pipeline Runtime Information: \n"
  974. << comment << "\n";
  975. const unsigned offset = sizeof(unsigned);
  976. const PSVRuntimeInfo0 *pInfo = (PSVRuntimeInfo0 *)(pBuffer + offset);
  977. switch (shaderKind) {
  978. case DXIL::ShaderKind::Hull: {
  979. OS << comment << " Hull Shader\n";
  980. OS << comment
  981. << " InputControlPointCount=" << pInfo->HS.InputControlPointCount
  982. << "\n";
  983. OS << comment
  984. << " OutputControlPointCount=" << pInfo->HS.OutputControlPointCount
  985. << "\n";
  986. OS << comment << " Domain=";
  987. DXIL::TessellatorDomain domain =
  988. static_cast<DXIL::TessellatorDomain>(pInfo->HS.TessellatorDomain);
  989. switch (domain) {
  990. case DXIL::TessellatorDomain::IsoLine:
  991. OS << "isoline\n";
  992. break;
  993. case DXIL::TessellatorDomain::Tri:
  994. OS << "tri\n";
  995. break;
  996. case DXIL::TessellatorDomain::Quad:
  997. OS << "quad\n";
  998. break;
  999. default:
  1000. OS << "invalid\n";
  1001. break;
  1002. }
  1003. OS << comment << " OutputPrimitive=";
  1004. DXIL::TessellatorOutputPrimitive primitive =
  1005. static_cast<DXIL::TessellatorOutputPrimitive>(
  1006. pInfo->HS.TessellatorOutputPrimitive);
  1007. switch (primitive) {
  1008. case DXIL::TessellatorOutputPrimitive::Point:
  1009. OS << "point\n";
  1010. break;
  1011. case DXIL::TessellatorOutputPrimitive::Line:
  1012. OS << "line\n";
  1013. break;
  1014. case DXIL::TessellatorOutputPrimitive::TriangleCW:
  1015. OS << "triangle_cw\n";
  1016. break;
  1017. case DXIL::TessellatorOutputPrimitive::TriangleCCW:
  1018. OS << "triangle_ccw\n";
  1019. break;
  1020. default:
  1021. OS << "invalid\n";
  1022. break;
  1023. }
  1024. } break;
  1025. case DXIL::ShaderKind::Domain:
  1026. OS << comment << " Domain Shader\n";
  1027. OS << comment
  1028. << " InputControlPointCount=" << pInfo->DS.InputControlPointCount
  1029. << "\n";
  1030. OS << comment
  1031. << " OutputPositionPresent=" << (bool)pInfo->DS.OutputPositionPresent
  1032. << "\n";
  1033. break;
  1034. case DXIL::ShaderKind::Geometry: {
  1035. OS << comment << " Geometry Shader\n";
  1036. OS << comment << " InputPrimitive=";
  1037. DXIL::InputPrimitive primitive =
  1038. static_cast<DXIL::InputPrimitive>(pInfo->GS.InputPrimitive);
  1039. switch (primitive) {
  1040. case DXIL::InputPrimitive::Point:
  1041. OS << "point\n";
  1042. break;
  1043. case DXIL::InputPrimitive::Line:
  1044. OS << "line\n";
  1045. break;
  1046. case DXIL::InputPrimitive::LineWithAdjacency:
  1047. OS << "lineadj\n";
  1048. break;
  1049. case DXIL::InputPrimitive::Triangle:
  1050. OS << "triangle\n";
  1051. break;
  1052. case DXIL::InputPrimitive::TriangleWithAdjacency:
  1053. OS << "triangleadj\n";
  1054. break;
  1055. case DXIL::InputPrimitive::ControlPointPatch1:
  1056. OS << "patch1\n";
  1057. break;
  1058. case DXIL::InputPrimitive::ControlPointPatch2:
  1059. OS << "patch2\n";
  1060. break;
  1061. case DXIL::InputPrimitive::ControlPointPatch3:
  1062. OS << "patch3\n";
  1063. break;
  1064. case DXIL::InputPrimitive::ControlPointPatch4:
  1065. OS << "patch4\n";
  1066. break;
  1067. case DXIL::InputPrimitive::ControlPointPatch5:
  1068. OS << "patch5\n";
  1069. break;
  1070. case DXIL::InputPrimitive::ControlPointPatch6:
  1071. OS << "patch6\n";
  1072. break;
  1073. case DXIL::InputPrimitive::ControlPointPatch7:
  1074. OS << "patch7\n";
  1075. break;
  1076. case DXIL::InputPrimitive::ControlPointPatch8:
  1077. OS << "patch8\n";
  1078. break;
  1079. case DXIL::InputPrimitive::ControlPointPatch9:
  1080. OS << "patch9\n";
  1081. break;
  1082. case DXIL::InputPrimitive::ControlPointPatch10:
  1083. OS << "patch10\n";
  1084. break;
  1085. case DXIL::InputPrimitive::ControlPointPatch11:
  1086. OS << "patch11\n";
  1087. break;
  1088. case DXIL::InputPrimitive::ControlPointPatch12:
  1089. OS << "patch12\n";
  1090. break;
  1091. case DXIL::InputPrimitive::ControlPointPatch13:
  1092. OS << "patch13\n";
  1093. break;
  1094. case DXIL::InputPrimitive::ControlPointPatch14:
  1095. OS << "patch14\n";
  1096. break;
  1097. case DXIL::InputPrimitive::ControlPointPatch15:
  1098. OS << "patch15\n";
  1099. break;
  1100. case DXIL::InputPrimitive::ControlPointPatch16:
  1101. OS << "patch16\n";
  1102. break;
  1103. case DXIL::InputPrimitive::ControlPointPatch17:
  1104. OS << "patch17\n";
  1105. break;
  1106. case DXIL::InputPrimitive::ControlPointPatch18:
  1107. OS << "patch18\n";
  1108. break;
  1109. case DXIL::InputPrimitive::ControlPointPatch19:
  1110. OS << "patch19\n";
  1111. break;
  1112. case DXIL::InputPrimitive::ControlPointPatch20:
  1113. OS << "patch20\n";
  1114. break;
  1115. case DXIL::InputPrimitive::ControlPointPatch21:
  1116. OS << "patch21\n";
  1117. break;
  1118. case DXIL::InputPrimitive::ControlPointPatch22:
  1119. OS << "patch22\n";
  1120. break;
  1121. case DXIL::InputPrimitive::ControlPointPatch23:
  1122. OS << "patch23\n";
  1123. break;
  1124. case DXIL::InputPrimitive::ControlPointPatch24:
  1125. OS << "patch24\n";
  1126. break;
  1127. case DXIL::InputPrimitive::ControlPointPatch25:
  1128. OS << "patch25\n";
  1129. break;
  1130. case DXIL::InputPrimitive::ControlPointPatch26:
  1131. OS << "patch26\n";
  1132. break;
  1133. case DXIL::InputPrimitive::ControlPointPatch27:
  1134. OS << "patch27\n";
  1135. break;
  1136. case DXIL::InputPrimitive::ControlPointPatch28:
  1137. OS << "patch28\n";
  1138. break;
  1139. case DXIL::InputPrimitive::ControlPointPatch29:
  1140. OS << "patch29\n";
  1141. break;
  1142. case DXIL::InputPrimitive::ControlPointPatch30:
  1143. OS << "patch30\n";
  1144. break;
  1145. case DXIL::InputPrimitive::ControlPointPatch31:
  1146. OS << "patch31\n";
  1147. break;
  1148. case DXIL::InputPrimitive::ControlPointPatch32:
  1149. OS << "patch32\n";
  1150. break;
  1151. default:
  1152. OS << "invalid\n";
  1153. break;
  1154. }
  1155. OS << comment << " OutputTopology=";
  1156. DXIL::PrimitiveTopology topology =
  1157. static_cast<DXIL::PrimitiveTopology>(pInfo->GS.OutputTopology);
  1158. switch (topology) {
  1159. case DXIL::PrimitiveTopology::PointList:
  1160. OS << "point\n";
  1161. break;
  1162. case DXIL::PrimitiveTopology::LineStrip:
  1163. OS << "line\n";
  1164. break;
  1165. case DXIL::PrimitiveTopology::TriangleStrip:
  1166. OS << "triangle\n";
  1167. break;
  1168. default:
  1169. OS << "invalid\n";
  1170. break;
  1171. }
  1172. OS << comment << " OutputStreamMask=" << pInfo->GS.OutputStreamMask << "\n";
  1173. OS << comment
  1174. << " OutputPositionPresent=" << (bool)pInfo->GS.OutputPositionPresent
  1175. << "\n";
  1176. } break;
  1177. case DXIL::ShaderKind::Vertex:
  1178. OS << comment << " Vertex Shader\n";
  1179. OS << comment
  1180. << " OutputPositionPresent=" << (bool)pInfo->VS.OutputPositionPresent
  1181. << "\n";
  1182. break;
  1183. case DXIL::ShaderKind::Pixel:
  1184. OS << comment << " Pixel Shader\n";
  1185. OS << comment << " DepthOutput=" << (bool)pInfo->PS.DepthOutput << "\n";
  1186. OS << comment << " SampleFrequency=" << (bool)pInfo->PS.SampleFrequency
  1187. << "\n";
  1188. break;
  1189. }
  1190. OS << comment << "\n";
  1191. }
  1192. }
  1193. namespace dxcutil {
  1194. HRESULT Disassemble(IDxcBlob *pProgram, raw_string_ostream &Stream) {
  1195. const char *pIL = (const char *)pProgram->GetBufferPointer();
  1196. uint32_t pILLength = pProgram->GetBufferSize();
  1197. if (const DxilContainerHeader *pContainer =
  1198. IsDxilContainerLike(pIL, pILLength)) {
  1199. if (!IsValidDxilContainer(pContainer, pILLength)) {
  1200. return DXC_E_CONTAINER_INVALID;
  1201. }
  1202. DxilPartIterator it = std::find_if(begin(pContainer), end(pContainer),
  1203. DxilPartIsType(DFCC_FeatureInfo));
  1204. if (it != end(pContainer)) {
  1205. PrintFeatureInfo(
  1206. reinterpret_cast<const DxilShaderFeatureInfo *>(GetDxilPartData(*it)),
  1207. Stream, /*comment*/ ";");
  1208. }
  1209. it = std::find_if(begin(pContainer), end(pContainer),
  1210. DxilPartIsType(DFCC_InputSignature));
  1211. if (it != end(pContainer)) {
  1212. PrintSignature(
  1213. "Input",
  1214. reinterpret_cast<const DxilProgramSignature *>(GetDxilPartData(*it)),
  1215. true, Stream, /*comment*/ ";");
  1216. }
  1217. it = std::find_if(begin(pContainer), end(pContainer),
  1218. DxilPartIsType(DFCC_OutputSignature));
  1219. if (it != end(pContainer)) {
  1220. PrintSignature(
  1221. "Output",
  1222. reinterpret_cast<const DxilProgramSignature *>(GetDxilPartData(*it)),
  1223. false, Stream, /*comment*/ ";");
  1224. }
  1225. it = std::find_if(begin(pContainer), end(pContainer),
  1226. DxilPartIsType(DFCC_PatchConstantSignature));
  1227. if (it != end(pContainer)) {
  1228. PrintSignature(
  1229. "Patch Constant signature",
  1230. reinterpret_cast<const DxilProgramSignature *>(GetDxilPartData(*it)),
  1231. false, Stream, /*comment*/ ";");
  1232. }
  1233. it = std::find_if(begin(pContainer), end(pContainer),
  1234. DxilPartIsType(DFCC_ShaderDebugName));
  1235. if (it != end(pContainer)) {
  1236. const char *pDebugName;
  1237. if (!GetDxilShaderDebugName(*it, &pDebugName, nullptr)) {
  1238. Stream << "; shader debug name present; corruption detected\n";
  1239. } else if (pDebugName && *pDebugName) {
  1240. Stream << "; shader debug name: " << pDebugName << "\n";
  1241. }
  1242. }
  1243. it = std::find_if(begin(pContainer), end(pContainer),
  1244. DxilPartIsType(DFCC_DXIL));
  1245. if (it == end(pContainer)) {
  1246. return DXC_E_CONTAINER_MISSING_DXIL;
  1247. }
  1248. DxilPartIterator dbgit =
  1249. std::find_if(begin(pContainer), end(pContainer),
  1250. DxilPartIsType(DFCC_ShaderDebugInfoDXIL));
  1251. // Use dbg module if exist.
  1252. if (dbgit != end(pContainer))
  1253. it = dbgit;
  1254. const DxilProgramHeader *pProgramHeader =
  1255. reinterpret_cast<const DxilProgramHeader *>(GetDxilPartData(*it));
  1256. if (!IsValidDxilProgramHeader(pProgramHeader, (*it)->PartSize)) {
  1257. return DXC_E_CONTAINER_INVALID;
  1258. }
  1259. it = std::find_if(begin(pContainer), end(pContainer),
  1260. DxilPartIsType(DFCC_PipelineStateValidation));
  1261. if (it != end(pContainer)) {
  1262. PrintPipelineStateValidationRuntimeInfo(
  1263. GetDxilPartData(*it),
  1264. GetVersionShaderType(pProgramHeader->ProgramVersion), Stream,
  1265. /*comment*/ ";");
  1266. }
  1267. GetDxilProgramBitcode(pProgramHeader, &pIL, &pILLength);
  1268. } else {
  1269. const DxilProgramHeader *pProgramHeader =
  1270. reinterpret_cast<const DxilProgramHeader *>(pIL);
  1271. if (IsValidDxilProgramHeader(pProgramHeader, pILLength)) {
  1272. GetDxilProgramBitcode(pProgramHeader, &pIL, &pILLength);
  1273. }
  1274. }
  1275. std::string DiagStr;
  1276. llvm::LLVMContext llvmContext;
  1277. std::unique_ptr<llvm::Module> pModule(dxilutil::LoadModuleFromBitcode(
  1278. llvm::StringRef(pIL, pILLength), llvmContext, DiagStr));
  1279. if (pModule.get() == nullptr) {
  1280. return DXC_E_IR_VERIFICATION_FAILED;
  1281. }
  1282. if (pModule->getNamedMetadata("dx.version")) {
  1283. DxilModule &dxilModule = pModule->GetOrCreateDxilModule();
  1284. if (!dxilModule.GetShaderModel()->IsLib()) {
  1285. PrintDxilSignature("Input", dxilModule.GetInputSignature(), Stream,
  1286. /*comment*/ ";");
  1287. PrintDxilSignature("Output", dxilModule.GetOutputSignature(), Stream,
  1288. /*comment*/ ";");
  1289. PrintDxilSignature("Patch Constant signature",
  1290. dxilModule.GetPatchConstantSignature(), Stream,
  1291. /*comment*/ ";");
  1292. }
  1293. PrintBufferDefinitions(dxilModule, Stream, /*comment*/ ";");
  1294. PrintResourceBindings(dxilModule, Stream, /*comment*/ ";");
  1295. PrintViewIdState(dxilModule, Stream, /*comment*/ ";");
  1296. }
  1297. DxcAssemblyAnnotationWriter w;
  1298. pModule->print(Stream, &w);
  1299. Stream.flush();
  1300. return S_OK;
  1301. }
  1302. }