Path: blob/master/thirdparty/glslang/SPIRV/disassemble.cpp
9903 views
//1// Copyright (C) 2014-2015 LunarG, Inc.2//3// All rights reserved.4//5// Redistribution and use in source and binary forms, with or without6// modification, are permitted provided that the following conditions7// are met:8//9// Redistributions of source code must retain the above copyright10// notice, this list of conditions and the following disclaimer.11//12// Redistributions in binary form must reproduce the above13// copyright notice, this list of conditions and the following14// disclaimer in the documentation and/or other materials provided15// with the distribution.16//17// Neither the name of 3Dlabs Inc. Ltd. nor the names of its18// contributors may be used to endorse or promote products derived19// from this software without specific prior written permission.20//21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS24// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE25// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,26// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,27// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;28// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER29// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT30// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN31// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE32// POSSIBILITY OF SUCH DAMAGE.3334//35// Disassembler for SPIR-V.36//3738#include <cstdlib>39#include <cstring>40#include <cassert>41#include <iomanip>42#include <stack>43#include <sstream>44#include <cstring>45#include <utility>4647#include "disassemble.h"48#include "doc.h"4950namespace spv {51extern "C" {52// Include C-based headers that don't have a namespace53#include "GLSL.std.450.h"54#include "GLSL.ext.AMD.h"55#include "GLSL.ext.NV.h"56#include "GLSL.ext.ARM.h"57#include "NonSemanticShaderDebugInfo100.h"58#include "GLSL.ext.QCOM.h"59}60}61const char* GlslStd450DebugNames[spv::GLSLstd450Count];6263namespace spv {6465static const char* GLSLextAMDGetDebugNames(const char*, unsigned);66static const char* GLSLextNVGetDebugNames(const char*, unsigned);67static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned);6869static void Kill(std::ostream& out, const char* message)70{71out << std::endl << "Disassembly failed: " << message << std::endl;72exit(1);73}7475// used to identify the extended instruction library imported when printing76enum ExtInstSet {77GLSL450Inst,78GLSLextAMDInst,79GLSLextNVInst,80OpenCLExtInst,81NonSemanticDebugPrintfExtInst,82NonSemanticDebugBreakExtInst,83NonSemanticShaderDebugInfo10084};8586// Container class for a single instance of a SPIR-V stream, with methods for disassembly.87class SpirvStream {88public:89SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }90virtual ~SpirvStream() { }9192void validate();93void processInstructions();9495protected:96SpirvStream(const SpirvStream&);97SpirvStream& operator=(const SpirvStream&);98Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }99100// Output methods101void outputIndent();102void formatId(Id id, std::stringstream&);103void outputResultId(Id id);104void outputTypeId(Id id);105void outputId(Id id);106void outputMask(OperandClass operandClass, unsigned mask);107void disassembleImmediates(int numOperands);108void disassembleIds(int numOperands);109std::pair<int, std::string> decodeString();110int disassembleString();111void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);112113// Data114std::ostream& out; // where to write the disassembly115const std::vector<unsigned int>& stream; // the actual word stream116int size; // the size of the word stream117int word; // the next word of the stream to read118119// map each <id> to the instruction that created it120Id bound;121std::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)122123std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>124125// schema126unsigned int schema;127128// stack of structured-merge points129std::stack<Id> nestedControl;130Id nextNestedControl; // need a slight delay for when we are nested131};132133void SpirvStream::validate()134{135size = (int)stream.size();136if (size < 4)137Kill(out, "stream is too short");138139// Magic number140if (stream[word++] != MagicNumber) {141out << "Bad magic number";142return;143}144145// Version146out << "// Module Version " << std::hex << stream[word++] << std::endl;147148// Generator's magic number149out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;150151// Result <id> bound152bound = stream[word++];153idInstruction.resize(bound);154idDescriptor.resize(bound);155out << "// Id's are bound by " << bound << std::endl;156out << std::endl;157158// Reserved schema, must be 0 for now159schema = stream[word++];160if (schema != 0)161Kill(out, "bad schema, must be 0");162}163164// Loop over all the instructions, in order, processing each.165// Boiler plate for each is handled here directly, the rest is dispatched.166void SpirvStream::processInstructions()167{168// Instructions169while (word < size) {170int instructionStart = word;171172// Instruction wordCount and opcode173unsigned int firstWord = stream[word];174unsigned wordCount = firstWord >> WordCountShift;175Op opCode = (Op)(firstWord & OpCodeMask);176int nextInst = word + wordCount;177++word;178179// Presence of full instruction180if (nextInst > size)181Kill(out, "stream instruction terminated too early");182183// Base for computing number of operands; will be updated as more is learned184unsigned numOperands = wordCount - 1;185186// Type <id>187Id typeId = 0;188if (InstructionDesc[opCode].hasType()) {189typeId = stream[word++];190--numOperands;191}192193// Result <id>194Id resultId = 0;195if (InstructionDesc[opCode].hasResult()) {196resultId = stream[word++];197--numOperands;198199// save instruction for future reference200idInstruction[resultId] = instructionStart;201}202203outputResultId(resultId);204outputTypeId(typeId);205outputIndent();206207// Hand off the Op and all its operands208disassembleInstruction(resultId, typeId, opCode, numOperands);209if (word != nextInst) {210out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;211word = nextInst;212}213out << std::endl;214}215}216217void SpirvStream::outputIndent()218{219for (int i = 0; i < (int)nestedControl.size(); ++i)220out << " ";221}222223void SpirvStream::formatId(Id id, std::stringstream& idStream)224{225if (id != 0) {226// On instructions with no IDs, this is called with "0", which does not227// have to be within ID bounds on null shaders.228if (id >= bound)229Kill(out, "Bad <id>");230231idStream << id;232if (idDescriptor[id].size() > 0)233idStream << "(" << idDescriptor[id] << ")";234}235}236237void SpirvStream::outputResultId(Id id)238{239const int width = 16;240std::stringstream idStream;241formatId(id, idStream);242out << std::setw(width) << std::right << idStream.str();243if (id != 0)244out << ":";245else246out << " ";247248if (nestedControl.size() && id == nestedControl.top())249nestedControl.pop();250}251252void SpirvStream::outputTypeId(Id id)253{254const int width = 12;255std::stringstream idStream;256formatId(id, idStream);257out << std::setw(width) << std::right << idStream.str() << " ";258}259260void SpirvStream::outputId(Id id)261{262if (id >= bound)263Kill(out, "Bad <id>");264265out << id;266if (idDescriptor[id].size() > 0)267out << "(" << idDescriptor[id] << ")";268}269270void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)271{272if (mask == 0)273out << "None";274else {275for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {276if (mask & (1 << m))277out << OperandClassParams[operandClass].getName(m) << " ";278}279}280}281282void SpirvStream::disassembleImmediates(int numOperands)283{284for (int i = 0; i < numOperands; ++i) {285out << stream[word++];286if (i < numOperands - 1)287out << " ";288}289}290291void SpirvStream::disassembleIds(int numOperands)292{293for (int i = 0; i < numOperands; ++i) {294outputId(stream[word++]);295if (i < numOperands - 1)296out << " ";297}298}299300// decode string from words at current position (non-consuming)301std::pair<int, std::string> SpirvStream::decodeString()302{303std::string res;304int wordPos = word;305char c;306bool done = false;307308do {309unsigned int content = stream[wordPos];310for (int charCount = 0; charCount < 4; ++charCount) {311c = content & 0xff;312content >>= 8;313if (c == '\0') {314done = true;315break;316}317res += c;318}319++wordPos;320} while(! done);321322return std::make_pair(wordPos - word, res);323}324325// return the number of operands consumed by the string326int SpirvStream::disassembleString()327{328out << " \"";329330std::pair<int, std::string> decoderes = decodeString();331332out << decoderes.second;333out << "\"";334335word += decoderes.first;336337return decoderes.first;338}339340void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)341{342// Process the opcode343344out << (OpcodeString(opCode) + 2); // leave out the "Op"345346if (opCode == OpLoopMerge || opCode == OpSelectionMerge)347nextNestedControl = stream[word];348else if (opCode == OpBranchConditional || opCode == OpSwitch) {349if (nextNestedControl) {350nestedControl.push(nextNestedControl);351nextNestedControl = 0;352}353} else if (opCode == OpExtInstImport) {354idDescriptor[resultId] = decodeString().second;355}356else {357if (resultId != 0 && idDescriptor[resultId].size() == 0) {358switch (opCode) {359case OpTypeInt:360switch (stream[word]) {361case 8: idDescriptor[resultId] = "int8_t"; break;362case 16: idDescriptor[resultId] = "int16_t"; break;363default: assert(0); [[fallthrough]];364case 32: idDescriptor[resultId] = "int"; break;365case 64: idDescriptor[resultId] = "int64_t"; break;366}367break;368case OpTypeFloat:369switch (stream[word]) {370case 16: idDescriptor[resultId] = "float16_t"; break;371default: assert(0); [[fallthrough]];372case 32: idDescriptor[resultId] = "float"; break;373case 64: idDescriptor[resultId] = "float64_t"; break;374}375break;376case OpTypeBool:377idDescriptor[resultId] = "bool";378break;379case OpTypeStruct:380idDescriptor[resultId] = "struct";381break;382case OpTypePointer:383idDescriptor[resultId] = "ptr";384break;385case OpTypeVector:386if (idDescriptor[stream[word]].size() > 0) {387idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);388if (strstr(idDescriptor[stream[word]].c_str(), "8")) {389idDescriptor[resultId].append("8");390}391if (strstr(idDescriptor[stream[word]].c_str(), "16")) {392idDescriptor[resultId].append("16");393}394if (strstr(idDescriptor[stream[word]].c_str(), "64")) {395idDescriptor[resultId].append("64");396}397}398idDescriptor[resultId].append("vec");399switch (stream[word + 1]) {400case 2: idDescriptor[resultId].append("2"); break;401case 3: idDescriptor[resultId].append("3"); break;402case 4: idDescriptor[resultId].append("4"); break;403case 8: idDescriptor[resultId].append("8"); break;404case 16: idDescriptor[resultId].append("16"); break;405case 32: idDescriptor[resultId].append("32"); break;406default: break;407}408break;409default:410break;411}412}413}414415// Process the operands. Note, a new context-dependent set could be416// swapped in mid-traversal.417418// Handle images specially, so can put out helpful strings.419if (opCode == OpTypeImage) {420out << " ";421disassembleIds(1);422out << " " << DimensionString((Dim)stream[word++]);423out << (stream[word++] != 0 ? " depth" : "");424out << (stream[word++] != 0 ? " array" : "");425out << (stream[word++] != 0 ? " multi-sampled" : "");426switch (stream[word++]) {427case 0: out << " runtime"; break;428case 1: out << " sampled"; break;429case 2: out << " nonsampled"; break;430}431out << " format:" << ImageFormatString((ImageFormat)stream[word++]);432433if (numOperands == 8) {434out << " " << AccessQualifierString(stream[word++]);435}436return;437}438439// Handle all the parameterized operands440for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {441out << " ";442OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);443switch (operandClass) {444case OperandId:445case OperandScope:446case OperandMemorySemantics:447disassembleIds(1);448--numOperands;449// Get names for printing "(XXX)" for readability, *after* this id450if (opCode == OpName)451idDescriptor[stream[word - 1]] = decodeString().second;452break;453case OperandVariableIds:454disassembleIds(numOperands);455return;456case OperandImageOperands:457outputMask(OperandImageOperands, stream[word++]);458--numOperands;459disassembleIds(numOperands);460return;461case OperandOptionalLiteral:462case OperandVariableLiterals:463if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||464(opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {465out << BuiltInString(stream[word++]);466--numOperands;467++op;468}469disassembleImmediates(numOperands);470return;471case OperandVariableIdLiteral:472while (numOperands > 0) {473out << std::endl;474outputResultId(0);475outputTypeId(0);476outputIndent();477out << " Type ";478disassembleIds(1);479out << ", member ";480disassembleImmediates(1);481numOperands -= 2;482}483return;484case OperandVariableLiteralId:485while (numOperands > 0) {486out << std::endl;487outputResultId(0);488outputTypeId(0);489outputIndent();490out << " case ";491disassembleImmediates(1);492out << ": ";493disassembleIds(1);494numOperands -= 2;495}496return;497case OperandLiteralNumber:498disassembleImmediates(1);499--numOperands;500if (opCode == OpExtInst) {501ExtInstSet extInstSet = GLSL450Inst;502const char* name = idDescriptor[stream[word - 2]].c_str();503if (strcmp("OpenCL.std", name) == 0) {504extInstSet = OpenCLExtInst;505} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {506extInstSet = OpenCLExtInst;507} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {508extInstSet = NonSemanticDebugPrintfExtInst;509} else if (strcmp("NonSemantic.DebugBreak", name) == 0) {510extInstSet = NonSemanticDebugBreakExtInst;511} else if (strcmp("NonSemantic.Shader.DebugInfo.100", name) == 0) {512extInstSet = NonSemanticShaderDebugInfo100;513} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||514strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||515strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||516strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {517extInstSet = GLSLextAMDInst;518} else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||519strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||520strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||521strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||522strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||523strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {524extInstSet = GLSLextNVInst;525}526unsigned entrypoint = stream[word - 1];527if (extInstSet == GLSL450Inst) {528if (entrypoint < GLSLstd450Count) {529out << "(" << GlslStd450DebugNames[entrypoint] << ")";530}531} else if (extInstSet == GLSLextAMDInst) {532out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";533}534else if (extInstSet == GLSLextNVInst) {535out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";536} else if (extInstSet == NonSemanticDebugPrintfExtInst) {537out << "(DebugPrintf)";538} else if (extInstSet == NonSemanticDebugBreakExtInst) {539out << "(DebugBreak)";540} else if (extInstSet == NonSemanticShaderDebugInfo100) {541out << "(" << NonSemanticShaderDebugInfo100GetDebugNames(entrypoint) << ")";542}543}544break;545case OperandOptionalLiteralString:546case OperandLiteralString:547numOperands -= disassembleString();548break;549case OperandVariableLiteralStrings:550while (numOperands > 0)551numOperands -= disassembleString();552return;553case OperandMemoryAccess:554outputMask(OperandMemoryAccess, stream[word++]);555--numOperands;556// Aligned is the only memory access operand that uses an immediate557// value, and it is also the first operand that uses a value at all.558if (stream[word-1] & MemoryAccessAlignedMask) {559disassembleImmediates(1);560numOperands--;561if (numOperands)562out << " ";563}564disassembleIds(numOperands);565return;566default:567assert(operandClass >= OperandSource && operandClass < OperandOpcode);568569if (OperandClassParams[operandClass].bitmask)570outputMask(operandClass, stream[word++]);571else572out << OperandClassParams[operandClass].getName(stream[word++]);573--numOperands;574575break;576}577}578579return;580}581582static void GLSLstd450GetDebugNames(const char** names)583{584for (int i = 0; i < GLSLstd450Count; ++i)585names[i] = "Unknown";586587names[GLSLstd450Round] = "Round";588names[GLSLstd450RoundEven] = "RoundEven";589names[GLSLstd450Trunc] = "Trunc";590names[GLSLstd450FAbs] = "FAbs";591names[GLSLstd450SAbs] = "SAbs";592names[GLSLstd450FSign] = "FSign";593names[GLSLstd450SSign] = "SSign";594names[GLSLstd450Floor] = "Floor";595names[GLSLstd450Ceil] = "Ceil";596names[GLSLstd450Fract] = "Fract";597names[GLSLstd450Radians] = "Radians";598names[GLSLstd450Degrees] = "Degrees";599names[GLSLstd450Sin] = "Sin";600names[GLSLstd450Cos] = "Cos";601names[GLSLstd450Tan] = "Tan";602names[GLSLstd450Asin] = "Asin";603names[GLSLstd450Acos] = "Acos";604names[GLSLstd450Atan] = "Atan";605names[GLSLstd450Sinh] = "Sinh";606names[GLSLstd450Cosh] = "Cosh";607names[GLSLstd450Tanh] = "Tanh";608names[GLSLstd450Asinh] = "Asinh";609names[GLSLstd450Acosh] = "Acosh";610names[GLSLstd450Atanh] = "Atanh";611names[GLSLstd450Atan2] = "Atan2";612names[GLSLstd450Pow] = "Pow";613names[GLSLstd450Exp] = "Exp";614names[GLSLstd450Log] = "Log";615names[GLSLstd450Exp2] = "Exp2";616names[GLSLstd450Log2] = "Log2";617names[GLSLstd450Sqrt] = "Sqrt";618names[GLSLstd450InverseSqrt] = "InverseSqrt";619names[GLSLstd450Determinant] = "Determinant";620names[GLSLstd450MatrixInverse] = "MatrixInverse";621names[GLSLstd450Modf] = "Modf";622names[GLSLstd450ModfStruct] = "ModfStruct";623names[GLSLstd450FMin] = "FMin";624names[GLSLstd450SMin] = "SMin";625names[GLSLstd450UMin] = "UMin";626names[GLSLstd450FMax] = "FMax";627names[GLSLstd450SMax] = "SMax";628names[GLSLstd450UMax] = "UMax";629names[GLSLstd450FClamp] = "FClamp";630names[GLSLstd450SClamp] = "SClamp";631names[GLSLstd450UClamp] = "UClamp";632names[GLSLstd450FMix] = "FMix";633names[GLSLstd450Step] = "Step";634names[GLSLstd450SmoothStep] = "SmoothStep";635names[GLSLstd450Fma] = "Fma";636names[GLSLstd450Frexp] = "Frexp";637names[GLSLstd450FrexpStruct] = "FrexpStruct";638names[GLSLstd450Ldexp] = "Ldexp";639names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";640names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";641names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";642names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";643names[GLSLstd450PackHalf2x16] = "PackHalf2x16";644names[GLSLstd450PackDouble2x32] = "PackDouble2x32";645names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";646names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";647names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";648names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";649names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";650names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";651names[GLSLstd450Length] = "Length";652names[GLSLstd450Distance] = "Distance";653names[GLSLstd450Cross] = "Cross";654names[GLSLstd450Normalize] = "Normalize";655names[GLSLstd450FaceForward] = "FaceForward";656names[GLSLstd450Reflect] = "Reflect";657names[GLSLstd450Refract] = "Refract";658names[GLSLstd450FindILsb] = "FindILsb";659names[GLSLstd450FindSMsb] = "FindSMsb";660names[GLSLstd450FindUMsb] = "FindUMsb";661names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";662names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";663names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";664names[GLSLstd450NMin] = "NMin";665names[GLSLstd450NMax] = "NMax";666names[GLSLstd450NClamp] = "NClamp";667}668669static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)670{671if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {672switch (entrypoint) {673case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";674case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";675case WriteInvocationAMD: return "WriteInvocationAMD";676case MbcntAMD: return "MbcntAMD";677default: return "Bad";678}679} else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {680switch (entrypoint) {681case FMin3AMD: return "FMin3AMD";682case UMin3AMD: return "UMin3AMD";683case SMin3AMD: return "SMin3AMD";684case FMax3AMD: return "FMax3AMD";685case UMax3AMD: return "UMax3AMD";686case SMax3AMD: return "SMax3AMD";687case FMid3AMD: return "FMid3AMD";688case UMid3AMD: return "UMid3AMD";689case SMid3AMD: return "SMid3AMD";690default: return "Bad";691}692} else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {693switch (entrypoint) {694case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";695default: return "Bad";696}697}698else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {699switch (entrypoint) {700case CubeFaceIndexAMD: return "CubeFaceIndexAMD";701case CubeFaceCoordAMD: return "CubeFaceCoordAMD";702case TimeAMD: return "TimeAMD";703default:704break;705}706}707708return "Bad";709}710711static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)712{713if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||714strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||715strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||716strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||717strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||718strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||719strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||720strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {721switch (entrypoint) {722// NV builtins723case BuiltInViewportMaskNV: return "ViewportMaskNV";724case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";725case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";726case BuiltInPositionPerViewNV: return "PositionPerViewNV";727case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";728case BuiltInBaryCoordNV: return "BaryCoordNV";729case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";730case BuiltInTaskCountNV: return "TaskCountNV";731case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";732case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";733case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";734case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";735case BuiltInLayerPerViewNV: return "LayerPerViewNV";736case BuiltInMeshViewCountNV: return "MeshViewCountNV";737case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";738739// NV Capabilities740case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";741case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";742case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";743case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";744case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";745case CapabilityMeshShadingNV: return "MeshShadingNV";746case CapabilityImageFootprintNV: return "ImageFootprintNV";747case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";748749// NV Decorations750case DecorationOverrideCoverageNV: return "OverrideCoverageNV";751case DecorationPassthroughNV: return "PassthroughNV";752case DecorationViewportRelativeNV: return "ViewportRelativeNV";753case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";754case DecorationPerVertexNV: return "PerVertexNV";755case DecorationPerPrimitiveNV: return "PerPrimitiveNV";756case DecorationPerViewNV: return "PerViewNV";757case DecorationPerTaskNV: return "PerTaskNV";758759default: return "Bad";760}761}762return "Bad";763}764765static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned entrypoint)766{767switch (entrypoint) {768case NonSemanticShaderDebugInfo100DebugInfoNone: return "DebugInfoNone";769case NonSemanticShaderDebugInfo100DebugCompilationUnit: return "DebugCompilationUnit";770case NonSemanticShaderDebugInfo100DebugTypeBasic: return "DebugTypeBasic";771case NonSemanticShaderDebugInfo100DebugTypePointer: return "DebugTypePointer";772case NonSemanticShaderDebugInfo100DebugTypeQualifier: return "DebugTypeQualifier";773case NonSemanticShaderDebugInfo100DebugTypeArray: return "DebugTypeArray";774case NonSemanticShaderDebugInfo100DebugTypeVector: return "DebugTypeVector";775case NonSemanticShaderDebugInfo100DebugTypedef: return "DebugTypedef";776case NonSemanticShaderDebugInfo100DebugTypeFunction: return "DebugTypeFunction";777case NonSemanticShaderDebugInfo100DebugTypeEnum: return "DebugTypeEnum";778case NonSemanticShaderDebugInfo100DebugTypeComposite: return "DebugTypeComposite";779case NonSemanticShaderDebugInfo100DebugTypeMember: return "DebugTypeMember";780case NonSemanticShaderDebugInfo100DebugTypeInheritance: return "DebugTypeInheritance";781case NonSemanticShaderDebugInfo100DebugTypePtrToMember: return "DebugTypePtrToMember";782case NonSemanticShaderDebugInfo100DebugTypeTemplate: return "DebugTypeTemplate";783case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter: return "DebugTypeTemplateParameter";784case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter: return "DebugTypeTemplateTemplateParameter";785case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack: return "DebugTypeTemplateParameterPack";786case NonSemanticShaderDebugInfo100DebugGlobalVariable: return "DebugGlobalVariable";787case NonSemanticShaderDebugInfo100DebugFunctionDeclaration: return "DebugFunctionDeclaration";788case NonSemanticShaderDebugInfo100DebugFunction: return "DebugFunction";789case NonSemanticShaderDebugInfo100DebugLexicalBlock: return "DebugLexicalBlock";790case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator: return "DebugLexicalBlockDiscriminator";791case NonSemanticShaderDebugInfo100DebugScope: return "DebugScope";792case NonSemanticShaderDebugInfo100DebugNoScope: return "DebugNoScope";793case NonSemanticShaderDebugInfo100DebugInlinedAt: return "DebugInlinedAt";794case NonSemanticShaderDebugInfo100DebugLocalVariable: return "DebugLocalVariable";795case NonSemanticShaderDebugInfo100DebugInlinedVariable: return "DebugInlinedVariable";796case NonSemanticShaderDebugInfo100DebugDeclare: return "DebugDeclare";797case NonSemanticShaderDebugInfo100DebugValue: return "DebugValue";798case NonSemanticShaderDebugInfo100DebugOperation: return "DebugOperation";799case NonSemanticShaderDebugInfo100DebugExpression: return "DebugExpression";800case NonSemanticShaderDebugInfo100DebugMacroDef: return "DebugMacroDef";801case NonSemanticShaderDebugInfo100DebugMacroUndef: return "DebugMacroUndef";802case NonSemanticShaderDebugInfo100DebugImportedEntity: return "DebugImportedEntity";803case NonSemanticShaderDebugInfo100DebugSource: return "DebugSource";804case NonSemanticShaderDebugInfo100DebugFunctionDefinition: return "DebugFunctionDefinition";805case NonSemanticShaderDebugInfo100DebugSourceContinued: return "DebugSourceContinued";806case NonSemanticShaderDebugInfo100DebugLine: return "DebugLine";807case NonSemanticShaderDebugInfo100DebugNoLine: return "DebugNoLine";808case NonSemanticShaderDebugInfo100DebugBuildIdentifier: return "DebugBuildIdentifier";809case NonSemanticShaderDebugInfo100DebugStoragePath: return "DebugStoragePath";810case NonSemanticShaderDebugInfo100DebugEntryPoint: return "DebugEntryPoint";811case NonSemanticShaderDebugInfo100DebugTypeMatrix: return "DebugTypeMatrix";812default: return "Bad";813}814815return "Bad";816}817818void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)819{820SpirvStream SpirvStream(out, stream);821spv::Parameterize();822GLSLstd450GetDebugNames(GlslStd450DebugNames);823SpirvStream.validate();824SpirvStream.processInstructions();825}826827}; // end namespace spv828829830