tgsi: consolidate TGSI string arrays in new tgsi_strings.h
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_dump.c
1 /**************************************************************************
2 *
3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 "util/u_debug.h"
29 #include "util/u_string.h"
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
32 #include "tgsi_dump.h"
33 #include "tgsi_info.h"
34 #include "tgsi_iterate.h"
35 #include "tgsi_strings.h"
36
37
38 /** Number of spaces to indent for IF/LOOP/etc */
39 static const int indent_spaces = 3;
40
41
42 struct dump_ctx
43 {
44 struct tgsi_iterate_context iter;
45
46 uint instno;
47 int indent;
48
49 uint indentation;
50
51 void (*printf)(struct dump_ctx *ctx, const char *format, ...);
52 };
53
54 static void
55 dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
56 {
57 va_list ap;
58 (void)ctx;
59 va_start(ap, format);
60 _debug_vprintf(format, ap);
61 va_end(ap);
62 }
63
64 static void
65 dump_enum(
66 struct dump_ctx *ctx,
67 uint e,
68 const char **enums,
69 uint enum_count )
70 {
71 if (e >= enum_count)
72 ctx->printf( ctx, "%u", e );
73 else
74 ctx->printf( ctx, "%s", enums[e] );
75 }
76
77 #define EOL() ctx->printf( ctx, "\n" )
78 #define TXT(S) ctx->printf( ctx, "%s", S )
79 #define CHR(C) ctx->printf( ctx, "%c", C )
80 #define UIX(I) ctx->printf( ctx, "0x%x", I )
81 #define UID(I) ctx->printf( ctx, "%u", I )
82 #define INSTID(I) ctx->printf( ctx, "% 3u", I )
83 #define SID(I) ctx->printf( ctx, "%d", I )
84 #define FLT(F) ctx->printf( ctx, "%10.4f", F )
85 #define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
86
87 const char *
88 tgsi_swizzle_names[4] =
89 {
90 "x",
91 "y",
92 "z",
93 "w"
94 };
95
96 static void
97 _dump_register_src(
98 struct dump_ctx *ctx,
99 const struct tgsi_full_src_register *src )
100 {
101 ENM(src->Register.File, tgsi_file_names);
102 if (src->Register.Dimension) {
103 if (src->Dimension.Indirect) {
104 CHR( '[' );
105 ENM( src->DimIndirect.File, tgsi_file_names );
106 CHR( '[' );
107 SID( src->DimIndirect.Index );
108 TXT( "]." );
109 ENM( src->DimIndirect.SwizzleX, tgsi_swizzle_names );
110 if (src->Dimension.Index != 0) {
111 if (src->Dimension.Index > 0)
112 CHR( '+' );
113 SID( src->Dimension.Index );
114 }
115 CHR( ']' );
116 } else {
117 CHR('[');
118 SID(src->Dimension.Index);
119 CHR(']');
120 }
121 }
122 if (src->Register.Indirect) {
123 CHR( '[' );
124 ENM( src->Indirect.File, tgsi_file_names );
125 CHR( '[' );
126 SID( src->Indirect.Index );
127 TXT( "]." );
128 ENM( src->Indirect.SwizzleX, tgsi_swizzle_names );
129 if (src->Register.Index != 0) {
130 if (src->Register.Index > 0)
131 CHR( '+' );
132 SID( src->Register.Index );
133 }
134 CHR( ']' );
135 } else {
136 CHR( '[' );
137 SID( src->Register.Index );
138 CHR( ']' );
139 }
140 }
141
142
143 static void
144 _dump_register_dst(
145 struct dump_ctx *ctx,
146 const struct tgsi_full_dst_register *dst )
147 {
148 ENM(dst->Register.File, tgsi_file_names);
149 if (dst->Register.Dimension) {
150 if (dst->Dimension.Indirect) {
151 CHR( '[' );
152 ENM( dst->DimIndirect.File, tgsi_file_names );
153 CHR( '[' );
154 SID( dst->DimIndirect.Index );
155 TXT( "]." );
156 ENM( dst->DimIndirect.SwizzleX, tgsi_swizzle_names );
157 if (dst->Dimension.Index != 0) {
158 if (dst->Dimension.Index > 0)
159 CHR( '+' );
160 SID( dst->Dimension.Index );
161 }
162 CHR( ']' );
163 } else {
164 CHR('[');
165 SID(dst->Dimension.Index);
166 CHR(']');
167 }
168 }
169 if (dst->Register.Indirect) {
170 CHR( '[' );
171 ENM( dst->Indirect.File, tgsi_file_names );
172 CHR( '[' );
173 SID( dst->Indirect.Index );
174 TXT( "]." );
175 ENM( dst->Indirect.SwizzleX, tgsi_swizzle_names );
176 if (dst->Register.Index != 0) {
177 if (dst->Register.Index > 0)
178 CHR( '+' );
179 SID( dst->Register.Index );
180 }
181 CHR( ']' );
182 } else {
183 CHR( '[' );
184 SID( dst->Register.Index );
185 CHR( ']' );
186 }
187 }
188 static void
189 _dump_writemask(
190 struct dump_ctx *ctx,
191 uint writemask )
192 {
193 if (writemask != TGSI_WRITEMASK_XYZW) {
194 CHR( '.' );
195 if (writemask & TGSI_WRITEMASK_X)
196 CHR( 'x' );
197 if (writemask & TGSI_WRITEMASK_Y)
198 CHR( 'y' );
199 if (writemask & TGSI_WRITEMASK_Z)
200 CHR( 'z' );
201 if (writemask & TGSI_WRITEMASK_W)
202 CHR( 'w' );
203 }
204 }
205
206 static void
207 dump_imm_data(struct tgsi_iterate_context *iter,
208 union tgsi_immediate_data *data,
209 unsigned num_tokens,
210 unsigned data_type)
211 {
212 struct dump_ctx *ctx = (struct dump_ctx *)iter;
213 unsigned i ;
214
215 TXT( " {" );
216
217 assert( num_tokens <= 4 );
218 for (i = 0; i < num_tokens; i++) {
219 switch (data_type) {
220 case TGSI_IMM_FLOAT32:
221 FLT( data[i].Float );
222 break;
223 case TGSI_IMM_UINT32:
224 UID(data[i].Uint);
225 break;
226 case TGSI_IMM_INT32:
227 SID(data[i].Int);
228 break;
229 default:
230 assert( 0 );
231 }
232
233 if (i < num_tokens - 1)
234 TXT( ", " );
235 }
236 TXT( "}" );
237 }
238
239 static boolean
240 iter_declaration(
241 struct tgsi_iterate_context *iter,
242 struct tgsi_full_declaration *decl )
243 {
244 struct dump_ctx *ctx = (struct dump_ctx *)iter;
245
246 TXT( "DCL " );
247
248 ENM(decl->Declaration.File, tgsi_file_names);
249
250 /* all geometry shader inputs are two dimensional */
251 if (decl->Declaration.File == TGSI_FILE_INPUT &&
252 iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
253 TXT("[]");
254 }
255
256 if (decl->Declaration.Dimension) {
257 CHR('[');
258 SID(decl->Dim.Index2D);
259 CHR(']');
260 }
261
262 CHR('[');
263 SID(decl->Range.First);
264 if (decl->Range.First != decl->Range.Last) {
265 TXT("..");
266 SID(decl->Range.Last);
267 }
268 CHR(']');
269
270 _dump_writemask(
271 ctx,
272 decl->Declaration.UsageMask );
273
274 if (decl->Declaration.Semantic) {
275 TXT( ", " );
276 ENM( decl->Semantic.Name, tgsi_semantic_names );
277 if (decl->Semantic.Index != 0 ||
278 decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
279 CHR( '[' );
280 UID( decl->Semantic.Index );
281 CHR( ']' );
282 }
283 }
284
285 if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
286 TXT(", ");
287 ENM(decl->Resource.Resource, tgsi_texture_names);
288 TXT(", ");
289 if ((decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeY) &&
290 (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeZ) &&
291 (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeW)) {
292 ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
293 } else {
294 ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
295 TXT(", ");
296 ENM(decl->Resource.ReturnTypeY, tgsi_type_names);
297 TXT(", ");
298 ENM(decl->Resource.ReturnTypeZ, tgsi_type_names);
299 TXT(", ");
300 ENM(decl->Resource.ReturnTypeW, tgsi_type_names);
301 }
302
303 }
304
305 if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
306 decl->Declaration.File == TGSI_FILE_INPUT)
307 {
308 TXT( ", " );
309 ENM( decl->Declaration.Interpolate, tgsi_interpolate_names );
310 }
311
312 if (decl->Declaration.Centroid) {
313 TXT( ", CENTROID" );
314 }
315
316 if (decl->Declaration.Invariant) {
317 TXT( ", INVARIANT" );
318 }
319
320 if (decl->Declaration.CylindricalWrap) {
321 TXT(", CYLWRAP_");
322 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
323 CHR('X');
324 }
325 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
326 CHR('Y');
327 }
328 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
329 CHR('Z');
330 }
331 if (decl->Declaration.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
332 CHR('W');
333 }
334 }
335
336 if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) {
337 unsigned i;
338 char range_indent[4];
339
340 TXT(" {");
341
342 if (decl->Range.Last < 10)
343 range_indent[0] = '\0';
344 else if (decl->Range.Last < 100) {
345 range_indent[0] = ' ';
346 range_indent[1] = '\0';
347 } else if (decl->Range.Last < 1000) {
348 range_indent[0] = ' ';
349 range_indent[1] = ' ';
350 range_indent[2] = '\0';
351 } else {
352 range_indent[0] = ' ';
353 range_indent[1] = ' ';
354 range_indent[2] = ' ';
355 range_indent[3] = '\0';
356 }
357
358 dump_imm_data(iter, decl->ImmediateData.u,
359 4, TGSI_IMM_FLOAT32);
360 for(i = 1; i <= decl->Range.Last; ++i) {
361 /* indent by strlen of:
362 * "DCL IMMX[0..1] {" */
363 CHR('\n');
364 TXT( " " );
365 TXT( range_indent );
366 dump_imm_data(iter, decl->ImmediateData.u + i,
367 4, TGSI_IMM_FLOAT32);
368 }
369
370 TXT(" }");
371 }
372
373 EOL();
374
375 return TRUE;
376 }
377
378 void
379 tgsi_dump_declaration(
380 const struct tgsi_full_declaration *decl )
381 {
382 struct dump_ctx ctx;
383
384 ctx.printf = dump_ctx_printf;
385
386 iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
387 }
388
389 static boolean
390 iter_property(
391 struct tgsi_iterate_context *iter,
392 struct tgsi_full_property *prop )
393 {
394 int i;
395 struct dump_ctx *ctx = (struct dump_ctx *)iter;
396
397 TXT( "PROPERTY " );
398 ENM(prop->Property.PropertyName, tgsi_property_names);
399
400 if (prop->Property.NrTokens > 1)
401 TXT(" ");
402
403 for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
404 switch (prop->Property.PropertyName) {
405 case TGSI_PROPERTY_GS_INPUT_PRIM:
406 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
407 ENM(prop->u[i].Data, tgsi_primitive_names);
408 break;
409 case TGSI_PROPERTY_FS_COORD_ORIGIN:
410 ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
411 break;
412 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
413 ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
414 break;
415 default:
416 SID( prop->u[i].Data );
417 break;
418 }
419 if (i < prop->Property.NrTokens - 2)
420 TXT( ", " );
421 }
422 EOL();
423
424 return TRUE;
425 }
426
427 void tgsi_dump_property(
428 const struct tgsi_full_property *prop )
429 {
430 struct dump_ctx ctx;
431
432 ctx.printf = dump_ctx_printf;
433
434 iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
435 }
436
437 static boolean
438 iter_immediate(
439 struct tgsi_iterate_context *iter,
440 struct tgsi_full_immediate *imm )
441 {
442 struct dump_ctx *ctx = (struct dump_ctx *) iter;
443
444 TXT( "IMM " );
445 ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
446
447 dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
448 imm->Immediate.DataType);
449
450 EOL();
451
452 return TRUE;
453 }
454
455 void
456 tgsi_dump_immediate(
457 const struct tgsi_full_immediate *imm )
458 {
459 struct dump_ctx ctx;
460
461 ctx.printf = dump_ctx_printf;
462
463 iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
464 }
465
466 static boolean
467 iter_instruction(
468 struct tgsi_iterate_context *iter,
469 struct tgsi_full_instruction *inst )
470 {
471 struct dump_ctx *ctx = (struct dump_ctx *) iter;
472 uint instno = ctx->instno++;
473 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
474 uint i;
475 boolean first_reg = TRUE;
476
477 INSTID( instno );
478 TXT( ": " );
479
480 ctx->indent -= info->pre_dedent;
481 for(i = 0; (int)i < ctx->indent; ++i)
482 TXT( " " );
483 ctx->indent += info->post_indent;
484
485 if (inst->Instruction.Predicate) {
486 CHR( '(' );
487
488 if (inst->Predicate.Negate)
489 CHR( '!' );
490
491 TXT( "PRED[" );
492 SID( inst->Predicate.Index );
493 CHR( ']' );
494
495 if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
496 inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
497 inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
498 inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
499 CHR( '.' );
500 ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
501 ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
502 ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
503 ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
504 }
505
506 TXT( ") " );
507 }
508
509 TXT( info->mnemonic );
510
511 switch (inst->Instruction.Saturate) {
512 case TGSI_SAT_NONE:
513 break;
514 case TGSI_SAT_ZERO_ONE:
515 TXT( "_SAT" );
516 break;
517 case TGSI_SAT_MINUS_PLUS_ONE:
518 TXT( "_SATNV" );
519 break;
520 default:
521 assert( 0 );
522 }
523
524 for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
525 const struct tgsi_full_dst_register *dst = &inst->Dst[i];
526
527 if (!first_reg)
528 CHR( ',' );
529 CHR( ' ' );
530
531 _dump_register_dst( ctx, dst );
532 _dump_writemask( ctx, dst->Register.WriteMask );
533
534 first_reg = FALSE;
535 }
536
537 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
538 const struct tgsi_full_src_register *src = &inst->Src[i];
539
540 if (!first_reg)
541 CHR( ',' );
542 CHR( ' ' );
543
544 if (src->Register.Negate)
545 CHR( '-' );
546 if (src->Register.Absolute)
547 CHR( '|' );
548
549 _dump_register_src(ctx, src);
550
551 if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
552 src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
553 src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
554 src->Register.SwizzleW != TGSI_SWIZZLE_W) {
555 CHR( '.' );
556 ENM( src->Register.SwizzleX, tgsi_swizzle_names );
557 ENM( src->Register.SwizzleY, tgsi_swizzle_names );
558 ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
559 ENM( src->Register.SwizzleW, tgsi_swizzle_names );
560 }
561
562 if (src->Register.Absolute)
563 CHR( '|' );
564
565 first_reg = FALSE;
566 }
567
568 if (inst->Instruction.Texture) {
569 TXT( ", " );
570 ENM( inst->Texture.Texture, tgsi_texture_names );
571 for (i = 0; i < inst->Texture.NumOffsets; i++) {
572 TXT( ", " );
573 ENM( inst->TexOffsets[i].File, tgsi_file_names);
574 CHR( '[' );
575 SID( inst->TexOffsets[i].Index );
576 CHR( ']' );
577 CHR( '.' );
578 ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
579 ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
580 ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
581 }
582 }
583
584 switch (inst->Instruction.Opcode) {
585 case TGSI_OPCODE_IF:
586 case TGSI_OPCODE_ELSE:
587 case TGSI_OPCODE_BGNLOOP:
588 case TGSI_OPCODE_ENDLOOP:
589 case TGSI_OPCODE_CAL:
590 TXT( " :" );
591 UID( inst->Label.Label );
592 break;
593 }
594
595 /* update indentation */
596 if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
597 inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
598 inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
599 ctx->indentation += indent_spaces;
600 }
601
602 EOL();
603
604 return TRUE;
605 }
606
607 void
608 tgsi_dump_instruction(
609 const struct tgsi_full_instruction *inst,
610 uint instno )
611 {
612 struct dump_ctx ctx;
613
614 ctx.instno = instno;
615 ctx.indent = 0;
616 ctx.printf = dump_ctx_printf;
617 ctx.indentation = 0;
618
619 iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
620 }
621
622 static boolean
623 prolog(
624 struct tgsi_iterate_context *iter )
625 {
626 struct dump_ctx *ctx = (struct dump_ctx *) iter;
627 ENM( iter->processor.Processor, tgsi_processor_type_names );
628 EOL();
629 return TRUE;
630 }
631
632 void
633 tgsi_dump(
634 const struct tgsi_token *tokens,
635 uint flags )
636 {
637 struct dump_ctx ctx;
638
639 ctx.iter.prolog = prolog;
640 ctx.iter.iterate_instruction = iter_instruction;
641 ctx.iter.iterate_declaration = iter_declaration;
642 ctx.iter.iterate_immediate = iter_immediate;
643 ctx.iter.iterate_property = iter_property;
644 ctx.iter.epilog = NULL;
645
646 ctx.instno = 0;
647 ctx.indent = 0;
648 ctx.printf = dump_ctx_printf;
649 ctx.indentation = 0;
650
651 tgsi_iterate_shader( tokens, &ctx.iter );
652 }
653
654 struct str_dump_ctx
655 {
656 struct dump_ctx base;
657 char *str;
658 char *ptr;
659 int left;
660 };
661
662 static void
663 str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
664 {
665 struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
666
667 if(sctx->left > 1) {
668 int written;
669 va_list ap;
670 va_start(ap, format);
671 written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
672 va_end(ap);
673
674 /* Some complicated logic needed to handle the return value of
675 * vsnprintf:
676 */
677 if (written > 0) {
678 written = MIN2(sctx->left, written);
679 sctx->ptr += written;
680 sctx->left -= written;
681 }
682 }
683 }
684
685 void
686 tgsi_dump_str(
687 const struct tgsi_token *tokens,
688 uint flags,
689 char *str,
690 size_t size)
691 {
692 struct str_dump_ctx ctx;
693
694 ctx.base.iter.prolog = prolog;
695 ctx.base.iter.iterate_instruction = iter_instruction;
696 ctx.base.iter.iterate_declaration = iter_declaration;
697 ctx.base.iter.iterate_immediate = iter_immediate;
698 ctx.base.iter.iterate_property = iter_property;
699 ctx.base.iter.epilog = NULL;
700
701 ctx.base.instno = 0;
702 ctx.base.indent = 0;
703 ctx.base.printf = &str_dump_ctx_printf;
704 ctx.base.indentation = 0;
705
706 ctx.str = str;
707 ctx.str[0] = 0;
708 ctx.ptr = str;
709 ctx.left = (int)size;
710
711 tgsi_iterate_shader( tokens, &ctx.base.iter );
712 }