yum-mirror/glslang
git clone https://git.yummers.dev/yum-mirror/glslang
8d6dd0e4
main
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// 36// Disassembler for SPIR-V. 37// 38 39#include <cstdint> 40#include <cstdlib> 41#include <cstring> 42#include <cassert> 43#include <iomanip> 44#include <stack> 45#include <sstream> 46#include <cstring> 47#include <utility> 48 49#include "disassemble.h" 50#include "doc.h" 51#include "spvUtil.h" 52 53namespace spv { 54extern "C" { 55// Include C-based headers that don't have a namespace 56#include "GLSL.std.450.h" 57#include "GLSL.ext.AMD.h" 58#include "GLSL.ext.NV.h" 59#include "GLSL.ext.ARM.h" 60#include "NonSemanticShaderDebugInfo.h" 61#include "GLSL.ext.QCOM.h" 62 } 63} 64static const char * GlslStd450DebugNames [spv::GLSLstd450Count ]; 65 66namespace spv { 67 68static const char * GLSLextAMDGetDebugNames (const char * ,unsigned ); 69static const char * GLSLextNVGetDebugNames (const char * ,unsigned ); 70static const char * NonSemanticShaderDebugInfoGetDebugNames (unsigned ); 71 72static void Kill (std::ostream & out ,const char * message ) 73{ 74out << std::endl <<"Disassembly failed: " <<message << std::endl ; 75exit (1 ); 76} 77 78// used to identify the extended instruction library imported when printing 79enum ExtInstSet { 80GLSL450Inst , 81GLSLextAMDInst , 82GLSLextNVInst , 83OpenCLExtInst , 84NonSemanticDebugPrintfExtInst , 85NonSemanticDebugBreakExtInst , 86NonSemanticShaderDebugInfo 87}; 88 89// Container class for a single instance of a SPIR-V stream, with methods for disassembly. 90class SpirvStream { 91public : 92SpirvStream (std::ostream & out ,const std::vector < unsigned int >& stream ) :out (out ),stream (stream ),word (0 ),nextNestedControl (0 ) { } 93virtual ~SpirvStream () { } 94 95void validate (); 96void processInstructions (); 97 98protected : 99SpirvStream (const SpirvStream & ); 100SpirvStream & operator= (const SpirvStream & ); 101Op getOpCode (int id )const {return idInstruction [id ] ? (Op )(stream [idInstruction [id ]]& OpCodeMask ) :Op ::OpNop ; } 102 103// Output methods 104void outputIndent (); 105void formatId (Id id , std::stringstream & ); 106void outputResultId (Id id ); 107void outputTypeId (Id id ); 108void outputId (Id id ); 109void outputMask (OperandClass operandClass ,unsigned mask ); 110void disassembleImmediates (int numOperands ); 111void disassembleIds (int numOperands ); 112 std::pair < int , std::string > decodeString (); 113int disassembleString (); 114void disassembleInstruction (Id resultId ,Id typeId ,Op opCode ,int numOperands ); 115 116// Data 117 std::ostream & out ;// where to write the disassembly 118const std::vector < unsigned int >& stream ;// the actual word stream 119int size ;// the size of the word stream 120int word ;// the next word of the stream to read 121 122// map each <id> to the instruction that created it 123Id bound ; 124 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) 125 126 std::vector < std::string > idDescriptor ;// the best text string known for explaining the <id> 127 128// schema 129unsigned int schema ; 130 131// stack of structured-merge points 132 std::stack < Id > nestedControl ; 133Id nextNestedControl ;// need a slight delay for when we are nested 134}; 135 136void SpirvStream ::validate () 137{ 138size = (int )stream .size (); 139if (size < 4 ) 140Kill (out ,"stream is too short" ); 141 142// Magic number 143if (stream [word ++ ]!= MagicNumber ) { 144out <<"Bad magic number" ; 145return ; 146 } 147 148// Version 149out <<"// Module Version " << std::hex <<stream [word ++ ] << std::endl ; 150 151// Generator's magic number 152out <<"// Generated by (magic number): " << std::hex <<stream [word ++ ] << std::dec << std::endl ; 153 154// Result <id> bound 155bound = stream [word ++ ]; 156idInstruction .resize (bound ); 157idDescriptor .resize (bound ); 158out <<"// Id's are bound by " <<bound << std::endl ; 159out << std::endl ; 160 161// Reserved schema, must be 0 for now 162schema = stream [word ++ ]; 163if (schema != 0 ) 164Kill (out ,"bad schema, must be 0" ); 165} 166 167// Loop over all the instructions, in order, processing each. 168// Boiler plate for each is handled here directly, the rest is dispatched. 169void SpirvStream ::processInstructions () 170{ 171// Instructions 172while (word < size ) { 173int instructionStart = word ; 174 175// Instruction wordCount and opcode 176unsigned int firstWord = stream [word ]; 177unsigned wordCount = firstWord >>WordCountShift ; 178Op opCode = (Op )(firstWord & OpCodeMask ); 179int nextInst = word + wordCount ; 180++ word ; 181 182// Presence of full instruction 183if (nextInst > size ) 184Kill (out ,"stream instruction terminated too early" ); 185 186// Base for computing number of operands; will be updated as more is learned 187unsigned numOperands = wordCount - 1 ; 188 189// Type <id> 190Id typeId = 0 ; 191if (InstructionDesc [enumCast (opCode )].hasType ()) { 192typeId = stream [word ++ ]; 193-- numOperands ; 194 } 195 196// Result <id> 197Id resultId = 0 ; 198if (InstructionDesc [enumCast (opCode )].hasResult ()) { 199resultId = stream [word ++ ]; 200-- numOperands ; 201 202if (resultId >=bound ) 203Kill (out ,"Bad <id>" ); 204 205// save instruction for future reference 206idInstruction [resultId ]= instructionStart ; 207 } 208 209outputResultId (resultId ); 210outputTypeId (typeId ); 211outputIndent (); 212 213// Hand off the Op and all its operands 214disassembleInstruction (resultId ,typeId ,opCode ,numOperands ); 215if (word != nextInst ) { 216out <<" ERROR, incorrect number of operands consumed. At " <<word <<" instead of " <<nextInst <<" instruction start was " <<instructionStart ; 217word = nextInst ; 218 } 219out << std::endl ; 220 } 221} 222 223void SpirvStream ::outputIndent () 224{ 225for (int i = 0 ;i < (int )nestedControl .size ();++ i ) 226out <<" " ; 227} 228 229void SpirvStream ::formatId (Id id , std::stringstream & idStream ) 230{ 231if (id != 0 ) { 232// On instructions with no IDs, this is called with "0", which does not 233// have to be within ID bounds on null shaders. 234if (id >=bound ) 235Kill (out ,"Bad <id>" ); 236 237idStream <<id ; 238if (idDescriptor [id ].size ()> 0 ) 239idStream <<"(" <<idDescriptor [id ] <<")" ; 240 } 241} 242 243void SpirvStream ::outputResultId (Id id ) 244{ 245const int width = 16 ; 246 std::stringstream idStream ; 247formatId (id ,idStream ); 248out << std::setw (width ) << std::right <<idStream .str (); 249if (id != 0 ) 250out <<":" ; 251else 252out <<" " ; 253 254if (nestedControl .size ()&& id == nestedControl .top ()) 255nestedControl .pop (); 256} 257 258void SpirvStream ::outputTypeId (Id id ) 259{ 260const int width = 12 ; 261 std::stringstream idStream ; 262formatId (id ,idStream ); 263out << std::setw (width ) << std::right <<idStream .str () <<" " ; 264} 265 266void SpirvStream ::outputId (Id id ) 267{ 268if (id >=bound ) 269Kill (out ,"Bad <id>" ); 270 271out <<id ; 272if (idDescriptor [id ].size ()> 0 ) 273out <<"(" <<idDescriptor [id ] <<")" ; 274} 275 276void SpirvStream ::outputMask (OperandClass operandClass ,unsigned mask ) 277{ 278if (mask == 0 ) 279out <<"None" ; 280else { 281for (int m = 0 ;m < OperandClassParams [operandClass ].ceiling ;++ m ) { 282if (mask & (1 <<m )) 283out <<OperandClassParams [operandClass ].getName (m ) <<" " ; 284 } 285 } 286} 287 288void SpirvStream ::disassembleImmediates (int numOperands ) 289{ 290for (int i = 0 ;i < numOperands ;++ i ) { 291out <<stream [word ++ ]; 292if (i < numOperands - 1 ) 293out <<" " ; 294 } 295} 296 297void SpirvStream ::disassembleIds (int numOperands ) 298{ 299for (int i = 0 ;i < numOperands ;++ i ) { 300outputId (stream [word ++ ]); 301if (i < numOperands - 1 ) 302out <<" " ; 303 } 304} 305 306// decode string from words at current position (non-consuming) 307std::pair < int , std::string > SpirvStream ::decodeString () 308{ 309 std::string res ; 310int wordPos = word ; 311char c ; 312bool done = false; 313 314do { 315unsigned int content = stream [wordPos ]; 316for (int charCount = 0 ;charCount < 4 ;++ charCount ) { 317c = content & 0xff ; 318content >>=8 ; 319if (c == '\0' ) { 320done = true; 321break ; 322 } 323res += c ; 324 } 325++ wordPos ; 326 }while (!done ); 327 328return std::make_pair (wordPos - word ,res ); 329} 330 331// return the number of operands consumed by the string 332int SpirvStream ::disassembleString () 333{ 334out <<" \"" ; 335 336 std::pair < int , std::string > decoderes = decodeString (); 337 338out <<decoderes .second ; 339out <<"\"" ; 340 341word += decoderes .first ; 342 343return decoderes .first ; 344} 345 346static uint32_t popcount (uint32_t mask ) 347{ 348uint32_t count = 0 ; 349while (mask ) { 350if (mask & 1 ) { 351count ++ ; 352 } 353mask >>=1 ; 354 } 355return count ; 356} 357 358void SpirvStream ::disassembleInstruction (Id resultId ,Id /*typeId*/ ,Op opCode ,int numOperands ) 359{ 360// Process the opcode 361 362out << (OpcodeString ((int )opCode )+ 2 );// leave out the "Op" 363 364if (opCode == Op ::OpLoopMerge || opCode == Op ::OpSelectionMerge ) 365nextNestedControl = stream [word ]; 366else if (opCode == Op ::OpBranchConditional || opCode == Op ::OpSwitch ) { 367if (nextNestedControl ) { 368nestedControl .push (nextNestedControl ); 369nextNestedControl = 0 ; 370 } 371 }else if (opCode == Op ::OpExtInstImport ) { 372idDescriptor [resultId ]= decodeString ().second ; 373 } 374else { 375if (resultId != 0 && idDescriptor [resultId ].size ()== 0 ) { 376switch (opCode ) { 377case Op ::OpTypeInt : 378switch (stream [word ]) { 379case 8 :idDescriptor [resultId ]= "int8_t" ;break ; 380case 16 :idDescriptor [resultId ]= "int16_t" ;break ; 381default :assert (0 ); [[fallthrough ]]; 382case 32 :idDescriptor [resultId ]= "int" ;break ; 383case 64 :idDescriptor [resultId ]= "int64_t" ;break ; 384 } 385break ; 386case Op ::OpTypeFloat : 387switch (stream [word ]) { 388case 4 : 389case 6 : 390case 8 : 391case 16 : 392if (numOperands > 1 ) { 393switch (stream [word + 1 ]) { 394default : 395assert (0 ); [[fallthrough ]]; 396case (int )spv::FPEncoding ::BFloat16KHR : 397idDescriptor [resultId ]= "bfloat16_t" ; 398break ; 399case (int )spv::FPEncoding ::Float8E4M3EXT : 400idDescriptor [resultId ]= "floate4m3_t" ; 401break ; 402case (int )spv::FPEncoding ::Float8E5M2EXT : 403idDescriptor [resultId ]= "floate5m2_t" ; 404break ; 405case (int )spv::FPEncoding ::Float4E2M1EXT : 406idDescriptor [resultId ]= "floate2m1_t" ; 407break ; 408case (int )spv::FPEncoding ::Float6E3M2EXT : 409idDescriptor [resultId ]= "floate3m2_t" ; 410break ; 411case (int )spv::FPEncoding ::Float6E2M3EXT : 412idDescriptor [resultId ]= "floate2m3_t" ; 413break ; 414case (int )spv::FPEncoding ::Float8UnsignedE8M0EXT : 415idDescriptor [resultId ]= "floatue8m0_t" ; 416break ; 417case (int )spv::FPEncoding ::MXInt8EXT : 418idDescriptor [resultId ]= "floatmxint8_t" ; 419break ; 420 } 421 }else { 422idDescriptor [resultId ]= "float16_t" ; 423 } 424break ; 425default :assert (0 ); [[fallthrough ]]; 426case 32 :idDescriptor [resultId ]= "float" ;break ; 427case 64 :idDescriptor [resultId ]= "float64_t" ;break ; 428 } 429break ; 430case Op ::OpTypeBool : 431idDescriptor [resultId ]= "bool" ; 432break ; 433case Op ::OpTypeStruct : 434idDescriptor [resultId ]= "struct" ; 435break ; 436case Op ::OpTypePointer : 437case Op ::OpTypeUntypedPointerKHR : 438idDescriptor [resultId ]= "ptr" ; 439break ; 440case Op ::OpTypeVector : 441if (stream [word ] >=bound ) 442Kill (out ,"Bad <id>" ); 443if (idDescriptor [stream [word ]].size ()> 0 ) { 444if (idDescriptor [stream [word ]].substr (0 ,2 )== "bf" ) { 445idDescriptor [resultId ].append (idDescriptor [stream [word ]].begin (),idDescriptor [stream [word ]].begin ()+ 2 ); 446 }else { 447idDescriptor [resultId ].append (idDescriptor [stream [word ]].begin (),idDescriptor [stream [word ]].begin ()+ 1 ); 448 } 449if (strstr (idDescriptor [stream [word ]].c_str (),"8" )) { 450idDescriptor [resultId ].append ("8" ); 451 } 452if (strstr (idDescriptor [stream [word ]].c_str (),"16" )) { 453idDescriptor [resultId ].append ("16" ); 454 } 455if (strstr (idDescriptor [stream [word ]].c_str (),"64" )) { 456idDescriptor [resultId ].append ("64" ); 457 } 458 } 459idDescriptor [resultId ].append ("vec" ); 460switch (stream [word + 1 ]) { 461case 2 :idDescriptor [resultId ].append ("2" );break ; 462case 3 :idDescriptor [resultId ].append ("3" );break ; 463case 4 :idDescriptor [resultId ].append ("4" );break ; 464case 8 :idDescriptor [resultId ].append ("8" );break ; 465case 16 :idDescriptor [resultId ].append ("16" );break ; 466case 32 :idDescriptor [resultId ].append ("32" );break ; 467default :break ; 468 } 469break ; 470default : 471break ; 472 } 473 } 474 } 475 476// Process the operands. Note, a new context-dependent set could be 477// swapped in mid-traversal. 478 479// Handle images specially, so can put out helpful strings. 480if (opCode == Op ::OpTypeImage ) { 481out <<" " ; 482disassembleIds (1 ); 483out <<" " <<DimensionString ((int )(Dim )stream [word ++ ]); 484out << (stream [word ++ ]!= 0 ?" depth" :"" ); 485out << (stream [word ++ ]!= 0 ?" array" :"" ); 486out << (stream [word ++ ]!= 0 ?" multi-sampled" :"" ); 487switch (stream [word ++ ]) { 488case 0 :out <<" runtime" ;break ; 489case 1 :out <<" sampled" ;break ; 490case 2 :out <<" nonsampled" ;break ; 491 } 492out <<" format:" <<ImageFormatString ((int )(ImageFormat )stream [word ++ ]); 493 494if (numOperands == 8 ) { 495out <<" " <<AccessQualifierString (stream [word ++ ]); 496 } 497return ; 498 } 499 500// Handle all the parameterized operands 501for (int op = 0 ;op < InstructionDesc [enumCast (opCode )].operands .getNum ()&& numOperands > 0 ;++ op ) { 502out <<" " ; 503OperandClass operandClass = InstructionDesc [enumCast (opCode )].operands .getClass (op ); 504switch (operandClass ) { 505case OperandId : 506case OperandScope : 507case OperandMemorySemantics : 508disassembleIds (1 ); 509-- numOperands ; 510// Get names for printing "(XXX)" for readability, *after* this id 511if (opCode == Op ::OpName ) 512idDescriptor [stream [word - 1 ]]= decodeString ().second ; 513break ; 514case OperandVariableIds : 515disassembleIds (numOperands ); 516return ; 517case OperandImageOperands : 518outputMask (OperandImageOperands ,stream [word ++ ]); 519-- numOperands ; 520disassembleIds (numOperands ); 521return ; 522case OperandOptionalLiteral : 523case OperandVariableLiterals : 524if ((opCode == Op ::OpDecorate && stream [word - 1 ]== Decoration ::BuiltIn )|| 525 (opCode == Op ::OpMemberDecorate && stream [word - 1 ]== Decoration ::BuiltIn )) { 526out <<BuiltInString (stream [word ++ ]); 527-- numOperands ; 528++ op ; 529 } 530disassembleImmediates (numOperands ); 531return ; 532case OperandVariableIdLiteral : 533while (numOperands > 0 ) { 534out << std::endl ; 535outputResultId (0 ); 536outputTypeId (0 ); 537outputIndent (); 538out <<" Type " ; 539disassembleIds (1 ); 540out <<", member " ; 541disassembleImmediates (1 ); 542numOperands -= 2 ; 543 } 544return ; 545case OperandVariableLiteralId : 546while (numOperands > 0 ) { 547out << std::endl ; 548outputResultId (0 ); 549outputTypeId (0 ); 550outputIndent (); 551out <<" case " ; 552disassembleImmediates (1 ); 553out <<": " ; 554disassembleIds (1 ); 555numOperands -= 2 ; 556 } 557return ; 558case OperandLiteralNumber : 559disassembleImmediates (1 ); 560-- numOperands ; 561if (opCode == Op ::OpExtInst ) { 562ExtInstSet extInstSet = GLSL450Inst ; 563const char * name = idDescriptor [stream [word - 2 ]].c_str (); 564if (strcmp ("OpenCL.std" ,name )== 0 ) { 565extInstSet = OpenCLExtInst ; 566 }else if (strcmp ("OpenCL.DebugInfo.100" ,name )== 0 ) { 567extInstSet = OpenCLExtInst ; 568 }else if (strcmp ("NonSemantic.DebugPrintf" ,name )== 0 ) { 569extInstSet = NonSemanticDebugPrintfExtInst ; 570 }else if (strcmp ("NonSemantic.DebugBreak" ,name )== 0 ) { 571extInstSet = NonSemanticDebugBreakExtInst ; 572 }else if (strncmp ("NonSemantic.Shader.DebugInfo." ,name ,strlen ("NonSemantic.Shader.DebugInfo." ))== 5730 ) { 574extInstSet = NonSemanticShaderDebugInfo ; 575 }else if (strcmp (spv::E_SPV_AMD_shader_ballot ,name )== 0 || 576strcmp (spv::E_SPV_AMD_shader_trinary_minmax ,name )== 0 || 577strcmp (spv::E_SPV_AMD_shader_explicit_vertex_parameter ,name )== 0 || 578strcmp (spv::E_SPV_AMD_gcn_shader ,name )== 0 ) { 579extInstSet = GLSLextAMDInst ; 580 }else if (strcmp (spv::E_SPV_NV_sample_mask_override_coverage ,name )== 0 || 581strcmp (spv::E_SPV_NV_geometry_shader_passthrough ,name )== 0 || 582strcmp (spv::E_SPV_NV_viewport_array2 ,name )== 0 || 583strcmp (spv::E_SPV_NVX_multiview_per_view_attributes ,name )== 0 || 584strcmp (spv::E_SPV_NV_fragment_shader_barycentric ,name )== 0 || 585strcmp (spv::E_SPV_NV_mesh_shader ,name )== 0 ) { 586extInstSet = GLSLextNVInst ; 587 } 588unsigned entrypoint = stream [word - 1 ]; 589if (extInstSet == GLSL450Inst ) { 590if (entrypoint < GLSLstd450Count ) { 591out <<"(" <<GlslStd450DebugNames [entrypoint ] <<")" ; 592 } 593 }else if (extInstSet == GLSLextAMDInst ) { 594out <<"(" <<GLSLextAMDGetDebugNames (name ,entrypoint ) <<")" ; 595 } 596else if (extInstSet == GLSLextNVInst ) { 597out <<"(" <<GLSLextNVGetDebugNames (name ,entrypoint ) <<")" ; 598 }else if (extInstSet == NonSemanticDebugPrintfExtInst ) { 599out <<"(DebugPrintf)" ; 600 }else if (extInstSet == NonSemanticDebugBreakExtInst ) { 601out <<"(DebugBreak)" ; 602 }else if (extInstSet == NonSemanticShaderDebugInfo ) { 603out <<"(" <<NonSemanticShaderDebugInfoGetDebugNames (entrypoint ) <<")" ; 604 } 605 } 606break ; 607case OperandOptionalLiteralString : 608case OperandLiteralString : 609numOperands -= disassembleString (); 610break ; 611case OperandVariableLiteralStrings : 612while (numOperands > 0 ) 613numOperands -= disassembleString (); 614return ; 615case OperandMemoryAccess : 616 { 617outputMask (OperandMemoryAccess ,stream [word ++ ]); 618-- numOperands ; 619// Put a space after "None" if there are any remaining operands 620if (numOperands && stream [word - 1 ]== 0 ) { 621out <<" " ; 622 } 623uint32_t mask = stream [word - 1 ]; 624// Aligned is the only memory access operand that uses an immediate 625// value, and it is also the first operand that uses a value at all. 626if (mask & (uint32_t )MemoryAccessMask ::Aligned ) { 627disassembleImmediates (1 ); 628numOperands -- ; 629if (numOperands ) 630out <<" " ; 631 } 632 633uint32_t bitCount = popcount (mask & (uint32_t )(MemoryAccessMask ::MakePointerAvailable |MemoryAccessMask ::MakePointerVisible )); 634disassembleIds (bitCount ); 635numOperands -= bitCount ; 636 } 637break ; 638case OperandTensorAddressingOperands : 639 { 640outputMask (OperandTensorAddressingOperands ,stream [word ++ ]); 641-- numOperands ; 642// Put a space after "None" if there are any remaining operands 643if (numOperands && stream [word - 1 ]== 0 ) { 644out <<" " ; 645 } 646uint32_t bitCount = popcount (stream [word - 1 ]); 647disassembleIds (bitCount ); 648numOperands -= bitCount ; 649 } 650break ; 651default : 652assert (operandClass >=OperandSource && operandClass < OperandOpcode ); 653 654if (OperandClassParams [operandClass ].bitmask ) 655outputMask (operandClass ,stream [word ++ ]); 656else 657out <<OperandClassParams [operandClass ].getName (stream [word ++ ]); 658-- numOperands ; 659 660break ; 661 } 662 } 663 664return ; 665} 666 667static void GLSLstd450GetDebugNames (const char ** names ) 668{ 669for (int i = 0 ;i < GLSLstd450Count ;++ i ) 670names [i ]= "Unknown" ; 671 672names [GLSLstd450Round ]= "Round" ; 673names [GLSLstd450RoundEven ]= "RoundEven" ; 674names [GLSLstd450Trunc ]= "Trunc" ; 675names [GLSLstd450FAbs ]= "FAbs" ; 676names [GLSLstd450SAbs ]= "SAbs" ; 677names [GLSLstd450FSign ]= "FSign" ; 678names [GLSLstd450SSign ]= "SSign" ; 679names [GLSLstd450Floor ]= "Floor" ; 680names [GLSLstd450Ceil ]= "Ceil" ; 681names [GLSLstd450Fract ]= "Fract" ; 682names [GLSLstd450Radians ]= "Radians" ; 683names [GLSLstd450Degrees ]= "Degrees" ; 684names [GLSLstd450Sin ]= "Sin" ; 685names [GLSLstd450Cos ]= "Cos" ; 686names [GLSLstd450Tan ]= "Tan" ; 687names [GLSLstd450Asin ]= "Asin" ; 688names [GLSLstd450Acos ]= "Acos" ; 689names [GLSLstd450Atan ]= "Atan" ; 690names [GLSLstd450Sinh ]= "Sinh" ; 691names [GLSLstd450Cosh ]= "Cosh" ; 692names [GLSLstd450Tanh ]= "Tanh" ; 693names [GLSLstd450Asinh ]= "Asinh" ; 694names [GLSLstd450Acosh ]= "Acosh" ; 695names [GLSLstd450Atanh ]= "Atanh" ; 696names [GLSLstd450Atan2 ]= "Atan2" ; 697names [GLSLstd450Pow ]= "Pow" ; 698names [GLSLstd450Exp ]= "Exp" ; 699names [GLSLstd450Log ]= "Log" ; 700names [GLSLstd450Exp2 ]= "Exp2" ; 701names [GLSLstd450Log2 ]= "Log2" ; 702names [GLSLstd450Sqrt ]= "Sqrt" ; 703names [GLSLstd450InverseSqrt ]= "InverseSqrt" ; 704names [GLSLstd450Determinant ]= "Determinant" ; 705names [GLSLstd450MatrixInverse ]= "MatrixInverse" ; 706names [GLSLstd450Modf ]= "Modf" ; 707names [GLSLstd450ModfStruct ]= "ModfStruct" ; 708names [GLSLstd450FMin ]= "FMin" ; 709names [GLSLstd450SMin ]= "SMin" ; 710names [GLSLstd450UMin ]= "UMin" ; 711names [GLSLstd450FMax ]= "FMax" ; 712names [GLSLstd450SMax ]= "SMax" ; 713names [GLSLstd450UMax ]= "UMax" ; 714names [GLSLstd450FClamp ]= "FClamp" ; 715names [GLSLstd450SClamp ]= "SClamp" ; 716names [GLSLstd450UClamp ]= "UClamp" ; 717names [GLSLstd450FMix ]= "FMix" ; 718names [GLSLstd450Step ]= "Step" ; 719names [GLSLstd450SmoothStep ]= "SmoothStep" ; 720names [GLSLstd450Fma ]= "Fma" ; 721names [GLSLstd450Frexp ]= "Frexp" ; 722names [GLSLstd450FrexpStruct ]= "FrexpStruct" ; 723names [GLSLstd450Ldexp ]= "Ldexp" ; 724names [GLSLstd450PackSnorm4x8 ]= "PackSnorm4x8" ; 725names [GLSLstd450PackUnorm4x8 ]= "PackUnorm4x8" ; 726names [GLSLstd450PackSnorm2x16 ]= "PackSnorm2x16" ; 727names [GLSLstd450PackUnorm2x16 ]= "PackUnorm2x16" ; 728names [GLSLstd450PackHalf2x16 ]= "PackHalf2x16" ; 729names [GLSLstd450PackDouble2x32 ]= "PackDouble2x32" ; 730names [GLSLstd450UnpackSnorm2x16 ]= "UnpackSnorm2x16" ; 731names [GLSLstd450UnpackUnorm2x16 ]= "UnpackUnorm2x16" ; 732names [GLSLstd450UnpackHalf2x16 ]= "UnpackHalf2x16" ; 733names [GLSLstd450UnpackSnorm4x8 ]= "UnpackSnorm4x8" ; 734names [GLSLstd450UnpackUnorm4x8 ]= "UnpackUnorm4x8" ; 735names [GLSLstd450UnpackDouble2x32 ]= "UnpackDouble2x32" ; 736names [GLSLstd450Length ]= "Length" ; 737names [GLSLstd450Distance ]= "Distance" ; 738names [GLSLstd450Cross ]= "Cross" ; 739names [GLSLstd450Normalize ]= "Normalize" ; 740names [GLSLstd450FaceForward ]= "FaceForward" ; 741names [GLSLstd450Reflect ]= "Reflect" ; 742names [GLSLstd450Refract ]= "Refract" ; 743names [GLSLstd450FindILsb ]= "FindILsb" ; 744names [GLSLstd450FindSMsb ]= "FindSMsb" ; 745names [GLSLstd450FindUMsb ]= "FindUMsb" ; 746names [GLSLstd450InterpolateAtCentroid ]= "InterpolateAtCentroid" ; 747names [GLSLstd450InterpolateAtSample ]= "InterpolateAtSample" ; 748names [GLSLstd450InterpolateAtOffset ]= "InterpolateAtOffset" ; 749names [GLSLstd450NMin ]= "NMin" ; 750names [GLSLstd450NMax ]= "NMax" ; 751names [GLSLstd450NClamp ]= "NClamp" ; 752} 753 754static const char * GLSLextAMDGetDebugNames (const char * name ,unsigned entrypoint ) 755{ 756if (strcmp (name , spv::E_SPV_AMD_shader_ballot )== 0 ) { 757switch (entrypoint ) { 758case SwizzleInvocationsAMD :return "SwizzleInvocationsAMD" ; 759case SwizzleInvocationsMaskedAMD :return "SwizzleInvocationsMaskedAMD" ; 760case WriteInvocationAMD :return "WriteInvocationAMD" ; 761case MbcntAMD :return "MbcntAMD" ; 762default :return "Bad" ; 763 } 764 }else if (strcmp (name , spv::E_SPV_AMD_shader_trinary_minmax )== 0 ) { 765switch (entrypoint ) { 766case FMin3AMD :return "FMin3AMD" ; 767case UMin3AMD :return "UMin3AMD" ; 768case SMin3AMD :return "SMin3AMD" ; 769case FMax3AMD :return "FMax3AMD" ; 770case UMax3AMD :return "UMax3AMD" ; 771case SMax3AMD :return "SMax3AMD" ; 772case FMid3AMD :return "FMid3AMD" ; 773case UMid3AMD :return "UMid3AMD" ; 774case SMid3AMD :return "SMid3AMD" ; 775default :return "Bad" ; 776 } 777 }else if (strcmp (name , spv::E_SPV_AMD_shader_explicit_vertex_parameter )== 0 ) { 778switch (entrypoint ) { 779case InterpolateAtVertexAMD :return "InterpolateAtVertexAMD" ; 780default :return "Bad" ; 781 } 782 } 783else if (strcmp (name , spv::E_SPV_AMD_gcn_shader )== 0 ) { 784switch (entrypoint ) { 785case CubeFaceIndexAMD :return "CubeFaceIndexAMD" ; 786case CubeFaceCoordAMD :return "CubeFaceCoordAMD" ; 787case TimeAMD :return "TimeAMD" ; 788default : 789break ; 790 } 791 } 792 793return "Bad" ; 794} 795 796static const char * GLSLextNVGetDebugNames (const char * name ,unsigned entrypoint ) 797{ 798if (strcmp (name , spv::E_SPV_NV_sample_mask_override_coverage )== 0 || 799strcmp (name , spv::E_SPV_NV_geometry_shader_passthrough )== 0 || 800strcmp (name , spv::E_ARB_shader_viewport_layer_array )== 0 || 801strcmp (name , spv::E_SPV_NV_viewport_array2 )== 0 || 802strcmp (name , spv::E_SPV_NVX_multiview_per_view_attributes )== 0 || 803strcmp (name , spv::E_SPV_NV_fragment_shader_barycentric )== 0 || 804strcmp (name , spv::E_SPV_NV_mesh_shader )== 0 || 805strcmp (name , spv::E_SPV_NV_shader_image_footprint )== 0 ) { 806switch (entrypoint ) { 807// NV builtins 808case (unsigned )BuiltIn ::ViewportMaskNV :return "ViewportMaskNV" ; 809case (unsigned )BuiltIn ::SecondaryPositionNV :return "SecondaryPositionNV" ; 810case (unsigned )BuiltIn ::SecondaryViewportMaskNV :return "SecondaryViewportMaskNV" ; 811case (unsigned )BuiltIn ::PositionPerViewNV :return "PositionPerViewNV" ; 812case (unsigned )BuiltIn ::ViewportMaskPerViewNV :return "ViewportMaskPerViewNV" ; 813case (unsigned )BuiltIn ::BaryCoordNV :return "BaryCoordNV" ; 814case (unsigned )BuiltIn ::BaryCoordNoPerspNV :return "BaryCoordNoPerspNV" ; 815case (unsigned )BuiltIn ::TaskCountNV :return "TaskCountNV" ; 816case (unsigned )BuiltIn ::PrimitiveCountNV :return "PrimitiveCountNV" ; 817case (unsigned )BuiltIn ::PrimitiveIndicesNV :return "PrimitiveIndicesNV" ; 818case (unsigned )BuiltIn ::ClipDistancePerViewNV :return "ClipDistancePerViewNV" ; 819case (unsigned )BuiltIn ::CullDistancePerViewNV :return "CullDistancePerViewNV" ; 820case (unsigned )BuiltIn ::LayerPerViewNV :return "LayerPerViewNV" ; 821case (unsigned )BuiltIn ::MeshViewCountNV :return "MeshViewCountNV" ; 822case (unsigned )BuiltIn ::MeshViewIndicesNV :return "MeshViewIndicesNV" ; 823 824// NV Capabilities 825case (unsigned )Capability ::GeometryShaderPassthroughNV :return "GeometryShaderPassthroughNV" ; 826case (unsigned )Capability ::ShaderViewportMaskNV :return "ShaderViewportMaskNV" ; 827case (unsigned )Capability ::ShaderStereoViewNV :return "ShaderStereoViewNV" ; 828case (unsigned )Capability ::PerViewAttributesNV :return "PerViewAttributesNV" ; 829case (unsigned )Capability ::FragmentBarycentricNV :return "FragmentBarycentricNV" ; 830case (unsigned )Capability ::MeshShadingNV :return "MeshShadingNV" ; 831case (unsigned )Capability ::ImageFootprintNV :return "ImageFootprintNV" ; 832case (unsigned )Capability ::SampleMaskOverrideCoverageNV :return "SampleMaskOverrideCoverageNV" ; 833 834// NV Decorations 835case (unsigned )Decoration ::OverrideCoverageNV :return "OverrideCoverageNV" ; 836case (unsigned )Decoration ::PassthroughNV :return "PassthroughNV" ; 837case (unsigned )Decoration ::ViewportRelativeNV :return "ViewportRelativeNV" ; 838case (unsigned )Decoration ::SecondaryViewportRelativeNV :return "SecondaryViewportRelativeNV" ; 839case (unsigned )Decoration ::PerVertexNV :return "PerVertexNV" ; 840case (unsigned )Decoration ::PerPrimitiveNV :return "PerPrimitiveNV" ; 841case (unsigned )Decoration ::PerViewNV :return "PerViewNV" ; 842case (unsigned )Decoration ::PerTaskNV :return "PerTaskNV" ; 843 844default :return "Bad" ; 845 } 846 } 847return "Bad" ; 848} 849 850static const char * NonSemanticShaderDebugInfoGetDebugNames (unsigned entrypoint ) 851{ 852switch (entrypoint ) { 853case NonSemanticShaderDebugInfoDebugInfoNone :return "DebugInfoNone" ; 854case NonSemanticShaderDebugInfoDebugCompilationUnit :return "DebugCompilationUnit" ; 855case NonSemanticShaderDebugInfoDebugTypeBasic :return "DebugTypeBasic" ; 856case NonSemanticShaderDebugInfoDebugTypePointer :return "DebugTypePointer" ; 857case NonSemanticShaderDebugInfoDebugTypeQualifier :return "DebugTypeQualifier" ; 858case NonSemanticShaderDebugInfoDebugTypeArray :return "DebugTypeArray" ; 859case NonSemanticShaderDebugInfoDebugTypeVector :return "DebugTypeVector" ; 860case NonSemanticShaderDebugInfoDebugTypedef :return "DebugTypedef" ; 861case NonSemanticShaderDebugInfoDebugTypeFunction :return "DebugTypeFunction" ; 862case NonSemanticShaderDebugInfoDebugTypeEnum :return "DebugTypeEnum" ; 863case NonSemanticShaderDebugInfoDebugTypeComposite :return "DebugTypeComposite" ; 864case NonSemanticShaderDebugInfoDebugTypeMember :return "DebugTypeMember" ; 865case NonSemanticShaderDebugInfoDebugTypeInheritance :return "DebugTypeInheritance" ; 866case NonSemanticShaderDebugInfoDebugTypePtrToMember :return "DebugTypePtrToMember" ; 867case NonSemanticShaderDebugInfoDebugTypeTemplate :return "DebugTypeTemplate" ; 868case NonSemanticShaderDebugInfoDebugTypeTemplateParameter :return "DebugTypeTemplateParameter" ; 869case NonSemanticShaderDebugInfoDebugTypeTemplateTemplateParameter :return "DebugTypeTemplateTemplateParameter" ; 870case NonSemanticShaderDebugInfoDebugTypeTemplateParameterPack :return "DebugTypeTemplateParameterPack" ; 871case NonSemanticShaderDebugInfoDebugGlobalVariable :return "DebugGlobalVariable" ; 872case NonSemanticShaderDebugInfoDebugFunctionDeclaration :return "DebugFunctionDeclaration" ; 873case NonSemanticShaderDebugInfoDebugFunction :return "DebugFunction" ; 874case NonSemanticShaderDebugInfoDebugLexicalBlock :return "DebugLexicalBlock" ; 875case NonSemanticShaderDebugInfoDebugLexicalBlockDiscriminator :return "DebugLexicalBlockDiscriminator" ; 876case NonSemanticShaderDebugInfoDebugScope :return "DebugScope" ; 877case NonSemanticShaderDebugInfoDebugNoScope :return "DebugNoScope" ; 878case NonSemanticShaderDebugInfoDebugInlinedAt :return "DebugInlinedAt" ; 879case NonSemanticShaderDebugInfoDebugLocalVariable :return "DebugLocalVariable" ; 880case NonSemanticShaderDebugInfoDebugInlinedVariable :return "DebugInlinedVariable" ; 881case NonSemanticShaderDebugInfoDebugDeclare :return "DebugDeclare" ; 882case NonSemanticShaderDebugInfoDebugValue :return "DebugValue" ; 883case NonSemanticShaderDebugInfoDebugOperation :return "DebugOperation" ; 884case NonSemanticShaderDebugInfoDebugExpression :return "DebugExpression" ; 885case NonSemanticShaderDebugInfoDebugMacroDef :return "DebugMacroDef" ; 886case NonSemanticShaderDebugInfoDebugMacroUndef :return "DebugMacroUndef" ; 887case NonSemanticShaderDebugInfoDebugImportedEntity :return "DebugImportedEntity" ; 888case NonSemanticShaderDebugInfoDebugSource :return "DebugSource" ; 889case NonSemanticShaderDebugInfoDebugFunctionDefinition :return "DebugFunctionDefinition" ; 890case NonSemanticShaderDebugInfoDebugSourceContinued :return "DebugSourceContinued" ; 891case NonSemanticShaderDebugInfoDebugLine :return "DebugLine" ; 892case NonSemanticShaderDebugInfoDebugNoLine :return "DebugNoLine" ; 893case NonSemanticShaderDebugInfoDebugBuildIdentifier :return "DebugBuildIdentifier" ; 894case NonSemanticShaderDebugInfoDebugStoragePath :return "DebugStoragePath" ; 895case NonSemanticShaderDebugInfoDebugEntryPoint :return "DebugEntryPoint" ; 896case NonSemanticShaderDebugInfoDebugTypeMatrix :return "DebugTypeMatrix" ; 897case NonSemanticShaderDebugInfoDebugTypeVectorIdEXT :return "DebugTypeVectorIdEXT" ; 898case NonSemanticShaderDebugInfoDebugTypeCooperativeMatrixKHR :return "DebugTypeCooperativeMatrixKHR" ; 899default :return "Bad" ; 900 } 901 902return "Bad" ; 903} 904 905void Disassemble (std::ostream & out ,const std::vector < unsigned int >& stream ) 906{ 907SpirvStream SpirvStream (out ,stream ); 908 spv::Parameterize (); 909GLSLstd450GetDebugNames (GlslStd450DebugNames ); 910SpirvStream .validate (); 911SpirvStream .processInstructions (); 912} 913 914}// end namespace spv