Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/tgsi/tgsi_dump.c
4565 views
1
/**************************************************************************
2
*
3
* Copyright 2007-2008 VMware, Inc.
4
* All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
13
*
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial portions
16
* of the Software.
17
*
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
*
26
**************************************************************************/
27
28
#include <inttypes.h>
29
30
#include "util/u_debug.h"
31
#include "util/u_string.h"
32
#include "util/u_math.h"
33
#include "util/u_memory.h"
34
#include "util/u_math.h"
35
#include "tgsi_dump.h"
36
#include "tgsi_info.h"
37
#include "tgsi_iterate.h"
38
#include "tgsi_strings.h"
39
40
41
/** Number of spaces to indent for IF/LOOP/etc */
42
static const int indent_spaces = 3;
43
44
45
struct dump_ctx
46
{
47
struct tgsi_iterate_context iter;
48
49
boolean dump_float_as_hex;
50
51
uint instno;
52
uint immno;
53
int indent;
54
55
uint indentation;
56
FILE *file;
57
58
void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
59
};
60
61
static void
62
dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
63
{
64
va_list ap;
65
(void)ctx;
66
va_start(ap, format);
67
if (ctx->file)
68
vfprintf(ctx->file, format, ap);
69
else
70
_debug_vprintf(format, ap);
71
va_end(ap);
72
}
73
74
static void
75
dump_enum(
76
struct dump_ctx *ctx,
77
uint e,
78
const char **enums,
79
uint enum_count )
80
{
81
if (e >= enum_count)
82
ctx->dump_printf( ctx, "%u", e );
83
else
84
ctx->dump_printf( ctx, "%s", enums[e] );
85
}
86
87
#define EOL() ctx->dump_printf( ctx, "\n" )
88
#define TXT(S) ctx->dump_printf( ctx, "%s", S )
89
#define CHR(C) ctx->dump_printf( ctx, "%c", C )
90
#define UIX(I) ctx->dump_printf( ctx, "0x%x", I )
91
#define UID(I) ctx->dump_printf( ctx, "%u", I )
92
#define SI64D(I) ctx->dump_printf( ctx, "%"PRId64, I )
93
#define UI64D(I) ctx->dump_printf( ctx, "%"PRIu64, I )
94
#define INSTID(I) ctx->dump_printf( ctx, "% 3u", I )
95
#define SID(I) ctx->dump_printf( ctx, "%d", I )
96
#define FLT(F) ctx->dump_printf( ctx, "%10.4f", F )
97
#define DBL(D) ctx->dump_printf( ctx, "%10.8f", D )
98
#define HFLT(F) ctx->dump_printf( ctx, "0x%08x", fui((F)) )
99
#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
100
101
const char *
102
tgsi_swizzle_names[4] =
103
{
104
"x",
105
"y",
106
"z",
107
"w"
108
};
109
110
static void
111
_dump_register_src(
112
struct dump_ctx *ctx,
113
const struct tgsi_full_src_register *src )
114
{
115
TXT(tgsi_file_name(src->Register.File));
116
if (src->Register.Dimension) {
117
if (src->Dimension.Indirect) {
118
CHR( '[' );
119
TXT(tgsi_file_name(src->DimIndirect.File));
120
CHR( '[' );
121
SID( src->DimIndirect.Index );
122
TXT( "]." );
123
ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
124
if (src->Dimension.Index != 0) {
125
if (src->Dimension.Index > 0)
126
CHR( '+' );
127
SID( src->Dimension.Index );
128
}
129
CHR( ']' );
130
if (src->DimIndirect.ArrayID) {
131
CHR( '(' );
132
SID( src->DimIndirect.ArrayID );
133
CHR( ')' );
134
}
135
} else {
136
CHR('[');
137
SID(src->Dimension.Index);
138
CHR(']');
139
}
140
}
141
if (src->Register.Indirect) {
142
CHR( '[' );
143
TXT(tgsi_file_name(src->Indirect.File));
144
CHR( '[' );
145
SID( src->Indirect.Index );
146
TXT( "]." );
147
ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
148
if (src->Register.Index != 0) {
149
if (src->Register.Index > 0)
150
CHR( '+' );
151
SID( src->Register.Index );
152
}
153
CHR( ']' );
154
if (src->Indirect.ArrayID) {
155
CHR( '(' );
156
SID( src->Indirect.ArrayID );
157
CHR( ')' );
158
}
159
} else {
160
CHR( '[' );
161
SID( src->Register.Index );
162
CHR( ']' );
163
}
164
}
165
166
167
static void
168
_dump_register_dst(
169
struct dump_ctx *ctx,
170
const struct tgsi_full_dst_register *dst )
171
{
172
TXT(tgsi_file_name(dst->Register.File));
173
if (dst->Register.Dimension) {
174
if (dst->Dimension.Indirect) {
175
CHR( '[' );
176
TXT(tgsi_file_name(dst->DimIndirect.File));
177
CHR( '[' );
178
SID( dst->DimIndirect.Index );
179
TXT( "]." );
180
ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
181
if (dst->Dimension.Index != 0) {
182
if (dst->Dimension.Index > 0)
183
CHR( '+' );
184
SID( dst->Dimension.Index );
185
}
186
CHR( ']' );
187
if (dst->DimIndirect.ArrayID) {
188
CHR( '(' );
189
SID( dst->DimIndirect.ArrayID );
190
CHR( ')' );
191
}
192
} else {
193
CHR('[');
194
SID(dst->Dimension.Index);
195
CHR(']');
196
}
197
}
198
if (dst->Register.Indirect) {
199
CHR( '[' );
200
TXT(tgsi_file_name(dst->Indirect.File));
201
CHR( '[' );
202
SID( dst->Indirect.Index );
203
TXT( "]." );
204
ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
205
if (dst->Register.Index != 0) {
206
if (dst->Register.Index > 0)
207
CHR( '+' );
208
SID( dst->Register.Index );
209
}
210
CHR( ']' );
211
if (dst->Indirect.ArrayID) {
212
CHR( '(' );
213
SID( dst->Indirect.ArrayID );
214
CHR( ')' );
215
}
216
} else {
217
CHR( '[' );
218
SID( dst->Register.Index );
219
CHR( ']' );
220
}
221
}
222
static void
223
_dump_writemask(
224
struct dump_ctx *ctx,
225
uint writemask )
226
{
227
if (writemask != TGSI_WRITEMASK_XYZW) {
228
CHR( '.' );
229
if (writemask & TGSI_WRITEMASK_X)
230
CHR( 'x' );
231
if (writemask & TGSI_WRITEMASK_Y)
232
CHR( 'y' );
233
if (writemask & TGSI_WRITEMASK_Z)
234
CHR( 'z' );
235
if (writemask & TGSI_WRITEMASK_W)
236
CHR( 'w' );
237
}
238
}
239
240
static void
241
dump_imm_data(struct tgsi_iterate_context *iter,
242
union tgsi_immediate_data *data,
243
unsigned num_tokens,
244
unsigned data_type)
245
{
246
struct dump_ctx *ctx = (struct dump_ctx *)iter;
247
unsigned i ;
248
249
TXT( " {" );
250
251
assert( num_tokens <= 4 );
252
for (i = 0; i < num_tokens; i++) {
253
switch (data_type) {
254
case TGSI_IMM_FLOAT64: {
255
union di d;
256
d.ui = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
257
DBL( d.d );
258
i++;
259
break;
260
}
261
case TGSI_IMM_INT64: {
262
union di d;
263
d.i = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
264
SI64D( d.i );
265
i++;
266
break;
267
}
268
case TGSI_IMM_UINT64: {
269
union di d;
270
d.ui = data[i].Uint | (uint64_t)data[i+1].Uint << 32;
271
UI64D( d.ui );
272
i++;
273
break;
274
}
275
case TGSI_IMM_FLOAT32:
276
if (ctx->dump_float_as_hex)
277
HFLT( data[i].Float );
278
else
279
FLT( data[i].Float );
280
break;
281
case TGSI_IMM_UINT32:
282
UID(data[i].Uint);
283
break;
284
case TGSI_IMM_INT32:
285
SID(data[i].Int);
286
break;
287
default:
288
assert( 0 );
289
}
290
291
if (i < num_tokens - 1)
292
TXT( ", " );
293
}
294
TXT( "}" );
295
}
296
297
static boolean
298
iter_declaration(
299
struct tgsi_iterate_context *iter,
300
struct tgsi_full_declaration *decl )
301
{
302
struct dump_ctx *ctx = (struct dump_ctx *)iter;
303
boolean patch = decl->Semantic.Name == TGSI_SEMANTIC_PATCH ||
304
decl->Semantic.Name == TGSI_SEMANTIC_TESSINNER ||
305
decl->Semantic.Name == TGSI_SEMANTIC_TESSOUTER ||
306
decl->Semantic.Name == TGSI_SEMANTIC_PRIMID;
307
308
TXT( "DCL " );
309
310
TXT(tgsi_file_name(decl->Declaration.File));
311
312
/* all geometry shader inputs and non-patch tessellation shader inputs are
313
* two dimensional
314
*/
315
if (decl->Declaration.File == TGSI_FILE_INPUT &&
316
(iter->processor.Processor == PIPE_SHADER_GEOMETRY ||
317
(!patch &&
318
(iter->processor.Processor == PIPE_SHADER_TESS_CTRL ||
319
iter->processor.Processor == PIPE_SHADER_TESS_EVAL)))) {
320
TXT("[]");
321
}
322
323
/* all non-patch tess ctrl shader outputs are two dimensional */
324
if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
325
!patch &&
326
iter->processor.Processor == PIPE_SHADER_TESS_CTRL) {
327
TXT("[]");
328
}
329
330
if (decl->Declaration.Dimension) {
331
CHR('[');
332
SID(decl->Dim.Index2D);
333
CHR(']');
334
}
335
336
CHR('[');
337
SID(decl->Range.First);
338
if (decl->Range.First != decl->Range.Last) {
339
TXT("..");
340
SID(decl->Range.Last);
341
}
342
CHR(']');
343
344
_dump_writemask(
345
ctx,
346
decl->Declaration.UsageMask );
347
348
if (decl->Declaration.Array) {
349
TXT( ", ARRAY(" );
350
SID(decl->Array.ArrayID);
351
CHR(')');
352
}
353
354
if (decl->Declaration.Local)
355
TXT( ", LOCAL" );
356
357
if (decl->Declaration.Semantic) {
358
TXT( ", " );
359
ENM( decl->Semantic.Name, tgsi_semantic_names );
360
if (decl->Semantic.Index != 0 ||
361
decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
362
decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
363
CHR( '[' );
364
UID( decl->Semantic.Index );
365
CHR( ']' );
366
}
367
368
if (decl->Semantic.StreamX != 0 || decl->Semantic.StreamY != 0 ||
369
decl->Semantic.StreamZ != 0 || decl->Semantic.StreamW != 0) {
370
TXT(", STREAM(");
371
UID(decl->Semantic.StreamX);
372
TXT(", ");
373
UID(decl->Semantic.StreamY);
374
TXT(", ");
375
UID(decl->Semantic.StreamZ);
376
TXT(", ");
377
UID(decl->Semantic.StreamW);
378
CHR(')');
379
}
380
}
381
382
if (decl->Declaration.File == TGSI_FILE_IMAGE) {
383
TXT(", ");
384
ENM(decl->Image.Resource, tgsi_texture_names);
385
TXT(", ");
386
TXT(util_format_name(decl->Image.Format));
387
if (decl->Image.Writable)
388
TXT(", WR");
389
if (decl->Image.Raw)
390
TXT(", RAW");
391
}
392
393
if (decl->Declaration.File == TGSI_FILE_BUFFER) {
394
if (decl->Declaration.Atomic)
395
TXT(", ATOMIC");
396
}
397
398
if (decl->Declaration.File == TGSI_FILE_MEMORY) {
399
switch (decl->Declaration.MemType) {
400
/* Note: ,GLOBAL is optional / the default */
401
case TGSI_MEMORY_TYPE_GLOBAL: TXT(", GLOBAL"); break;
402
case TGSI_MEMORY_TYPE_SHARED: TXT(", SHARED"); break;
403
case TGSI_MEMORY_TYPE_PRIVATE: TXT(", PRIVATE"); break;
404
case TGSI_MEMORY_TYPE_INPUT: TXT(", INPUT"); break;
405
}
406
}
407
408
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
409
TXT(", ");
410
ENM(decl->SamplerView.Resource, tgsi_texture_names);
411
TXT(", ");
412
if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
413
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
414
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
415
ENM(decl->SamplerView.ReturnTypeX, tgsi_return_type_names);
416
} else {
417
ENM(decl->SamplerView.ReturnTypeX, tgsi_return_type_names);
418
TXT(", ");
419
ENM(decl->SamplerView.ReturnTypeY, tgsi_return_type_names);
420
TXT(", ");
421
ENM(decl->SamplerView.ReturnTypeZ, tgsi_return_type_names);
422
TXT(", ");
423
ENM(decl->SamplerView.ReturnTypeW, tgsi_return_type_names);
424
}
425
}
426
427
if (decl->Declaration.Interpolate) {
428
if (iter->processor.Processor == PIPE_SHADER_FRAGMENT &&
429
decl->Declaration.File == TGSI_FILE_INPUT)
430
{
431
TXT( ", " );
432
ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
433
}
434
435
if (decl->Interp.Location != TGSI_INTERPOLATE_LOC_CENTER) {
436
TXT( ", " );
437
ENM( decl->Interp.Location, tgsi_interpolate_locations );
438
}
439
440
if (decl->Interp.CylindricalWrap) {
441
TXT(", CYLWRAP_");
442
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
443
CHR('X');
444
}
445
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
446
CHR('Y');
447
}
448
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
449
CHR('Z');
450
}
451
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
452
CHR('W');
453
}
454
}
455
}
456
457
if (decl->Declaration.Invariant) {
458
TXT( ", INVARIANT" );
459
}
460
461
EOL();
462
463
return TRUE;
464
}
465
466
void
467
tgsi_dump_declaration(
468
const struct tgsi_full_declaration *decl )
469
{
470
struct dump_ctx ctx;
471
memset(&ctx, 0, sizeof(ctx));
472
473
ctx.dump_printf = dump_ctx_printf;
474
475
iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
476
}
477
478
static boolean
479
iter_property(
480
struct tgsi_iterate_context *iter,
481
struct tgsi_full_property *prop )
482
{
483
int i;
484
struct dump_ctx *ctx = (struct dump_ctx *)iter;
485
486
TXT( "PROPERTY " );
487
ENM(prop->Property.PropertyName, tgsi_property_names);
488
489
if (prop->Property.NrTokens > 1)
490
TXT(" ");
491
492
for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
493
switch (prop->Property.PropertyName) {
494
case TGSI_PROPERTY_GS_INPUT_PRIM:
495
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
496
ENM(prop->u[i].Data, tgsi_primitive_names);
497
break;
498
case TGSI_PROPERTY_FS_COORD_ORIGIN:
499
ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
500
break;
501
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
502
ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
503
break;
504
case TGSI_PROPERTY_NEXT_SHADER:
505
ENM(prop->u[i].Data, tgsi_processor_type_names);
506
break;
507
default:
508
SID( prop->u[i].Data );
509
break;
510
}
511
if (i < prop->Property.NrTokens - 2)
512
TXT( ", " );
513
}
514
EOL();
515
516
return TRUE;
517
}
518
519
void tgsi_dump_property(
520
const struct tgsi_full_property *prop )
521
{
522
struct dump_ctx ctx;
523
memset(&ctx, 0, sizeof(ctx));
524
525
ctx.dump_printf = dump_ctx_printf;
526
527
iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
528
}
529
530
static boolean
531
iter_immediate(
532
struct tgsi_iterate_context *iter,
533
struct tgsi_full_immediate *imm )
534
{
535
struct dump_ctx *ctx = (struct dump_ctx *) iter;
536
537
TXT( "IMM[" );
538
SID( ctx->immno++ );
539
TXT( "] " );
540
ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
541
542
dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
543
imm->Immediate.DataType);
544
545
EOL();
546
547
return TRUE;
548
}
549
550
void
551
tgsi_dump_immediate(
552
const struct tgsi_full_immediate *imm )
553
{
554
struct dump_ctx ctx;
555
memset(&ctx, 0, sizeof(ctx));
556
557
ctx.dump_printf = dump_ctx_printf;
558
559
iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
560
}
561
562
static boolean
563
iter_instruction(
564
struct tgsi_iterate_context *iter,
565
struct tgsi_full_instruction *inst )
566
{
567
struct dump_ctx *ctx = (struct dump_ctx *) iter;
568
uint instno = ctx->instno++;
569
const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
570
uint i;
571
boolean first_reg = TRUE;
572
573
INSTID( instno );
574
TXT( ": " );
575
576
ctx->indent -= info->pre_dedent;
577
for(i = 0; (int)i < ctx->indent; ++i)
578
TXT( " " );
579
ctx->indent += info->post_indent;
580
581
TXT( tgsi_get_opcode_name(inst->Instruction.Opcode) );
582
583
if (inst->Instruction.Saturate) {
584
TXT( "_SAT" );
585
}
586
587
if (inst->Instruction.Precise) {
588
TXT( "_PRECISE" );
589
}
590
591
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
592
const struct tgsi_full_dst_register *dst = &inst->Dst[i];
593
594
if (!first_reg)
595
CHR( ',' );
596
CHR( ' ' );
597
598
_dump_register_dst( ctx, dst );
599
_dump_writemask( ctx, dst->Register.WriteMask );
600
601
first_reg = FALSE;
602
}
603
604
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
605
const struct tgsi_full_src_register *src = &inst->Src[i];
606
607
if (!first_reg)
608
CHR( ',' );
609
CHR( ' ' );
610
611
if (src->Register.Negate)
612
CHR( '-' );
613
if (src->Register.Absolute)
614
CHR( '|' );
615
616
_dump_register_src(ctx, src);
617
618
if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
619
src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
620
src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
621
src->Register.SwizzleW != TGSI_SWIZZLE_W) {
622
CHR( '.' );
623
ENM( src->Register.SwizzleX, tgsi_swizzle_names );
624
ENM( src->Register.SwizzleY, tgsi_swizzle_names );
625
ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
626
ENM( src->Register.SwizzleW, tgsi_swizzle_names );
627
}
628
629
if (src->Register.Absolute)
630
CHR( '|' );
631
632
first_reg = FALSE;
633
}
634
635
if (inst->Instruction.Texture) {
636
if (!(inst->Instruction.Opcode >= TGSI_OPCODE_SAMPLE &&
637
inst->Instruction.Opcode <= TGSI_OPCODE_GATHER4)) {
638
TXT( ", " );
639
ENM( inst->Texture.Texture, tgsi_texture_names );
640
}
641
for (i = 0; i < inst->Texture.NumOffsets; i++) {
642
TXT( ", " );
643
TXT(tgsi_file_name(inst->TexOffsets[i].File));
644
CHR( '[' );
645
SID( inst->TexOffsets[i].Index );
646
CHR( ']' );
647
CHR( '.' );
648
ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
649
ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
650
ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
651
}
652
}
653
654
if (inst->Instruction.Memory) {
655
uint32_t qualifier = inst->Memory.Qualifier;
656
while (qualifier) {
657
int bit = ffs(qualifier) - 1;
658
qualifier &= ~(1U << bit);
659
TXT(", ");
660
ENM(bit, tgsi_memory_names);
661
}
662
if (inst->Memory.Texture) {
663
TXT( ", " );
664
ENM( inst->Memory.Texture, tgsi_texture_names );
665
}
666
if (inst->Memory.Format) {
667
TXT( ", " );
668
TXT( util_format_name(inst->Memory.Format) );
669
}
670
}
671
672
if (inst->Instruction.Label) {
673
switch (inst->Instruction.Opcode) {
674
case TGSI_OPCODE_IF:
675
case TGSI_OPCODE_UIF:
676
case TGSI_OPCODE_ELSE:
677
case TGSI_OPCODE_BGNLOOP:
678
case TGSI_OPCODE_ENDLOOP:
679
case TGSI_OPCODE_CAL:
680
case TGSI_OPCODE_BGNSUB:
681
TXT( " :" );
682
UID( inst->Label.Label );
683
break;
684
}
685
}
686
687
/* update indentation */
688
if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
689
inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
690
inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
691
inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
692
ctx->indentation += indent_spaces;
693
}
694
695
EOL();
696
697
return TRUE;
698
}
699
700
void
701
tgsi_dump_instruction(
702
const struct tgsi_full_instruction *inst,
703
uint instno )
704
{
705
struct dump_ctx ctx;
706
memset(&ctx, 0, sizeof(ctx));
707
708
ctx.instno = instno;
709
ctx.immno = instno;
710
ctx.indent = 0;
711
ctx.dump_printf = dump_ctx_printf;
712
ctx.indentation = 0;
713
ctx.file = NULL;
714
715
iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
716
}
717
718
static boolean
719
prolog(
720
struct tgsi_iterate_context *iter )
721
{
722
struct dump_ctx *ctx = (struct dump_ctx *) iter;
723
ENM( iter->processor.Processor, tgsi_processor_type_names );
724
EOL();
725
return TRUE;
726
}
727
728
static void
729
init_dump_ctx(struct dump_ctx *ctx, uint flags)
730
{
731
memset(ctx, 0, sizeof(*ctx));
732
733
ctx->iter.prolog = prolog;
734
ctx->iter.iterate_instruction = iter_instruction;
735
ctx->iter.iterate_declaration = iter_declaration;
736
ctx->iter.iterate_immediate = iter_immediate;
737
ctx->iter.iterate_property = iter_property;
738
739
if (flags & TGSI_DUMP_FLOAT_AS_HEX)
740
ctx->dump_float_as_hex = TRUE;
741
}
742
743
void
744
tgsi_dump_to_file(const struct tgsi_token *tokens, uint flags, FILE *file)
745
{
746
struct dump_ctx ctx;
747
memset(&ctx, 0, sizeof(ctx));
748
749
init_dump_ctx(&ctx, flags);
750
751
ctx.dump_printf = dump_ctx_printf;
752
ctx.file = file;
753
754
tgsi_iterate_shader( tokens, &ctx.iter );
755
}
756
757
void
758
tgsi_dump(const struct tgsi_token *tokens, uint flags)
759
{
760
tgsi_dump_to_file(tokens, flags, NULL);
761
}
762
763
struct str_dump_ctx
764
{
765
struct dump_ctx base;
766
char *str;
767
char *ptr;
768
int left;
769
bool nospace;
770
};
771
772
static void
773
str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
774
{
775
struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
776
777
if (!sctx->nospace) {
778
int written;
779
va_list ap;
780
va_start(ap, format);
781
written = vsnprintf(sctx->ptr, sctx->left, format, ap);
782
va_end(ap);
783
784
/* Some complicated logic needed to handle the return value of
785
* vsnprintf:
786
*/
787
if (written > 0) {
788
if (written >= sctx->left) {
789
sctx->nospace = true;
790
written = sctx->left;
791
}
792
sctx->ptr += written;
793
sctx->left -= written;
794
}
795
}
796
}
797
798
bool
799
tgsi_dump_str(
800
const struct tgsi_token *tokens,
801
uint flags,
802
char *str,
803
size_t size)
804
{
805
struct str_dump_ctx ctx;
806
memset(&ctx, 0, sizeof(ctx));
807
808
init_dump_ctx(&ctx.base, flags);
809
810
ctx.base.dump_printf = &str_dump_ctx_printf;
811
812
ctx.str = str;
813
ctx.str[0] = 0;
814
ctx.ptr = str;
815
ctx.left = (int)size;
816
ctx.nospace = false;
817
818
tgsi_iterate_shader( tokens, &ctx.base.iter );
819
820
return !ctx.nospace;
821
}
822
823
void
824
tgsi_dump_instruction_str(
825
const struct tgsi_full_instruction *inst,
826
uint instno,
827
char *str,
828
size_t size)
829
{
830
struct str_dump_ctx ctx;
831
memset(&ctx, 0, sizeof(ctx));
832
833
ctx.base.instno = instno;
834
ctx.base.immno = instno;
835
ctx.base.indent = 0;
836
ctx.base.dump_printf = &str_dump_ctx_printf;
837
ctx.base.indentation = 0;
838
ctx.base.file = NULL;
839
840
ctx.str = str;
841
ctx.str[0] = 0;
842
ctx.ptr = str;
843
ctx.left = (int)size;
844
ctx.nospace = false;
845
846
iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst );
847
}
848
849