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