Path: blob/master/thirdparty/glslang/SPIRV/disassemble.cpp
21453 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 <cstdint>39#include <cstdlib>40#include <cstring>41#include <cassert>42#include <iomanip>43#include <stack>44#include <sstream>45#include <cstring>46#include <utility>4748#include "disassemble.h"49#include "doc.h"50#include "spvUtil.h"5152namespace spv {53extern "C" {54// Include C-based headers that don't have a namespace55#include "GLSL.std.450.h"56#include "GLSL.ext.AMD.h"57#include "GLSL.ext.NV.h"58#include "GLSL.ext.ARM.h"59#include "NonSemanticShaderDebugInfo100.h"60#include "GLSL.ext.QCOM.h"61}62}63static const char* GlslStd450DebugNames[spv::GLSLstd450Count];6465namespace spv {6667static const char* GLSLextAMDGetDebugNames(const char*, unsigned);68static const char* GLSLextNVGetDebugNames(const char*, unsigned);69static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned);7071static void Kill(std::ostream& out, const char* message)72{73out << std::endl << "Disassembly failed: " << message << std::endl;74exit(1);75}7677// used to identify the extended instruction library imported when printing78enum ExtInstSet {79GLSL450Inst,80GLSLextAMDInst,81GLSLextNVInst,82OpenCLExtInst,83NonSemanticDebugPrintfExtInst,84NonSemanticDebugBreakExtInst,85NonSemanticShaderDebugInfo10086};8788// Container class for a single instance of a SPIR-V stream, with methods for disassembly.89class SpirvStream {90public:91SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }92virtual ~SpirvStream() { }9394void validate();95void processInstructions();9697protected:98SpirvStream(const SpirvStream&);99SpirvStream& operator=(const SpirvStream&);100Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : Op::OpNop; }101102// Output methods103void outputIndent();104void formatId(Id id, std::stringstream&);105void outputResultId(Id id);106void outputTypeId(Id id);107void outputId(Id id);108void outputMask(OperandClass operandClass, unsigned mask);109void disassembleImmediates(int numOperands);110void disassembleIds(int numOperands);111std::pair<int, std::string> decodeString();112int disassembleString();113void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);114115// Data116std::ostream& out; // where to write the disassembly117const std::vector<unsigned int>& stream; // the actual word stream118int size; // the size of the word stream119int word; // the next word of the stream to read120121// map each <id> to the instruction that created it122Id bound;123std::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)124125std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>126127// schema128unsigned int schema;129130// stack of structured-merge points131std::stack<Id> nestedControl;132Id nextNestedControl; // need a slight delay for when we are nested133};134135void SpirvStream::validate()136{137size = (int)stream.size();138if (size < 4)139Kill(out, "stream is too short");140141// Magic number142if (stream[word++] != MagicNumber) {143out << "Bad magic number";144return;145}146147// Version148out << "// Module Version " << std::hex << stream[word++] << std::endl;149150// Generator's magic number151out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;152153// Result <id> bound154bound = stream[word++];155idInstruction.resize(bound);156idDescriptor.resize(bound);157out << "// Id's are bound by " << bound << std::endl;158out << std::endl;159160// Reserved schema, must be 0 for now161schema = stream[word++];162if (schema != 0)163Kill(out, "bad schema, must be 0");164}165166// Loop over all the instructions, in order, processing each.167// Boiler plate for each is handled here directly, the rest is dispatched.168void SpirvStream::processInstructions()169{170// Instructions171while (word < size) {172int instructionStart = word;173174// Instruction wordCount and opcode175unsigned int firstWord = stream[word];176unsigned wordCount = firstWord >> WordCountShift;177Op opCode = (Op)(firstWord & OpCodeMask);178int nextInst = word + wordCount;179++word;180181// Presence of full instruction182if (nextInst > size)183Kill(out, "stream instruction terminated too early");184185// Base for computing number of operands; will be updated as more is learned186unsigned numOperands = wordCount - 1;187188// Type <id>189Id typeId = 0;190if (InstructionDesc[enumCast(opCode)].hasType()) {191typeId = stream[word++];192--numOperands;193}194195// Result <id>196Id resultId = 0;197if (InstructionDesc[enumCast(opCode)].hasResult()) {198resultId = stream[word++];199--numOperands;200201// save instruction for future reference202idInstruction[resultId] = instructionStart;203}204205outputResultId(resultId);206outputTypeId(typeId);207outputIndent();208209// Hand off the Op and all its operands210disassembleInstruction(resultId, typeId, opCode, numOperands);211if (word != nextInst) {212out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;213word = nextInst;214}215out << std::endl;216}217}218219void SpirvStream::outputIndent()220{221for (int i = 0; i < (int)nestedControl.size(); ++i)222out << " ";223}224225void SpirvStream::formatId(Id id, std::stringstream& idStream)226{227if (id != 0) {228// On instructions with no IDs, this is called with "0", which does not229// have to be within ID bounds on null shaders.230if (id >= bound)231Kill(out, "Bad <id>");232233idStream << id;234if (idDescriptor[id].size() > 0)235idStream << "(" << idDescriptor[id] << ")";236}237}238239void SpirvStream::outputResultId(Id id)240{241const int width = 16;242std::stringstream idStream;243formatId(id, idStream);244out << std::setw(width) << std::right << idStream.str();245if (id != 0)246out << ":";247else248out << " ";249250if (nestedControl.size() && id == nestedControl.top())251nestedControl.pop();252}253254void SpirvStream::outputTypeId(Id id)255{256const int width = 12;257std::stringstream idStream;258formatId(id, idStream);259out << std::setw(width) << std::right << idStream.str() << " ";260}261262void SpirvStream::outputId(Id id)263{264if (id >= bound)265Kill(out, "Bad <id>");266267out << id;268if (idDescriptor[id].size() > 0)269out << "(" << idDescriptor[id] << ")";270}271272void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)273{274if (mask == 0)275out << "None";276else {277for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {278if (mask & (1 << m))279out << OperandClassParams[operandClass].getName(m) << " ";280}281}282}283284void SpirvStream::disassembleImmediates(int numOperands)285{286for (int i = 0; i < numOperands; ++i) {287out << stream[word++];288if (i < numOperands - 1)289out << " ";290}291}292293void SpirvStream::disassembleIds(int numOperands)294{295for (int i = 0; i < numOperands; ++i) {296outputId(stream[word++]);297if (i < numOperands - 1)298out << " ";299}300}301302// decode string from words at current position (non-consuming)303std::pair<int, std::string> SpirvStream::decodeString()304{305std::string res;306int wordPos = word;307char c;308bool done = false;309310do {311unsigned int content = stream[wordPos];312for (int charCount = 0; charCount < 4; ++charCount) {313c = content & 0xff;314content >>= 8;315if (c == '\0') {316done = true;317break;318}319res += c;320}321++wordPos;322} while(! done);323324return std::make_pair(wordPos - word, res);325}326327// return the number of operands consumed by the string328int SpirvStream::disassembleString()329{330out << " \"";331332std::pair<int, std::string> decoderes = decodeString();333334out << decoderes.second;335out << "\"";336337word += decoderes.first;338339return decoderes.first;340}341342static uint32_t popcount(uint32_t mask)343{344uint32_t count = 0;345while (mask) {346if (mask & 1) {347count++;348}349mask >>= 1;350}351return count;352}353354void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)355{356// Process the opcode357358out << (OpcodeString((int)opCode) + 2); // leave out the "Op"359360if (opCode == Op::OpLoopMerge || opCode == Op::OpSelectionMerge)361nextNestedControl = stream[word];362else if (opCode == Op::OpBranchConditional || opCode == Op::OpSwitch) {363if (nextNestedControl) {364nestedControl.push(nextNestedControl);365nextNestedControl = 0;366}367} else if (opCode == Op::OpExtInstImport) {368idDescriptor[resultId] = decodeString().second;369}370else {371if (resultId != 0 && idDescriptor[resultId].size() == 0) {372switch (opCode) {373case Op::OpTypeInt:374switch (stream[word]) {375case 8: idDescriptor[resultId] = "int8_t"; break;376case 16: idDescriptor[resultId] = "int16_t"; break;377default: assert(0); [[fallthrough]];378case 32: idDescriptor[resultId] = "int"; break;379case 64: idDescriptor[resultId] = "int64_t"; break;380}381break;382case Op::OpTypeFloat:383switch (stream[word]) {384case 8:385case 16:386if (numOperands > 1) {387switch (stream[word+1]) {388default:389assert(0); [[fallthrough]];390case (int)spv::FPEncoding::BFloat16KHR:391idDescriptor[resultId] = "bfloat16_t";392break;393case (int)spv::FPEncoding::Float8E4M3EXT:394idDescriptor[resultId] = "floate4m3_t";395break;396case (int)spv::FPEncoding::Float8E5M2EXT:397idDescriptor[resultId] = "floate5m2_t";398break;399}400} else {401idDescriptor[resultId] = "float16_t";402}403break;404default: assert(0); [[fallthrough]];405case 32: idDescriptor[resultId] = "float"; break;406case 64: idDescriptor[resultId] = "float64_t"; break;407}408break;409case Op::OpTypeBool:410idDescriptor[resultId] = "bool";411break;412case Op::OpTypeStruct:413idDescriptor[resultId] = "struct";414break;415case Op::OpTypePointer:416idDescriptor[resultId] = "ptr";417break;418case Op::OpTypeVector:419if (idDescriptor[stream[word]].size() > 0) {420if (idDescriptor[stream[word]].substr(0,2) == "bf") {421idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 2);422} else {423idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);424}425if (strstr(idDescriptor[stream[word]].c_str(), "8")) {426idDescriptor[resultId].append("8");427}428if (strstr(idDescriptor[stream[word]].c_str(), "16")) {429idDescriptor[resultId].append("16");430}431if (strstr(idDescriptor[stream[word]].c_str(), "64")) {432idDescriptor[resultId].append("64");433}434}435idDescriptor[resultId].append("vec");436switch (stream[word + 1]) {437case 2: idDescriptor[resultId].append("2"); break;438case 3: idDescriptor[resultId].append("3"); break;439case 4: idDescriptor[resultId].append("4"); break;440case 8: idDescriptor[resultId].append("8"); break;441case 16: idDescriptor[resultId].append("16"); break;442case 32: idDescriptor[resultId].append("32"); break;443default: break;444}445break;446default:447break;448}449}450}451452// Process the operands. Note, a new context-dependent set could be453// swapped in mid-traversal.454455// Handle images specially, so can put out helpful strings.456if (opCode == Op::OpTypeImage) {457out << " ";458disassembleIds(1);459out << " " << DimensionString((int)(Dim)stream[word++]);460out << (stream[word++] != 0 ? " depth" : "");461out << (stream[word++] != 0 ? " array" : "");462out << (stream[word++] != 0 ? " multi-sampled" : "");463switch (stream[word++]) {464case 0: out << " runtime"; break;465case 1: out << " sampled"; break;466case 2: out << " nonsampled"; break;467}468out << " format:" << ImageFormatString((int)(ImageFormat)stream[word++]);469470if (numOperands == 8) {471out << " " << AccessQualifierString(stream[word++]);472}473return;474}475476// Handle all the parameterized operands477for (int op = 0; op < InstructionDesc[enumCast(opCode)].operands.getNum() && numOperands > 0; ++op) {478out << " ";479OperandClass operandClass = InstructionDesc[enumCast(opCode)].operands.getClass(op);480switch (operandClass) {481case OperandId:482case OperandScope:483case OperandMemorySemantics:484disassembleIds(1);485--numOperands;486// Get names for printing "(XXX)" for readability, *after* this id487if (opCode == Op::OpName)488idDescriptor[stream[word - 1]] = decodeString().second;489break;490case OperandVariableIds:491disassembleIds(numOperands);492return;493case OperandImageOperands:494outputMask(OperandImageOperands, stream[word++]);495--numOperands;496disassembleIds(numOperands);497return;498case OperandOptionalLiteral:499case OperandVariableLiterals:500if ((opCode == Op::OpDecorate && stream[word - 1] == Decoration::BuiltIn) ||501(opCode == Op::OpMemberDecorate && stream[word - 1] == Decoration::BuiltIn)) {502out << BuiltInString(stream[word++]);503--numOperands;504++op;505}506disassembleImmediates(numOperands);507return;508case OperandVariableIdLiteral:509while (numOperands > 0) {510out << std::endl;511outputResultId(0);512outputTypeId(0);513outputIndent();514out << " Type ";515disassembleIds(1);516out << ", member ";517disassembleImmediates(1);518numOperands -= 2;519}520return;521case OperandVariableLiteralId:522while (numOperands > 0) {523out << std::endl;524outputResultId(0);525outputTypeId(0);526outputIndent();527out << " case ";528disassembleImmediates(1);529out << ": ";530disassembleIds(1);531numOperands -= 2;532}533return;534case OperandLiteralNumber:535disassembleImmediates(1);536--numOperands;537if (opCode == Op::OpExtInst) {538ExtInstSet extInstSet = GLSL450Inst;539const char* name = idDescriptor[stream[word - 2]].c_str();540if (strcmp("OpenCL.std", name) == 0) {541extInstSet = OpenCLExtInst;542} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {543extInstSet = OpenCLExtInst;544} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {545extInstSet = NonSemanticDebugPrintfExtInst;546} else if (strcmp("NonSemantic.DebugBreak", name) == 0) {547extInstSet = NonSemanticDebugBreakExtInst;548} else if (strcmp("NonSemantic.Shader.DebugInfo.100", name) == 0) {549extInstSet = NonSemanticShaderDebugInfo100;550} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||551strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||552strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||553strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {554extInstSet = GLSLextAMDInst;555} else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||556strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||557strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||558strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||559strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||560strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {561extInstSet = GLSLextNVInst;562}563unsigned entrypoint = stream[word - 1];564if (extInstSet == GLSL450Inst) {565if (entrypoint < GLSLstd450Count) {566out << "(" << GlslStd450DebugNames[entrypoint] << ")";567}568} else if (extInstSet == GLSLextAMDInst) {569out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";570}571else if (extInstSet == GLSLextNVInst) {572out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";573} else if (extInstSet == NonSemanticDebugPrintfExtInst) {574out << "(DebugPrintf)";575} else if (extInstSet == NonSemanticDebugBreakExtInst) {576out << "(DebugBreak)";577} else if (extInstSet == NonSemanticShaderDebugInfo100) {578out << "(" << NonSemanticShaderDebugInfo100GetDebugNames(entrypoint) << ")";579}580}581break;582case OperandOptionalLiteralString:583case OperandLiteralString:584numOperands -= disassembleString();585break;586case OperandVariableLiteralStrings:587while (numOperands > 0)588numOperands -= disassembleString();589return;590case OperandMemoryAccess:591{592outputMask(OperandMemoryAccess, stream[word++]);593--numOperands;594// Put a space after "None" if there are any remaining operands595if (numOperands && stream[word-1] == 0) {596out << " ";597}598uint32_t mask = stream[word-1];599// Aligned is the only memory access operand that uses an immediate600// value, and it is also the first operand that uses a value at all.601if (mask & (uint32_t)MemoryAccessMask::Aligned) {602disassembleImmediates(1);603numOperands--;604if (numOperands)605out << " ";606}607608uint32_t bitCount = popcount(mask & (uint32_t)(MemoryAccessMask::MakePointerAvailable | MemoryAccessMask::MakePointerVisible));609disassembleIds(bitCount);610numOperands -= bitCount;611}612break;613case OperandTensorAddressingOperands:614{615outputMask(OperandTensorAddressingOperands, stream[word++]);616--numOperands;617// Put a space after "None" if there are any remaining operands618if (numOperands && stream[word-1] == 0) {619out << " ";620}621uint32_t bitCount = popcount(stream[word-1]);622disassembleIds(bitCount);623numOperands -= bitCount;624}625break;626default:627assert(operandClass >= OperandSource && operandClass < OperandOpcode);628629if (OperandClassParams[operandClass].bitmask)630outputMask(operandClass, stream[word++]);631else632out << OperandClassParams[operandClass].getName(stream[word++]);633--numOperands;634635break;636}637}638639return;640}641642static void GLSLstd450GetDebugNames(const char** names)643{644for (int i = 0; i < GLSLstd450Count; ++i)645names[i] = "Unknown";646647names[GLSLstd450Round] = "Round";648names[GLSLstd450RoundEven] = "RoundEven";649names[GLSLstd450Trunc] = "Trunc";650names[GLSLstd450FAbs] = "FAbs";651names[GLSLstd450SAbs] = "SAbs";652names[GLSLstd450FSign] = "FSign";653names[GLSLstd450SSign] = "SSign";654names[GLSLstd450Floor] = "Floor";655names[GLSLstd450Ceil] = "Ceil";656names[GLSLstd450Fract] = "Fract";657names[GLSLstd450Radians] = "Radians";658names[GLSLstd450Degrees] = "Degrees";659names[GLSLstd450Sin] = "Sin";660names[GLSLstd450Cos] = "Cos";661names[GLSLstd450Tan] = "Tan";662names[GLSLstd450Asin] = "Asin";663names[GLSLstd450Acos] = "Acos";664names[GLSLstd450Atan] = "Atan";665names[GLSLstd450Sinh] = "Sinh";666names[GLSLstd450Cosh] = "Cosh";667names[GLSLstd450Tanh] = "Tanh";668names[GLSLstd450Asinh] = "Asinh";669names[GLSLstd450Acosh] = "Acosh";670names[GLSLstd450Atanh] = "Atanh";671names[GLSLstd450Atan2] = "Atan2";672names[GLSLstd450Pow] = "Pow";673names[GLSLstd450Exp] = "Exp";674names[GLSLstd450Log] = "Log";675names[GLSLstd450Exp2] = "Exp2";676names[GLSLstd450Log2] = "Log2";677names[GLSLstd450Sqrt] = "Sqrt";678names[GLSLstd450InverseSqrt] = "InverseSqrt";679names[GLSLstd450Determinant] = "Determinant";680names[GLSLstd450MatrixInverse] = "MatrixInverse";681names[GLSLstd450Modf] = "Modf";682names[GLSLstd450ModfStruct] = "ModfStruct";683names[GLSLstd450FMin] = "FMin";684names[GLSLstd450SMin] = "SMin";685names[GLSLstd450UMin] = "UMin";686names[GLSLstd450FMax] = "FMax";687names[GLSLstd450SMax] = "SMax";688names[GLSLstd450UMax] = "UMax";689names[GLSLstd450FClamp] = "FClamp";690names[GLSLstd450SClamp] = "SClamp";691names[GLSLstd450UClamp] = "UClamp";692names[GLSLstd450FMix] = "FMix";693names[GLSLstd450Step] = "Step";694names[GLSLstd450SmoothStep] = "SmoothStep";695names[GLSLstd450Fma] = "Fma";696names[GLSLstd450Frexp] = "Frexp";697names[GLSLstd450FrexpStruct] = "FrexpStruct";698names[GLSLstd450Ldexp] = "Ldexp";699names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";700names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";701names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";702names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";703names[GLSLstd450PackHalf2x16] = "PackHalf2x16";704names[GLSLstd450PackDouble2x32] = "PackDouble2x32";705names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";706names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";707names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";708names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";709names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";710names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";711names[GLSLstd450Length] = "Length";712names[GLSLstd450Distance] = "Distance";713names[GLSLstd450Cross] = "Cross";714names[GLSLstd450Normalize] = "Normalize";715names[GLSLstd450FaceForward] = "FaceForward";716names[GLSLstd450Reflect] = "Reflect";717names[GLSLstd450Refract] = "Refract";718names[GLSLstd450FindILsb] = "FindILsb";719names[GLSLstd450FindSMsb] = "FindSMsb";720names[GLSLstd450FindUMsb] = "FindUMsb";721names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";722names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";723names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";724names[GLSLstd450NMin] = "NMin";725names[GLSLstd450NMax] = "NMax";726names[GLSLstd450NClamp] = "NClamp";727}728729static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)730{731if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {732switch (entrypoint) {733case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";734case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";735case WriteInvocationAMD: return "WriteInvocationAMD";736case MbcntAMD: return "MbcntAMD";737default: return "Bad";738}739} else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {740switch (entrypoint) {741case FMin3AMD: return "FMin3AMD";742case UMin3AMD: return "UMin3AMD";743case SMin3AMD: return "SMin3AMD";744case FMax3AMD: return "FMax3AMD";745case UMax3AMD: return "UMax3AMD";746case SMax3AMD: return "SMax3AMD";747case FMid3AMD: return "FMid3AMD";748case UMid3AMD: return "UMid3AMD";749case SMid3AMD: return "SMid3AMD";750default: return "Bad";751}752} else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {753switch (entrypoint) {754case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";755default: return "Bad";756}757}758else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {759switch (entrypoint) {760case CubeFaceIndexAMD: return "CubeFaceIndexAMD";761case CubeFaceCoordAMD: return "CubeFaceCoordAMD";762case TimeAMD: return "TimeAMD";763default:764break;765}766}767768return "Bad";769}770771static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)772{773if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||774strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||775strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||776strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||777strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||778strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||779strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||780strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {781switch (entrypoint) {782// NV builtins783case (unsigned)BuiltIn::ViewportMaskNV: return "ViewportMaskNV";784case (unsigned)BuiltIn::SecondaryPositionNV: return "SecondaryPositionNV";785case (unsigned)BuiltIn::SecondaryViewportMaskNV: return "SecondaryViewportMaskNV";786case (unsigned)BuiltIn::PositionPerViewNV: return "PositionPerViewNV";787case (unsigned)BuiltIn::ViewportMaskPerViewNV: return "ViewportMaskPerViewNV";788case (unsigned)BuiltIn::BaryCoordNV: return "BaryCoordNV";789case (unsigned)BuiltIn::BaryCoordNoPerspNV: return "BaryCoordNoPerspNV";790case (unsigned)BuiltIn::TaskCountNV: return "TaskCountNV";791case (unsigned)BuiltIn::PrimitiveCountNV: return "PrimitiveCountNV";792case (unsigned)BuiltIn::PrimitiveIndicesNV: return "PrimitiveIndicesNV";793case (unsigned)BuiltIn::ClipDistancePerViewNV: return "ClipDistancePerViewNV";794case (unsigned)BuiltIn::CullDistancePerViewNV: return "CullDistancePerViewNV";795case (unsigned)BuiltIn::LayerPerViewNV: return "LayerPerViewNV";796case (unsigned)BuiltIn::MeshViewCountNV: return "MeshViewCountNV";797case (unsigned)BuiltIn::MeshViewIndicesNV: return "MeshViewIndicesNV";798799// NV Capabilities800case (unsigned)Capability::GeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";801case (unsigned)Capability::ShaderViewportMaskNV: return "ShaderViewportMaskNV";802case (unsigned)Capability::ShaderStereoViewNV: return "ShaderStereoViewNV";803case (unsigned)Capability::PerViewAttributesNV: return "PerViewAttributesNV";804case (unsigned)Capability::FragmentBarycentricNV: return "FragmentBarycentricNV";805case (unsigned)Capability::MeshShadingNV: return "MeshShadingNV";806case (unsigned)Capability::ImageFootprintNV: return "ImageFootprintNV";807case (unsigned)Capability::SampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";808809// NV Decorations810case (unsigned)Decoration::OverrideCoverageNV: return "OverrideCoverageNV";811case (unsigned)Decoration::PassthroughNV: return "PassthroughNV";812case (unsigned)Decoration::ViewportRelativeNV: return "ViewportRelativeNV";813case (unsigned)Decoration::SecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";814case (unsigned)Decoration::PerVertexNV: return "PerVertexNV";815case (unsigned)Decoration::PerPrimitiveNV: return "PerPrimitiveNV";816case (unsigned)Decoration::PerViewNV: return "PerViewNV";817case (unsigned)Decoration::PerTaskNV: return "PerTaskNV";818819default: return "Bad";820}821}822return "Bad";823}824825static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned entrypoint)826{827switch (entrypoint) {828case NonSemanticShaderDebugInfo100DebugInfoNone: return "DebugInfoNone";829case NonSemanticShaderDebugInfo100DebugCompilationUnit: return "DebugCompilationUnit";830case NonSemanticShaderDebugInfo100DebugTypeBasic: return "DebugTypeBasic";831case NonSemanticShaderDebugInfo100DebugTypePointer: return "DebugTypePointer";832case NonSemanticShaderDebugInfo100DebugTypeQualifier: return "DebugTypeQualifier";833case NonSemanticShaderDebugInfo100DebugTypeArray: return "DebugTypeArray";834case NonSemanticShaderDebugInfo100DebugTypeVector: return "DebugTypeVector";835case NonSemanticShaderDebugInfo100DebugTypedef: return "DebugTypedef";836case NonSemanticShaderDebugInfo100DebugTypeFunction: return "DebugTypeFunction";837case NonSemanticShaderDebugInfo100DebugTypeEnum: return "DebugTypeEnum";838case NonSemanticShaderDebugInfo100DebugTypeComposite: return "DebugTypeComposite";839case NonSemanticShaderDebugInfo100DebugTypeMember: return "DebugTypeMember";840case NonSemanticShaderDebugInfo100DebugTypeInheritance: return "DebugTypeInheritance";841case NonSemanticShaderDebugInfo100DebugTypePtrToMember: return "DebugTypePtrToMember";842case NonSemanticShaderDebugInfo100DebugTypeTemplate: return "DebugTypeTemplate";843case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter: return "DebugTypeTemplateParameter";844case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter: return "DebugTypeTemplateTemplateParameter";845case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack: return "DebugTypeTemplateParameterPack";846case NonSemanticShaderDebugInfo100DebugGlobalVariable: return "DebugGlobalVariable";847case NonSemanticShaderDebugInfo100DebugFunctionDeclaration: return "DebugFunctionDeclaration";848case NonSemanticShaderDebugInfo100DebugFunction: return "DebugFunction";849case NonSemanticShaderDebugInfo100DebugLexicalBlock: return "DebugLexicalBlock";850case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator: return "DebugLexicalBlockDiscriminator";851case NonSemanticShaderDebugInfo100DebugScope: return "DebugScope";852case NonSemanticShaderDebugInfo100DebugNoScope: return "DebugNoScope";853case NonSemanticShaderDebugInfo100DebugInlinedAt: return "DebugInlinedAt";854case NonSemanticShaderDebugInfo100DebugLocalVariable: return "DebugLocalVariable";855case NonSemanticShaderDebugInfo100DebugInlinedVariable: return "DebugInlinedVariable";856case NonSemanticShaderDebugInfo100DebugDeclare: return "DebugDeclare";857case NonSemanticShaderDebugInfo100DebugValue: return "DebugValue";858case NonSemanticShaderDebugInfo100DebugOperation: return "DebugOperation";859case NonSemanticShaderDebugInfo100DebugExpression: return "DebugExpression";860case NonSemanticShaderDebugInfo100DebugMacroDef: return "DebugMacroDef";861case NonSemanticShaderDebugInfo100DebugMacroUndef: return "DebugMacroUndef";862case NonSemanticShaderDebugInfo100DebugImportedEntity: return "DebugImportedEntity";863case NonSemanticShaderDebugInfo100DebugSource: return "DebugSource";864case NonSemanticShaderDebugInfo100DebugFunctionDefinition: return "DebugFunctionDefinition";865case NonSemanticShaderDebugInfo100DebugSourceContinued: return "DebugSourceContinued";866case NonSemanticShaderDebugInfo100DebugLine: return "DebugLine";867case NonSemanticShaderDebugInfo100DebugNoLine: return "DebugNoLine";868case NonSemanticShaderDebugInfo100DebugBuildIdentifier: return "DebugBuildIdentifier";869case NonSemanticShaderDebugInfo100DebugStoragePath: return "DebugStoragePath";870case NonSemanticShaderDebugInfo100DebugEntryPoint: return "DebugEntryPoint";871case NonSemanticShaderDebugInfo100DebugTypeMatrix: return "DebugTypeMatrix";872default: return "Bad";873}874875return "Bad";876}877878void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)879{880SpirvStream SpirvStream(out, stream);881spv::Parameterize();882GLSLstd450GetDebugNames(GlslStd450DebugNames);883SpirvStream.validate();884SpirvStream.processInstructions();885}886887} // end namespace spv888889890