123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- //
- // Copyright (C) 2014-2015 LunarG, Inc.
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions
- // are met:
- //
- // Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- //
- // Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following
- // disclaimer in the documentation and/or other materials provided
- // with the distribution.
- //
- // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
- // contributors may be used to endorse or promote products derived
- // from this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- //
- // Disassembler for SPIR-V.
- //
- #include <cstdlib>
- #include <cstring>
- #include <cassert>
- #include <iomanip>
- #include <stack>
- #include <sstream>
- #include <cstring>
- #include "disassemble.h"
- #include "doc.h"
- #include "SpvTools.h"
- namespace spv {
- extern "C" {
- // Include C-based headers that don't have a namespace
- #include "GLSL.std.450.h"
- #ifdef AMD_EXTENSIONS
- #include "GLSL.ext.AMD.h"
- #endif
- #ifdef NV_EXTENSIONS
- #include "GLSL.ext.NV.h"
- #endif
- }
- }
- const char* GlslStd450DebugNames[spv::GLSLstd450Count];
- namespace spv {
- #ifdef AMD_EXTENSIONS
- static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
- #endif
- #ifdef NV_EXTENSIONS
- static const char* GLSLextNVGetDebugNames(const char*, unsigned);
- #endif
- static void Kill(std::ostream& out, const char* message)
- {
- out << std::endl << "Disassembly failed: " << message << std::endl;
- exit(1);
- }
- // used to identify the extended instruction library imported when printing
- enum ExtInstSet {
- GLSL450Inst,
- #ifdef AMD_EXTENSIONS
- GLSLextAMDInst,
- #endif
- #ifdef NV_EXTENSIONS
- GLSLextNVInst,
- #endif
- OpenCLExtInst,
- };
- // Container class for a single instance of a SPIR-V stream, with methods for disassembly.
- class SpirvStream {
- public:
- SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
- virtual ~SpirvStream() { }
- void validate();
- void processInstructions();
- protected:
- SpirvStream(const SpirvStream&);
- SpirvStream& operator=(const SpirvStream&);
- Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
- // Output methods
- void outputIndent();
- void formatId(Id id, std::stringstream&);
- void outputResultId(Id id);
- void outputTypeId(Id id);
- void outputId(Id id);
- void outputMask(OperandClass operandClass, unsigned mask);
- void disassembleImmediates(int numOperands);
- void disassembleIds(int numOperands);
- int disassembleString();
- void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
- // Data
- std::ostream& out; // where to write the disassembly
- const std::vector<unsigned int>& stream; // the actual word stream
- int size; // the size of the word stream
- int word; // the next word of the stream to read
- // map each <id> to the instruction that created it
- Id bound;
- 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)
- std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>
- // schema
- unsigned int schema;
- // stack of structured-merge points
- std::stack<Id> nestedControl;
- Id nextNestedControl; // need a slight delay for when we are nested
- };
- void SpirvStream::validate()
- {
- size = (int)stream.size();
- if (size < 4)
- Kill(out, "stream is too short");
- // Magic number
- if (stream[word++] != MagicNumber) {
- out << "Bad magic number";
- return;
- }
- // Version
- out << "// Module Version " << std::hex << stream[word++] << std::endl;
- // Generator's magic number
- out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;
- // Result <id> bound
- bound = stream[word++];
- idInstruction.resize(bound);
- idDescriptor.resize(bound);
- out << "// Id's are bound by " << bound << std::endl;
- out << std::endl;
- // Reserved schema, must be 0 for now
- schema = stream[word++];
- if (schema != 0)
- Kill(out, "bad schema, must be 0");
- }
- // Loop over all the instructions, in order, processing each.
- // Boiler plate for each is handled here directly, the rest is dispatched.
- void SpirvStream::processInstructions()
- {
- // Instructions
- while (word < size) {
- int instructionStart = word;
- // Instruction wordCount and opcode
- unsigned int firstWord = stream[word];
- unsigned wordCount = firstWord >> WordCountShift;
- Op opCode = (Op)(firstWord & OpCodeMask);
- int nextInst = word + wordCount;
- ++word;
- // Presence of full instruction
- if (nextInst > size)
- Kill(out, "stream instruction terminated too early");
- // Base for computing number of operands; will be updated as more is learned
- unsigned numOperands = wordCount - 1;
- // Type <id>
- Id typeId = 0;
- if (InstructionDesc[opCode].hasType()) {
- typeId = stream[word++];
- --numOperands;
- }
- // Result <id>
- Id resultId = 0;
- if (InstructionDesc[opCode].hasResult()) {
- resultId = stream[word++];
- --numOperands;
- // save instruction for future reference
- idInstruction[resultId] = instructionStart;
- }
- outputResultId(resultId);
- outputTypeId(typeId);
- outputIndent();
- // Hand off the Op and all its operands
- disassembleInstruction(resultId, typeId, opCode, numOperands);
- if (word != nextInst) {
- out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
- word = nextInst;
- }
- out << std::endl;
- }
- }
- void SpirvStream::outputIndent()
- {
- for (int i = 0; i < (int)nestedControl.size(); ++i)
- out << " ";
- }
- void SpirvStream::formatId(Id id, std::stringstream& idStream)
- {
- if (id != 0) {
- // On instructions with no IDs, this is called with "0", which does not
- // have to be within ID bounds on null shaders.
- if (id >= bound)
- Kill(out, "Bad <id>");
- idStream << id;
- if (idDescriptor[id].size() > 0)
- idStream << "(" << idDescriptor[id] << ")";
- }
- }
- void SpirvStream::outputResultId(Id id)
- {
- const int width = 16;
- std::stringstream idStream;
- formatId(id, idStream);
- out << std::setw(width) << std::right << idStream.str();
- if (id != 0)
- out << ":";
- else
- out << " ";
- if (nestedControl.size() && id == nestedControl.top())
- nestedControl.pop();
- }
- void SpirvStream::outputTypeId(Id id)
- {
- const int width = 12;
- std::stringstream idStream;
- formatId(id, idStream);
- out << std::setw(width) << std::right << idStream.str() << " ";
- }
- void SpirvStream::outputId(Id id)
- {
- if (id >= bound)
- Kill(out, "Bad <id>");
- out << id;
- if (idDescriptor[id].size() > 0)
- out << "(" << idDescriptor[id] << ")";
- }
- void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)
- {
- if (mask == 0)
- out << "None";
- else {
- for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
- if (mask & (1 << m))
- out << OperandClassParams[operandClass].getName(m) << " ";
- }
- }
- }
- void SpirvStream::disassembleImmediates(int numOperands)
- {
- for (int i = 0; i < numOperands; ++i) {
- out << stream[word++];
- if (i < numOperands - 1)
- out << " ";
- }
- }
- void SpirvStream::disassembleIds(int numOperands)
- {
- for (int i = 0; i < numOperands; ++i) {
- outputId(stream[word++]);
- if (i < numOperands - 1)
- out << " ";
- }
- }
- // return the number of operands consumed by the string
- int SpirvStream::disassembleString()
- {
- int startWord = word;
- out << " \"";
- const char* wordString;
- bool done = false;
- do {
- unsigned int content = stream[word];
- wordString = (const char*)&content;
- for (int charCount = 0; charCount < 4; ++charCount) {
- if (*wordString == 0) {
- done = true;
- break;
- }
- out << *(wordString++);
- }
- ++word;
- } while (! done);
- out << "\"";
- return word - startWord;
- }
- void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
- {
- // Process the opcode
- out << (OpcodeString(opCode) + 2); // leave out the "Op"
- if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
- nextNestedControl = stream[word];
- else if (opCode == OpBranchConditional || opCode == OpSwitch) {
- if (nextNestedControl) {
- nestedControl.push(nextNestedControl);
- nextNestedControl = 0;
- }
- } else if (opCode == OpExtInstImport) {
- idDescriptor[resultId] = (const char*)(&stream[word]);
- }
- else {
- if (resultId != 0 && idDescriptor[resultId].size() == 0) {
- switch (opCode) {
- case OpTypeInt:
- switch (stream[word]) {
- case 8: idDescriptor[resultId] = "int8_t"; break;
- case 16: idDescriptor[resultId] = "int16_t"; break;
- default: assert(0); // fallthrough
- case 32: idDescriptor[resultId] = "int"; break;
- case 64: idDescriptor[resultId] = "int64_t"; break;
- }
- break;
- case OpTypeFloat:
- switch (stream[word]) {
- case 16: idDescriptor[resultId] = "float16_t"; break;
- default: assert(0); // fallthrough
- case 32: idDescriptor[resultId] = "float"; break;
- case 64: idDescriptor[resultId] = "float64_t"; break;
- }
- break;
- case OpTypeBool:
- idDescriptor[resultId] = "bool";
- break;
- case OpTypeStruct:
- idDescriptor[resultId] = "struct";
- break;
- case OpTypePointer:
- idDescriptor[resultId] = "ptr";
- break;
- case OpTypeVector:
- if (idDescriptor[stream[word]].size() > 0) {
- idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
- if (strstr(idDescriptor[stream[word]].c_str(), "8")) {
- idDescriptor[resultId].append("8");
- }
- if (strstr(idDescriptor[stream[word]].c_str(), "16")) {
- idDescriptor[resultId].append("16");
- }
- if (strstr(idDescriptor[stream[word]].c_str(), "64")) {
- idDescriptor[resultId].append("64");
- }
- }
- idDescriptor[resultId].append("vec");
- switch (stream[word + 1]) {
- case 2: idDescriptor[resultId].append("2"); break;
- case 3: idDescriptor[resultId].append("3"); break;
- case 4: idDescriptor[resultId].append("4"); break;
- case 8: idDescriptor[resultId].append("8"); break;
- case 16: idDescriptor[resultId].append("16"); break;
- case 32: idDescriptor[resultId].append("32"); break;
- default: break;
- }
- break;
- default:
- break;
- }
- }
- }
- // Process the operands. Note, a new context-dependent set could be
- // swapped in mid-traversal.
- // Handle images specially, so can put out helpful strings.
- if (opCode == OpTypeImage) {
- out << " ";
- disassembleIds(1);
- out << " " << DimensionString((Dim)stream[word++]);
- out << (stream[word++] != 0 ? " depth" : "");
- out << (stream[word++] != 0 ? " array" : "");
- out << (stream[word++] != 0 ? " multi-sampled" : "");
- switch (stream[word++]) {
- case 0: out << " runtime"; break;
- case 1: out << " sampled"; break;
- case 2: out << " nonsampled"; break;
- }
- out << " format:" << ImageFormatString((ImageFormat)stream[word++]);
- if (numOperands == 8) {
- out << " " << AccessQualifierString(stream[word++]);
- }
- return;
- }
- // Handle all the parameterized operands
- for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
- out << " ";
- OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
- switch (operandClass) {
- case OperandId:
- case OperandScope:
- case OperandMemorySemantics:
- disassembleIds(1);
- --numOperands;
- // Get names for printing "(XXX)" for readability, *after* this id
- if (opCode == OpName)
- idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
- break;
- case OperandVariableIds:
- disassembleIds(numOperands);
- return;
- case OperandImageOperands:
- outputMask(OperandImageOperands, stream[word++]);
- --numOperands;
- disassembleIds(numOperands);
- return;
- case OperandOptionalLiteral:
- case OperandVariableLiterals:
- if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
- (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
- out << BuiltInString(stream[word++]);
- --numOperands;
- ++op;
- }
- disassembleImmediates(numOperands);
- return;
- case OperandVariableIdLiteral:
- while (numOperands > 0) {
- out << std::endl;
- outputResultId(0);
- outputTypeId(0);
- outputIndent();
- out << " Type ";
- disassembleIds(1);
- out << ", member ";
- disassembleImmediates(1);
- numOperands -= 2;
- }
- return;
- case OperandVariableLiteralId:
- while (numOperands > 0) {
- out << std::endl;
- outputResultId(0);
- outputTypeId(0);
- outputIndent();
- out << " case ";
- disassembleImmediates(1);
- out << ": ";
- disassembleIds(1);
- numOperands -= 2;
- }
- return;
- case OperandLiteralNumber:
- disassembleImmediates(1);
- --numOperands;
- if (opCode == OpExtInst) {
- ExtInstSet extInstSet = GLSL450Inst;
- const char* name = idDescriptor[stream[word - 2]].c_str();
- if (0 == memcmp("OpenCL", name, 6)) {
- extInstSet = OpenCLExtInst;
- #ifdef AMD_EXTENSIONS
- } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
- strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
- strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
- strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
- extInstSet = GLSLextAMDInst;
- #endif
- #ifdef NV_EXTENSIONS
- }else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
- strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
- strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
- strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
- strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
- strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {
- extInstSet = GLSLextNVInst;
- #endif
- }
- unsigned entrypoint = stream[word - 1];
- if (extInstSet == GLSL450Inst) {
- if (entrypoint < GLSLstd450Count) {
- out << "(" << GlslStd450DebugNames[entrypoint] << ")";
- }
- #ifdef AMD_EXTENSIONS
- } else if (extInstSet == GLSLextAMDInst) {
- out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
- #endif
- #ifdef NV_EXTENSIONS
- }
- else if (extInstSet == GLSLextNVInst) {
- out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
- #endif
- }
- }
- break;
- case OperandOptionalLiteralString:
- case OperandLiteralString:
- numOperands -= disassembleString();
- break;
- case OperandMemoryAccess:
- outputMask(OperandMemoryAccess, stream[word++]);
- --numOperands;
- // Aligned is the only memory access operand that uses an immediate
- // value, and it is also the first operand that uses a value at all.
- if (stream[word-1] & MemoryAccessAlignedMask) {
- disassembleImmediates(1);
- numOperands--;
- if (numOperands)
- out << " ";
- }
- disassembleIds(numOperands);
- return;
- default:
- assert(operandClass >= OperandSource && operandClass < OperandOpcode);
- if (OperandClassParams[operandClass].bitmask)
- outputMask(operandClass, stream[word++]);
- else
- out << OperandClassParams[operandClass].getName(stream[word++]);
- --numOperands;
- break;
- }
- }
- return;
- }
- static void GLSLstd450GetDebugNames(const char** names)
- {
- for (int i = 0; i < GLSLstd450Count; ++i)
- names[i] = "Unknown";
- names[GLSLstd450Round] = "Round";
- names[GLSLstd450RoundEven] = "RoundEven";
- names[GLSLstd450Trunc] = "Trunc";
- names[GLSLstd450FAbs] = "FAbs";
- names[GLSLstd450SAbs] = "SAbs";
- names[GLSLstd450FSign] = "FSign";
- names[GLSLstd450SSign] = "SSign";
- names[GLSLstd450Floor] = "Floor";
- names[GLSLstd450Ceil] = "Ceil";
- names[GLSLstd450Fract] = "Fract";
- names[GLSLstd450Radians] = "Radians";
- names[GLSLstd450Degrees] = "Degrees";
- names[GLSLstd450Sin] = "Sin";
- names[GLSLstd450Cos] = "Cos";
- names[GLSLstd450Tan] = "Tan";
- names[GLSLstd450Asin] = "Asin";
- names[GLSLstd450Acos] = "Acos";
- names[GLSLstd450Atan] = "Atan";
- names[GLSLstd450Sinh] = "Sinh";
- names[GLSLstd450Cosh] = "Cosh";
- names[GLSLstd450Tanh] = "Tanh";
- names[GLSLstd450Asinh] = "Asinh";
- names[GLSLstd450Acosh] = "Acosh";
- names[GLSLstd450Atanh] = "Atanh";
- names[GLSLstd450Atan2] = "Atan2";
- names[GLSLstd450Pow] = "Pow";
- names[GLSLstd450Exp] = "Exp";
- names[GLSLstd450Log] = "Log";
- names[GLSLstd450Exp2] = "Exp2";
- names[GLSLstd450Log2] = "Log2";
- names[GLSLstd450Sqrt] = "Sqrt";
- names[GLSLstd450InverseSqrt] = "InverseSqrt";
- names[GLSLstd450Determinant] = "Determinant";
- names[GLSLstd450MatrixInverse] = "MatrixInverse";
- names[GLSLstd450Modf] = "Modf";
- names[GLSLstd450ModfStruct] = "ModfStruct";
- names[GLSLstd450FMin] = "FMin";
- names[GLSLstd450SMin] = "SMin";
- names[GLSLstd450UMin] = "UMin";
- names[GLSLstd450FMax] = "FMax";
- names[GLSLstd450SMax] = "SMax";
- names[GLSLstd450UMax] = "UMax";
- names[GLSLstd450FClamp] = "FClamp";
- names[GLSLstd450SClamp] = "SClamp";
- names[GLSLstd450UClamp] = "UClamp";
- names[GLSLstd450FMix] = "FMix";
- names[GLSLstd450Step] = "Step";
- names[GLSLstd450SmoothStep] = "SmoothStep";
- names[GLSLstd450Fma] = "Fma";
- names[GLSLstd450Frexp] = "Frexp";
- names[GLSLstd450FrexpStruct] = "FrexpStruct";
- names[GLSLstd450Ldexp] = "Ldexp";
- names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";
- names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";
- names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";
- names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";
- names[GLSLstd450PackHalf2x16] = "PackHalf2x16";
- names[GLSLstd450PackDouble2x32] = "PackDouble2x32";
- names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";
- names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";
- names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";
- names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";
- names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";
- names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";
- names[GLSLstd450Length] = "Length";
- names[GLSLstd450Distance] = "Distance";
- names[GLSLstd450Cross] = "Cross";
- names[GLSLstd450Normalize] = "Normalize";
- names[GLSLstd450FaceForward] = "FaceForward";
- names[GLSLstd450Reflect] = "Reflect";
- names[GLSLstd450Refract] = "Refract";
- names[GLSLstd450FindILsb] = "FindILsb";
- names[GLSLstd450FindSMsb] = "FindSMsb";
- names[GLSLstd450FindUMsb] = "FindUMsb";
- names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";
- names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";
- names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
- names[GLSLstd450NMin] = "NMin";
- names[GLSLstd450NMax] = "NMax";
- names[GLSLstd450NClamp] = "NClamp";
- }
- #ifdef AMD_EXTENSIONS
- static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
- {
- if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
- switch (entrypoint) {
- case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
- case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
- case WriteInvocationAMD: return "WriteInvocationAMD";
- case MbcntAMD: return "MbcntAMD";
- default: return "Bad";
- }
- } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
- switch (entrypoint) {
- case FMin3AMD: return "FMin3AMD";
- case UMin3AMD: return "UMin3AMD";
- case SMin3AMD: return "SMin3AMD";
- case FMax3AMD: return "FMax3AMD";
- case UMax3AMD: return "UMax3AMD";
- case SMax3AMD: return "SMax3AMD";
- case FMid3AMD: return "FMid3AMD";
- case UMid3AMD: return "UMid3AMD";
- case SMid3AMD: return "SMid3AMD";
- default: return "Bad";
- }
- } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
- switch (entrypoint) {
- case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
- default: return "Bad";
- }
- }
- else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
- switch (entrypoint) {
- case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
- case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
- case TimeAMD: return "TimeAMD";
- default:
- break;
- }
- }
- return "Bad";
- }
- #endif
- #ifdef NV_EXTENSIONS
- static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
- {
- if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
- strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
- strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
- strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
- strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||
- strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||
- strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||
- strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {
- switch (entrypoint) {
- // NV builtins
- case BuiltInViewportMaskNV: return "ViewportMaskNV";
- case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
- case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
- case BuiltInPositionPerViewNV: return "PositionPerViewNV";
- case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
- case BuiltInBaryCoordNV: return "BaryCoordNV";
- case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
- case BuiltInTaskCountNV: return "TaskCountNV";
- case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
- case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
- case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
- case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
- case BuiltInLayerPerViewNV: return "LayerPerViewNV";
- case BuiltInMeshViewCountNV: return "MeshViewCountNV";
- case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
- // NV Capabilities
- case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
- case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
- case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
- case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
- case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
- case CapabilityMeshShadingNV: return "MeshShadingNV";
- case CapabilityImageFootprintNV: return "ImageFootprintNV";
- case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";
- // NV Decorations
- case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
- case DecorationPassthroughNV: return "PassthroughNV";
- case DecorationViewportRelativeNV: return "ViewportRelativeNV";
- case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
- case DecorationPerVertexNV: return "PerVertexNV";
- case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
- case DecorationPerViewNV: return "PerViewNV";
- case DecorationPerTaskNV: return "PerTaskNV";
- default: return "Bad";
- }
- }
- return "Bad";
- }
- #endif
- void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
- {
- SpirvStream SpirvStream(out, stream);
- spv::Parameterize();
- GLSLstd450GetDebugNames(GlslStd450DebugNames);
- SpirvStream.validate();
- SpirvStream.processInstructions();
- }
- }; // end namespace spv
|