disassemble.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. //
  2. // Copyright (C) 2014-2015 LunarG, Inc.
  3. //
  4. // All rights reserved.
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions
  8. // are met:
  9. //
  10. // Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. //
  13. // Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following
  15. // disclaimer in the documentation and/or other materials provided
  16. // with the distribution.
  17. //
  18. // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
  19. // contributors may be used to endorse or promote products derived
  20. // from this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  30. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. // POSSIBILITY OF SUCH DAMAGE.
  34. //
  35. // Disassembler for SPIR-V.
  36. //
  37. #include <cstdlib>
  38. #include <cstring>
  39. #include <cassert>
  40. #include <iomanip>
  41. #include <stack>
  42. #include <sstream>
  43. #include <cstring>
  44. #include <utility>
  45. #include "disassemble.h"
  46. #include "doc.h"
  47. namespace spv {
  48. extern "C" {
  49. // Include C-based headers that don't have a namespace
  50. #include "GLSL.std.450.h"
  51. #include "GLSL.ext.AMD.h"
  52. #include "GLSL.ext.NV.h"
  53. #include "GLSL.ext.ARM.h"
  54. #include "NonSemanticShaderDebugInfo100.h"
  55. }
  56. }
  57. const char* GlslStd450DebugNames[spv::GLSLstd450Count];
  58. namespace spv {
  59. static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
  60. static const char* GLSLextNVGetDebugNames(const char*, unsigned);
  61. static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned);
  62. static void Kill(std::ostream& out, const char* message)
  63. {
  64. out << std::endl << "Disassembly failed: " << message << std::endl;
  65. exit(1);
  66. }
  67. // used to identify the extended instruction library imported when printing
  68. enum ExtInstSet {
  69. GLSL450Inst,
  70. GLSLextAMDInst,
  71. GLSLextNVInst,
  72. OpenCLExtInst,
  73. NonSemanticDebugPrintfExtInst,
  74. NonSemanticShaderDebugInfo100
  75. };
  76. // Container class for a single instance of a SPIR-V stream, with methods for disassembly.
  77. class SpirvStream {
  78. public:
  79. SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
  80. virtual ~SpirvStream() { }
  81. void validate();
  82. void processInstructions();
  83. protected:
  84. SpirvStream(const SpirvStream&);
  85. SpirvStream& operator=(const SpirvStream&);
  86. Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
  87. // Output methods
  88. void outputIndent();
  89. void formatId(Id id, std::stringstream&);
  90. void outputResultId(Id id);
  91. void outputTypeId(Id id);
  92. void outputId(Id id);
  93. void outputMask(OperandClass operandClass, unsigned mask);
  94. void disassembleImmediates(int numOperands);
  95. void disassembleIds(int numOperands);
  96. std::pair<int, std::string> decodeString();
  97. int disassembleString();
  98. void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
  99. // Data
  100. std::ostream& out; // where to write the disassembly
  101. const std::vector<unsigned int>& stream; // the actual word stream
  102. int size; // the size of the word stream
  103. int word; // the next word of the stream to read
  104. // map each <id> to the instruction that created it
  105. Id bound;
  106. std::vector<unsigned int> idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter)
  107. std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>
  108. // schema
  109. unsigned int schema;
  110. // stack of structured-merge points
  111. std::stack<Id> nestedControl;
  112. Id nextNestedControl; // need a slight delay for when we are nested
  113. };
  114. void SpirvStream::validate()
  115. {
  116. size = (int)stream.size();
  117. if (size < 4)
  118. Kill(out, "stream is too short");
  119. // Magic number
  120. if (stream[word++] != MagicNumber) {
  121. out << "Bad magic number";
  122. return;
  123. }
  124. // Version
  125. out << "// Module Version " << std::hex << stream[word++] << std::endl;
  126. // Generator's magic number
  127. out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;
  128. // Result <id> bound
  129. bound = stream[word++];
  130. idInstruction.resize(bound);
  131. idDescriptor.resize(bound);
  132. out << "// Id's are bound by " << bound << std::endl;
  133. out << std::endl;
  134. // Reserved schema, must be 0 for now
  135. schema = stream[word++];
  136. if (schema != 0)
  137. Kill(out, "bad schema, must be 0");
  138. }
  139. // Loop over all the instructions, in order, processing each.
  140. // Boiler plate for each is handled here directly, the rest is dispatched.
  141. void SpirvStream::processInstructions()
  142. {
  143. // Instructions
  144. while (word < size) {
  145. int instructionStart = word;
  146. // Instruction wordCount and opcode
  147. unsigned int firstWord = stream[word];
  148. unsigned wordCount = firstWord >> WordCountShift;
  149. Op opCode = (Op)(firstWord & OpCodeMask);
  150. int nextInst = word + wordCount;
  151. ++word;
  152. // Presence of full instruction
  153. if (nextInst > size)
  154. Kill(out, "stream instruction terminated too early");
  155. // Base for computing number of operands; will be updated as more is learned
  156. unsigned numOperands = wordCount - 1;
  157. // Type <id>
  158. Id typeId = 0;
  159. if (InstructionDesc[opCode].hasType()) {
  160. typeId = stream[word++];
  161. --numOperands;
  162. }
  163. // Result <id>
  164. Id resultId = 0;
  165. if (InstructionDesc[opCode].hasResult()) {
  166. resultId = stream[word++];
  167. --numOperands;
  168. // save instruction for future reference
  169. idInstruction[resultId] = instructionStart;
  170. }
  171. outputResultId(resultId);
  172. outputTypeId(typeId);
  173. outputIndent();
  174. // Hand off the Op and all its operands
  175. disassembleInstruction(resultId, typeId, opCode, numOperands);
  176. if (word != nextInst) {
  177. out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
  178. word = nextInst;
  179. }
  180. out << std::endl;
  181. }
  182. }
  183. void SpirvStream::outputIndent()
  184. {
  185. for (int i = 0; i < (int)nestedControl.size(); ++i)
  186. out << " ";
  187. }
  188. void SpirvStream::formatId(Id id, std::stringstream& idStream)
  189. {
  190. if (id != 0) {
  191. // On instructions with no IDs, this is called with "0", which does not
  192. // have to be within ID bounds on null shaders.
  193. if (id >= bound)
  194. Kill(out, "Bad <id>");
  195. idStream << id;
  196. if (idDescriptor[id].size() > 0)
  197. idStream << "(" << idDescriptor[id] << ")";
  198. }
  199. }
  200. void SpirvStream::outputResultId(Id id)
  201. {
  202. const int width = 16;
  203. std::stringstream idStream;
  204. formatId(id, idStream);
  205. out << std::setw(width) << std::right << idStream.str();
  206. if (id != 0)
  207. out << ":";
  208. else
  209. out << " ";
  210. if (nestedControl.size() && id == nestedControl.top())
  211. nestedControl.pop();
  212. }
  213. void SpirvStream::outputTypeId(Id id)
  214. {
  215. const int width = 12;
  216. std::stringstream idStream;
  217. formatId(id, idStream);
  218. out << std::setw(width) << std::right << idStream.str() << " ";
  219. }
  220. void SpirvStream::outputId(Id id)
  221. {
  222. if (id >= bound)
  223. Kill(out, "Bad <id>");
  224. out << id;
  225. if (idDescriptor[id].size() > 0)
  226. out << "(" << idDescriptor[id] << ")";
  227. }
  228. void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)
  229. {
  230. if (mask == 0)
  231. out << "None";
  232. else {
  233. for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
  234. if (mask & (1 << m))
  235. out << OperandClassParams[operandClass].getName(m) << " ";
  236. }
  237. }
  238. }
  239. void SpirvStream::disassembleImmediates(int numOperands)
  240. {
  241. for (int i = 0; i < numOperands; ++i) {
  242. out << stream[word++];
  243. if (i < numOperands - 1)
  244. out << " ";
  245. }
  246. }
  247. void SpirvStream::disassembleIds(int numOperands)
  248. {
  249. for (int i = 0; i < numOperands; ++i) {
  250. outputId(stream[word++]);
  251. if (i < numOperands - 1)
  252. out << " ";
  253. }
  254. }
  255. // decode string from words at current position (non-consuming)
  256. std::pair<int, std::string> SpirvStream::decodeString()
  257. {
  258. std::string res;
  259. int wordPos = word;
  260. char c;
  261. bool done = false;
  262. do {
  263. unsigned int content = stream[wordPos];
  264. for (int charCount = 0; charCount < 4; ++charCount) {
  265. c = content & 0xff;
  266. content >>= 8;
  267. if (c == '\0') {
  268. done = true;
  269. break;
  270. }
  271. res += c;
  272. }
  273. ++wordPos;
  274. } while(! done);
  275. return std::make_pair(wordPos - word, res);
  276. }
  277. // return the number of operands consumed by the string
  278. int SpirvStream::disassembleString()
  279. {
  280. out << " \"";
  281. std::pair<int, std::string> decoderes = decodeString();
  282. out << decoderes.second;
  283. out << "\"";
  284. word += decoderes.first;
  285. return decoderes.first;
  286. }
  287. void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
  288. {
  289. // Process the opcode
  290. out << (OpcodeString(opCode) + 2); // leave out the "Op"
  291. if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
  292. nextNestedControl = stream[word];
  293. else if (opCode == OpBranchConditional || opCode == OpSwitch) {
  294. if (nextNestedControl) {
  295. nestedControl.push(nextNestedControl);
  296. nextNestedControl = 0;
  297. }
  298. } else if (opCode == OpExtInstImport) {
  299. idDescriptor[resultId] = decodeString().second;
  300. }
  301. else {
  302. if (resultId != 0 && idDescriptor[resultId].size() == 0) {
  303. switch (opCode) {
  304. case OpTypeInt:
  305. switch (stream[word]) {
  306. case 8: idDescriptor[resultId] = "int8_t"; break;
  307. case 16: idDescriptor[resultId] = "int16_t"; break;
  308. default: assert(0); // fallthrough
  309. case 32: idDescriptor[resultId] = "int"; break;
  310. case 64: idDescriptor[resultId] = "int64_t"; break;
  311. }
  312. break;
  313. case OpTypeFloat:
  314. switch (stream[word]) {
  315. case 16: idDescriptor[resultId] = "float16_t"; break;
  316. default: assert(0); // fallthrough
  317. case 32: idDescriptor[resultId] = "float"; break;
  318. case 64: idDescriptor[resultId] = "float64_t"; break;
  319. }
  320. break;
  321. case OpTypeBool:
  322. idDescriptor[resultId] = "bool";
  323. break;
  324. case OpTypeStruct:
  325. idDescriptor[resultId] = "struct";
  326. break;
  327. case OpTypePointer:
  328. idDescriptor[resultId] = "ptr";
  329. break;
  330. case OpTypeVector:
  331. if (idDescriptor[stream[word]].size() > 0) {
  332. idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
  333. if (strstr(idDescriptor[stream[word]].c_str(), "8")) {
  334. idDescriptor[resultId].append("8");
  335. }
  336. if (strstr(idDescriptor[stream[word]].c_str(), "16")) {
  337. idDescriptor[resultId].append("16");
  338. }
  339. if (strstr(idDescriptor[stream[word]].c_str(), "64")) {
  340. idDescriptor[resultId].append("64");
  341. }
  342. }
  343. idDescriptor[resultId].append("vec");
  344. switch (stream[word + 1]) {
  345. case 2: idDescriptor[resultId].append("2"); break;
  346. case 3: idDescriptor[resultId].append("3"); break;
  347. case 4: idDescriptor[resultId].append("4"); break;
  348. case 8: idDescriptor[resultId].append("8"); break;
  349. case 16: idDescriptor[resultId].append("16"); break;
  350. case 32: idDescriptor[resultId].append("32"); break;
  351. default: break;
  352. }
  353. break;
  354. default:
  355. break;
  356. }
  357. }
  358. }
  359. // Process the operands. Note, a new context-dependent set could be
  360. // swapped in mid-traversal.
  361. // Handle images specially, so can put out helpful strings.
  362. if (opCode == OpTypeImage) {
  363. out << " ";
  364. disassembleIds(1);
  365. out << " " << DimensionString((Dim)stream[word++]);
  366. out << (stream[word++] != 0 ? " depth" : "");
  367. out << (stream[word++] != 0 ? " array" : "");
  368. out << (stream[word++] != 0 ? " multi-sampled" : "");
  369. switch (stream[word++]) {
  370. case 0: out << " runtime"; break;
  371. case 1: out << " sampled"; break;
  372. case 2: out << " nonsampled"; break;
  373. }
  374. out << " format:" << ImageFormatString((ImageFormat)stream[word++]);
  375. if (numOperands == 8) {
  376. out << " " << AccessQualifierString(stream[word++]);
  377. }
  378. return;
  379. }
  380. // Handle all the parameterized operands
  381. for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
  382. out << " ";
  383. OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
  384. switch (operandClass) {
  385. case OperandId:
  386. case OperandScope:
  387. case OperandMemorySemantics:
  388. disassembleIds(1);
  389. --numOperands;
  390. // Get names for printing "(XXX)" for readability, *after* this id
  391. if (opCode == OpName)
  392. idDescriptor[stream[word - 1]] = decodeString().second;
  393. break;
  394. case OperandVariableIds:
  395. disassembleIds(numOperands);
  396. return;
  397. case OperandImageOperands:
  398. outputMask(OperandImageOperands, stream[word++]);
  399. --numOperands;
  400. disassembleIds(numOperands);
  401. return;
  402. case OperandOptionalLiteral:
  403. case OperandVariableLiterals:
  404. if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
  405. (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
  406. out << BuiltInString(stream[word++]);
  407. --numOperands;
  408. ++op;
  409. }
  410. disassembleImmediates(numOperands);
  411. return;
  412. case OperandVariableIdLiteral:
  413. while (numOperands > 0) {
  414. out << std::endl;
  415. outputResultId(0);
  416. outputTypeId(0);
  417. outputIndent();
  418. out << " Type ";
  419. disassembleIds(1);
  420. out << ", member ";
  421. disassembleImmediates(1);
  422. numOperands -= 2;
  423. }
  424. return;
  425. case OperandVariableLiteralId:
  426. while (numOperands > 0) {
  427. out << std::endl;
  428. outputResultId(0);
  429. outputTypeId(0);
  430. outputIndent();
  431. out << " case ";
  432. disassembleImmediates(1);
  433. out << ": ";
  434. disassembleIds(1);
  435. numOperands -= 2;
  436. }
  437. return;
  438. case OperandLiteralNumber:
  439. disassembleImmediates(1);
  440. --numOperands;
  441. if (opCode == OpExtInst) {
  442. ExtInstSet extInstSet = GLSL450Inst;
  443. const char* name = idDescriptor[stream[word - 2]].c_str();
  444. if (strcmp("OpenCL.std", name) == 0) {
  445. extInstSet = OpenCLExtInst;
  446. } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
  447. extInstSet = OpenCLExtInst;
  448. } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
  449. extInstSet = NonSemanticDebugPrintfExtInst;
  450. } else if (strcmp("NonSemantic.Shader.DebugInfo.100", name) == 0) {
  451. extInstSet = NonSemanticShaderDebugInfo100;
  452. } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
  453. strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
  454. strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
  455. strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
  456. extInstSet = GLSLextAMDInst;
  457. } else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
  458. strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
  459. strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
  460. strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
  461. strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
  462. strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {
  463. extInstSet = GLSLextNVInst;
  464. }
  465. unsigned entrypoint = stream[word - 1];
  466. if (extInstSet == GLSL450Inst) {
  467. if (entrypoint < GLSLstd450Count) {
  468. out << "(" << GlslStd450DebugNames[entrypoint] << ")";
  469. }
  470. } else if (extInstSet == GLSLextAMDInst) {
  471. out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
  472. }
  473. else if (extInstSet == GLSLextNVInst) {
  474. out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
  475. } else if (extInstSet == NonSemanticDebugPrintfExtInst) {
  476. out << "(DebugPrintf)";
  477. } else if (extInstSet == NonSemanticShaderDebugInfo100) {
  478. out << "(" << NonSemanticShaderDebugInfo100GetDebugNames(entrypoint) << ")";
  479. }
  480. }
  481. break;
  482. case OperandOptionalLiteralString:
  483. case OperandLiteralString:
  484. numOperands -= disassembleString();
  485. break;
  486. case OperandVariableLiteralStrings:
  487. while (numOperands > 0)
  488. numOperands -= disassembleString();
  489. return;
  490. case OperandMemoryAccess:
  491. outputMask(OperandMemoryAccess, stream[word++]);
  492. --numOperands;
  493. // Aligned is the only memory access operand that uses an immediate
  494. // value, and it is also the first operand that uses a value at all.
  495. if (stream[word-1] & MemoryAccessAlignedMask) {
  496. disassembleImmediates(1);
  497. numOperands--;
  498. if (numOperands)
  499. out << " ";
  500. }
  501. disassembleIds(numOperands);
  502. return;
  503. default:
  504. assert(operandClass >= OperandSource && operandClass < OperandOpcode);
  505. if (OperandClassParams[operandClass].bitmask)
  506. outputMask(operandClass, stream[word++]);
  507. else
  508. out << OperandClassParams[operandClass].getName(stream[word++]);
  509. --numOperands;
  510. break;
  511. }
  512. }
  513. return;
  514. }
  515. static void GLSLstd450GetDebugNames(const char** names)
  516. {
  517. for (int i = 0; i < GLSLstd450Count; ++i)
  518. names[i] = "Unknown";
  519. names[GLSLstd450Round] = "Round";
  520. names[GLSLstd450RoundEven] = "RoundEven";
  521. names[GLSLstd450Trunc] = "Trunc";
  522. names[GLSLstd450FAbs] = "FAbs";
  523. names[GLSLstd450SAbs] = "SAbs";
  524. names[GLSLstd450FSign] = "FSign";
  525. names[GLSLstd450SSign] = "SSign";
  526. names[GLSLstd450Floor] = "Floor";
  527. names[GLSLstd450Ceil] = "Ceil";
  528. names[GLSLstd450Fract] = "Fract";
  529. names[GLSLstd450Radians] = "Radians";
  530. names[GLSLstd450Degrees] = "Degrees";
  531. names[GLSLstd450Sin] = "Sin";
  532. names[GLSLstd450Cos] = "Cos";
  533. names[GLSLstd450Tan] = "Tan";
  534. names[GLSLstd450Asin] = "Asin";
  535. names[GLSLstd450Acos] = "Acos";
  536. names[GLSLstd450Atan] = "Atan";
  537. names[GLSLstd450Sinh] = "Sinh";
  538. names[GLSLstd450Cosh] = "Cosh";
  539. names[GLSLstd450Tanh] = "Tanh";
  540. names[GLSLstd450Asinh] = "Asinh";
  541. names[GLSLstd450Acosh] = "Acosh";
  542. names[GLSLstd450Atanh] = "Atanh";
  543. names[GLSLstd450Atan2] = "Atan2";
  544. names[GLSLstd450Pow] = "Pow";
  545. names[GLSLstd450Exp] = "Exp";
  546. names[GLSLstd450Log] = "Log";
  547. names[GLSLstd450Exp2] = "Exp2";
  548. names[GLSLstd450Log2] = "Log2";
  549. names[GLSLstd450Sqrt] = "Sqrt";
  550. names[GLSLstd450InverseSqrt] = "InverseSqrt";
  551. names[GLSLstd450Determinant] = "Determinant";
  552. names[GLSLstd450MatrixInverse] = "MatrixInverse";
  553. names[GLSLstd450Modf] = "Modf";
  554. names[GLSLstd450ModfStruct] = "ModfStruct";
  555. names[GLSLstd450FMin] = "FMin";
  556. names[GLSLstd450SMin] = "SMin";
  557. names[GLSLstd450UMin] = "UMin";
  558. names[GLSLstd450FMax] = "FMax";
  559. names[GLSLstd450SMax] = "SMax";
  560. names[GLSLstd450UMax] = "UMax";
  561. names[GLSLstd450FClamp] = "FClamp";
  562. names[GLSLstd450SClamp] = "SClamp";
  563. names[GLSLstd450UClamp] = "UClamp";
  564. names[GLSLstd450FMix] = "FMix";
  565. names[GLSLstd450Step] = "Step";
  566. names[GLSLstd450SmoothStep] = "SmoothStep";
  567. names[GLSLstd450Fma] = "Fma";
  568. names[GLSLstd450Frexp] = "Frexp";
  569. names[GLSLstd450FrexpStruct] = "FrexpStruct";
  570. names[GLSLstd450Ldexp] = "Ldexp";
  571. names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";
  572. names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";
  573. names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";
  574. names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";
  575. names[GLSLstd450PackHalf2x16] = "PackHalf2x16";
  576. names[GLSLstd450PackDouble2x32] = "PackDouble2x32";
  577. names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";
  578. names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";
  579. names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";
  580. names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";
  581. names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";
  582. names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";
  583. names[GLSLstd450Length] = "Length";
  584. names[GLSLstd450Distance] = "Distance";
  585. names[GLSLstd450Cross] = "Cross";
  586. names[GLSLstd450Normalize] = "Normalize";
  587. names[GLSLstd450FaceForward] = "FaceForward";
  588. names[GLSLstd450Reflect] = "Reflect";
  589. names[GLSLstd450Refract] = "Refract";
  590. names[GLSLstd450FindILsb] = "FindILsb";
  591. names[GLSLstd450FindSMsb] = "FindSMsb";
  592. names[GLSLstd450FindUMsb] = "FindUMsb";
  593. names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";
  594. names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";
  595. names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
  596. names[GLSLstd450NMin] = "NMin";
  597. names[GLSLstd450NMax] = "NMax";
  598. names[GLSLstd450NClamp] = "NClamp";
  599. }
  600. static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
  601. {
  602. if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
  603. switch (entrypoint) {
  604. case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
  605. case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
  606. case WriteInvocationAMD: return "WriteInvocationAMD";
  607. case MbcntAMD: return "MbcntAMD";
  608. default: return "Bad";
  609. }
  610. } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
  611. switch (entrypoint) {
  612. case FMin3AMD: return "FMin3AMD";
  613. case UMin3AMD: return "UMin3AMD";
  614. case SMin3AMD: return "SMin3AMD";
  615. case FMax3AMD: return "FMax3AMD";
  616. case UMax3AMD: return "UMax3AMD";
  617. case SMax3AMD: return "SMax3AMD";
  618. case FMid3AMD: return "FMid3AMD";
  619. case UMid3AMD: return "UMid3AMD";
  620. case SMid3AMD: return "SMid3AMD";
  621. default: return "Bad";
  622. }
  623. } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
  624. switch (entrypoint) {
  625. case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
  626. default: return "Bad";
  627. }
  628. }
  629. else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
  630. switch (entrypoint) {
  631. case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
  632. case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
  633. case TimeAMD: return "TimeAMD";
  634. default:
  635. break;
  636. }
  637. }
  638. return "Bad";
  639. }
  640. static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
  641. {
  642. if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
  643. strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
  644. strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
  645. strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
  646. strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||
  647. strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||
  648. strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||
  649. strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {
  650. switch (entrypoint) {
  651. // NV builtins
  652. case BuiltInViewportMaskNV: return "ViewportMaskNV";
  653. case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
  654. case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
  655. case BuiltInPositionPerViewNV: return "PositionPerViewNV";
  656. case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
  657. case BuiltInBaryCoordNV: return "BaryCoordNV";
  658. case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
  659. case BuiltInTaskCountNV: return "TaskCountNV";
  660. case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
  661. case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
  662. case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
  663. case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
  664. case BuiltInLayerPerViewNV: return "LayerPerViewNV";
  665. case BuiltInMeshViewCountNV: return "MeshViewCountNV";
  666. case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
  667. // NV Capabilities
  668. case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
  669. case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
  670. case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
  671. case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
  672. case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
  673. case CapabilityMeshShadingNV: return "MeshShadingNV";
  674. case CapabilityImageFootprintNV: return "ImageFootprintNV";
  675. case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";
  676. // NV Decorations
  677. case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
  678. case DecorationPassthroughNV: return "PassthroughNV";
  679. case DecorationViewportRelativeNV: return "ViewportRelativeNV";
  680. case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
  681. case DecorationPerVertexNV: return "PerVertexNV";
  682. case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
  683. case DecorationPerViewNV: return "PerViewNV";
  684. case DecorationPerTaskNV: return "PerTaskNV";
  685. default: return "Bad";
  686. }
  687. }
  688. return "Bad";
  689. }
  690. static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned entrypoint)
  691. {
  692. switch (entrypoint) {
  693. case NonSemanticShaderDebugInfo100DebugInfoNone: return "DebugInfoNone";
  694. case NonSemanticShaderDebugInfo100DebugCompilationUnit: return "DebugCompilationUnit";
  695. case NonSemanticShaderDebugInfo100DebugTypeBasic: return "DebugTypeBasic";
  696. case NonSemanticShaderDebugInfo100DebugTypePointer: return "DebugTypePointer";
  697. case NonSemanticShaderDebugInfo100DebugTypeQualifier: return "DebugTypeQualifier";
  698. case NonSemanticShaderDebugInfo100DebugTypeArray: return "DebugTypeArray";
  699. case NonSemanticShaderDebugInfo100DebugTypeVector: return "DebugTypeVector";
  700. case NonSemanticShaderDebugInfo100DebugTypedef: return "DebugTypedef";
  701. case NonSemanticShaderDebugInfo100DebugTypeFunction: return "DebugTypeFunction";
  702. case NonSemanticShaderDebugInfo100DebugTypeEnum: return "DebugTypeEnum";
  703. case NonSemanticShaderDebugInfo100DebugTypeComposite: return "DebugTypeComposite";
  704. case NonSemanticShaderDebugInfo100DebugTypeMember: return "DebugTypeMember";
  705. case NonSemanticShaderDebugInfo100DebugTypeInheritance: return "DebugTypeInheritance";
  706. case NonSemanticShaderDebugInfo100DebugTypePtrToMember: return "DebugTypePtrToMember";
  707. case NonSemanticShaderDebugInfo100DebugTypeTemplate: return "DebugTypeTemplate";
  708. case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter: return "DebugTypeTemplateParameter";
  709. case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter: return "DebugTypeTemplateTemplateParameter";
  710. case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack: return "DebugTypeTemplateParameterPack";
  711. case NonSemanticShaderDebugInfo100DebugGlobalVariable: return "DebugGlobalVariable";
  712. case NonSemanticShaderDebugInfo100DebugFunctionDeclaration: return "DebugFunctionDeclaration";
  713. case NonSemanticShaderDebugInfo100DebugFunction: return "DebugFunction";
  714. case NonSemanticShaderDebugInfo100DebugLexicalBlock: return "DebugLexicalBlock";
  715. case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator: return "DebugLexicalBlockDiscriminator";
  716. case NonSemanticShaderDebugInfo100DebugScope: return "DebugScope";
  717. case NonSemanticShaderDebugInfo100DebugNoScope: return "DebugNoScope";
  718. case NonSemanticShaderDebugInfo100DebugInlinedAt: return "DebugInlinedAt";
  719. case NonSemanticShaderDebugInfo100DebugLocalVariable: return "DebugLocalVariable";
  720. case NonSemanticShaderDebugInfo100DebugInlinedVariable: return "DebugInlinedVariable";
  721. case NonSemanticShaderDebugInfo100DebugDeclare: return "DebugDeclare";
  722. case NonSemanticShaderDebugInfo100DebugValue: return "DebugValue";
  723. case NonSemanticShaderDebugInfo100DebugOperation: return "DebugOperation";
  724. case NonSemanticShaderDebugInfo100DebugExpression: return "DebugExpression";
  725. case NonSemanticShaderDebugInfo100DebugMacroDef: return "DebugMacroDef";
  726. case NonSemanticShaderDebugInfo100DebugMacroUndef: return "DebugMacroUndef";
  727. case NonSemanticShaderDebugInfo100DebugImportedEntity: return "DebugImportedEntity";
  728. case NonSemanticShaderDebugInfo100DebugSource: return "DebugSource";
  729. case NonSemanticShaderDebugInfo100DebugFunctionDefinition: return "DebugFunctionDefinition";
  730. case NonSemanticShaderDebugInfo100DebugSourceContinued: return "DebugSourceContinued";
  731. case NonSemanticShaderDebugInfo100DebugLine: return "DebugLine";
  732. case NonSemanticShaderDebugInfo100DebugNoLine: return "DebugNoLine";
  733. case NonSemanticShaderDebugInfo100DebugBuildIdentifier: return "DebugBuildIdentifier";
  734. case NonSemanticShaderDebugInfo100DebugStoragePath: return "DebugStoragePath";
  735. case NonSemanticShaderDebugInfo100DebugEntryPoint: return "DebugEntryPoint";
  736. case NonSemanticShaderDebugInfo100DebugTypeMatrix: return "DebugTypeMatrix";
  737. default: return "Bad";
  738. }
  739. return "Bad";
  740. }
  741. void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
  742. {
  743. SpirvStream SpirvStream(out, stream);
  744. spv::Parameterize();
  745. GLSLstd450GetDebugNames(GlslStd450DebugNames);
  746. SpirvStream.validate();
  747. SpirvStream.processInstructions();
  748. }
  749. }; // end namespace spv