tgsi_dump.c revision c208a2c791fa24c7c5887fc496738cbddbfafc72
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 "pipe/p_debug.h"
29#include "tgsi_dump.h"
30#include "tgsi_iterate.h"
31
32struct dump_ctx
33{
34   struct tgsi_iterate_context iter;
35
36   uint instno;
37};
38
39static void
40dump_enum(
41   uint e,
42   const char **enums,
43   uint enum_count )
44{
45   if (e >= enum_count)
46      debug_printf( "%u", e );
47   else
48      debug_printf( "%s", enums[e] );
49}
50
51#define EOL()           debug_printf( "\n" )
52#define TXT(S)          debug_printf( "%s", S )
53#define CHR(C)          debug_printf( "%c", C )
54#define UIX(I)          debug_printf( "0x%x", I )
55#define UID(I)          debug_printf( "%u", I )
56#define SID(I)          debug_printf( "%d", I )
57#define FLT(F)          debug_printf( "%10.4f", F )
58#define ENM(E,ENUMS)    dump_enum( E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
59
60static const char *processor_type_names[] =
61{
62   "FRAG",
63   "VERT",
64   "GEOM"
65};
66
67static const char *file_names[] =
68{
69   "NULL",
70   "CONST",
71   "IN",
72   "OUT",
73   "TEMP",
74   "SAMP",
75   "ADDR",
76   "IMM"
77};
78
79static const char *interpolate_names[] =
80{
81   "CONSTANT",
82   "LINEAR",
83   "PERSPECTIVE"
84};
85
86static const char *semantic_names[] =
87{
88   "POSITION",
89   "COLOR",
90   "BCOLOR",
91   "FOG",
92   "PSIZE",
93   "GENERIC",
94   "NORMAL"
95};
96
97static const char *immediate_type_names[] =
98{
99   "FLT32"
100};
101
102static const char *opcode_names[TGSI_OPCODE_LAST] =
103{
104   "ARL",
105   "MOV",
106   "LIT",
107   "RCP",
108   "RSQ",
109   "EXP",
110   "LOG",
111   "MUL",
112   "ADD",
113   "DP3",
114   "DP4",
115   "DST",
116   "MIN",
117   "MAX",
118   "SLT",
119   "SGE",
120   "MAD",
121   "SUB",
122   "LERP",
123   "CND",
124   "CND0",
125   "DOT2ADD",
126   "INDEX",
127   "NEGATE",
128   "FRAC",
129   "CLAMP",
130   "FLOOR",
131   "ROUND",
132   "EXPBASE2",
133   "LOGBASE2",
134   "POWER",
135   "CROSSPRODUCT",
136   "MULTIPLYMATRIX",
137   "ABS",
138   "RCC",
139   "DPH",
140   "COS",
141   "DDX",
142   "DDY",
143   "KILP",
144   "PK2H",
145   "PK2US",
146   "PK4B",
147   "PK4UB",
148   "RFL",
149   "SEQ",
150   "SFL",
151   "SGT",
152   "SIN",
153   "SLE",
154   "SNE",
155   "STR",
156   "TEX",
157   "TXD",
158   "TXP",
159   "UP2H",
160   "UP2US",
161   "UP4B",
162   "UP4UB",
163   "X2D",
164   "ARA",
165   "ARR",
166   "BRA",
167   "CAL",
168   "RET",
169   "SSG",
170   "CMP",
171   "SCS",
172   "TXB",
173   "NRM",
174   "DIV",
175   "DP2",
176   "TXL",
177   "BRK",
178   "IF",
179   "LOOP",
180   "REP",
181   "ELSE",
182   "ENDIF",
183   "ENDLOOP",
184   "ENDREP",
185   "PUSHA",
186   "POPA",
187   "CEIL",
188   "I2F",
189   "NOT",
190   "TRUNC",
191   "SHL",
192   "SHR",
193   "AND",
194   "OR",
195   "MOD",
196   "XOR",
197   "SAD",
198   "TXF",
199   "TXQ",
200   "CONT",
201   "EMIT",
202   "ENDPRIM",
203   "BGNLOOP2",
204   "BGNSUB",
205   "ENDLOOP2",
206   "ENDSUB",
207   "NOISE1",
208   "NOISE2",
209   "NOISE3",
210   "NOISE4",
211   "NOP",
212   "M4X3",
213   "M3X4",
214   "M3X3",
215   "M3X2",
216   "NRM4",
217   "CALLNZ",
218   "IFC",
219   "BREAKC",
220   "KIL",
221   "END",
222   "SWZ"
223};
224
225static const char *swizzle_names[] =
226{
227   "x",
228   "y",
229   "z",
230   "w"
231};
232
233static const char *texture_names[] =
234{
235   "UNKNOWN",
236   "1D",
237   "2D",
238   "3D",
239   "CUBE",
240   "RECT",
241   "SHADOW1D",
242   "SHADOW2D",
243   "SHADOWRECT"
244};
245
246static const char *extswizzle_names[] =
247{
248   "x",
249   "y",
250   "z",
251   "w",
252   "0",
253   "1"
254};
255
256static const char *modulate_names[TGSI_MODULATE_COUNT] =
257{
258   "",
259   "_2X",
260   "_4X",
261   "_8X",
262   "_D2",
263   "_D4",
264   "_D8"
265};
266
267static void
268_dump_register_prefix(
269   uint file,
270   uint first,
271   uint last )
272{
273
274
275}
276
277static void
278_dump_register(
279   uint file,
280   int first,
281   int last )
282{
283   ENM( file, file_names );
284   CHR( '[' );
285   SID( first );
286   if (first != last) {
287      TXT( ".." );
288      SID( last );
289   }
290   CHR( ']' );
291}
292
293static void
294_dump_register_ind(
295   uint file,
296   int index,
297   uint ind_file,
298   int ind_index )
299{
300   ENM( file, file_names );
301   CHR( '[' );
302   ENM( ind_file, file_names );
303   CHR( '[' );
304   SID( ind_index );
305   CHR( ']' );
306   if (index != 0) {
307      if (index > 0)
308         CHR( '+' );
309      SID( index );
310   }
311   CHR( ']' );
312}
313
314static void
315_dump_writemask(
316   uint writemask )
317{
318   if (writemask != TGSI_WRITEMASK_XYZW) {
319      CHR( '.' );
320      if (writemask & TGSI_WRITEMASK_X)
321         CHR( 'x' );
322      if (writemask & TGSI_WRITEMASK_Y)
323         CHR( 'y' );
324      if (writemask & TGSI_WRITEMASK_Z)
325         CHR( 'z' );
326      if (writemask & TGSI_WRITEMASK_W)
327         CHR( 'w' );
328   }
329}
330
331void
332tgsi_dump_declaration(
333   const struct tgsi_full_declaration *decl )
334{
335   TXT( "\nDCL " );
336
337   _dump_register(
338      decl->Declaration.File,
339      decl->DeclarationRange.First,
340      decl->DeclarationRange.Last );
341   _dump_writemask(
342      decl->Declaration.UsageMask );
343
344   if (decl->Declaration.Semantic) {
345      TXT( ", " );
346      ENM( decl->Semantic.SemanticName, semantic_names );
347      if (decl->Semantic.SemanticIndex != 0 ||
348          decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC) {
349         CHR( '[' );
350         UID( decl->Semantic.SemanticIndex );
351         CHR( ']' );
352      }
353   }
354
355   TXT( ", " );
356   ENM( decl->Declaration.Interpolate, interpolate_names );
357}
358
359static boolean
360iter_declaration(
361   struct tgsi_iterate_context *iter,
362   struct tgsi_full_declaration *decl )
363{
364   tgsi_dump_declaration( decl );
365   return TRUE;
366}
367
368void
369tgsi_dump_immediate(
370   const struct tgsi_full_immediate *imm )
371{
372   uint i;
373
374   TXT( "\nIMM " );
375   ENM( imm->Immediate.DataType, immediate_type_names );
376
377   TXT( " { " );
378   for (i = 0; i < imm->Immediate.Size - 1; i++) {
379      switch (imm->Immediate.DataType) {
380      case TGSI_IMM_FLOAT32:
381         FLT( imm->u.ImmediateFloat32[i].Float );
382         break;
383      default:
384         assert( 0 );
385      }
386
387      if (i < imm->Immediate.Size - 2)
388         TXT( ", " );
389   }
390   TXT( " }" );
391}
392
393static boolean
394iter_immediate(
395   struct tgsi_iterate_context *iter,
396   struct tgsi_full_immediate *imm )
397{
398   tgsi_dump_immediate( imm );
399   return TRUE;
400}
401
402void
403tgsi_dump_instruction(
404   const struct tgsi_full_instruction *inst,
405   uint instno )
406{
407   uint i;
408   boolean first_reg = TRUE;
409
410   EOL();
411   UID( instno );
412   CHR( ':' );
413   ENM( inst->Instruction.Opcode, opcode_names );
414
415   switch (inst->Instruction.Saturate) {
416   case TGSI_SAT_NONE:
417      break;
418   case TGSI_SAT_ZERO_ONE:
419      TXT( "_SAT" );
420      break;
421   case TGSI_SAT_MINUS_PLUS_ONE:
422      TXT( "_SATNV" );
423      break;
424   default:
425      assert( 0 );
426   }
427
428   for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
429      const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
430
431      if (!first_reg)
432         CHR( ',' );
433      CHR( ' ' );
434
435      _dump_register(
436         dst->DstRegister.File,
437         dst->DstRegister.Index,
438         dst->DstRegister.Index );
439      ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
440      _dump_writemask( dst->DstRegister.WriteMask );
441
442      first_reg = FALSE;
443   }
444
445   for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
446      const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
447
448      if (!first_reg)
449         CHR( ',' );
450      CHR( ' ' );
451
452      if (src->SrcRegisterExtMod.Negate)
453         TXT( "-(" );
454      if (src->SrcRegisterExtMod.Absolute)
455         CHR( '|' );
456      if (src->SrcRegisterExtMod.Scale2X)
457         TXT( "2*(" );
458      if (src->SrcRegisterExtMod.Bias)
459         CHR( '(' );
460      if (src->SrcRegisterExtMod.Complement)
461         TXT( "1-(" );
462      if (src->SrcRegister.Negate)
463         CHR( '-' );
464
465      if (src->SrcRegister.Indirect) {
466         _dump_register_ind(
467            src->SrcRegister.File,
468            src->SrcRegister.Index,
469            src->SrcRegisterInd.File,
470            src->SrcRegisterInd.Index );
471      }
472      else {
473         _dump_register(
474            src->SrcRegister.File,
475            src->SrcRegister.Index,
476            src->SrcRegister.Index );
477      }
478
479      if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
480          src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
481          src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
482          src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
483         CHR( '.' );
484         ENM( src->SrcRegister.SwizzleX, swizzle_names );
485         ENM( src->SrcRegister.SwizzleY, swizzle_names );
486         ENM( src->SrcRegister.SwizzleZ, swizzle_names );
487         ENM( src->SrcRegister.SwizzleW, swizzle_names );
488      }
489      if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
490          src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
491          src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
492          src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
493         CHR( '.' );
494         if (src->SrcRegisterExtSwz.NegateX)
495            TXT("-");
496         ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names );
497         if (src->SrcRegisterExtSwz.NegateY)
498            TXT("-");
499         ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names );
500         if (src->SrcRegisterExtSwz.NegateZ)
501            TXT("-");
502         ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names );
503         if (src->SrcRegisterExtSwz.NegateW)
504            TXT("-");
505         ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names );
506      }
507
508      if (src->SrcRegisterExtMod.Complement)
509         CHR( ')' );
510      if (src->SrcRegisterExtMod.Bias)
511         TXT( ")-.5" );
512      if (src->SrcRegisterExtMod.Scale2X)
513         CHR( ')' );
514      if (src->SrcRegisterExtMod.Absolute)
515         CHR( '|' );
516      if (src->SrcRegisterExtMod.Negate)
517         CHR( ')' );
518
519      first_reg = FALSE;
520   }
521
522   if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) {
523      TXT( ", " );
524      ENM( inst->InstructionExtTexture.Texture, texture_names );
525   }
526
527   switch (inst->Instruction.Opcode) {
528   case TGSI_OPCODE_IF:
529   case TGSI_OPCODE_ELSE:
530   case TGSI_OPCODE_BGNLOOP2:
531   case TGSI_OPCODE_ENDLOOP2:
532   case TGSI_OPCODE_CAL:
533      TXT( " :" );
534      UID( inst->InstructionExtLabel.Label );
535      break;
536   }
537}
538
539static boolean
540iter_instruction(
541   struct tgsi_iterate_context *iter,
542   struct tgsi_full_instruction *inst )
543{
544   struct dump_ctx *ctx = (struct dump_ctx *) iter;
545
546   tgsi_dump_instruction( inst, ctx->instno++ );
547   return TRUE;
548}
549
550static boolean
551prolog(
552   struct tgsi_iterate_context *ctx )
553{
554   EOL();
555   ENM( ctx->processor.Processor, processor_type_names );
556   UID( ctx->version.MajorVersion );
557   CHR( '.' );
558   UID( ctx->version.MinorVersion );
559   return TRUE;
560}
561
562void
563tgsi_dump(
564   const struct tgsi_token *tokens,
565   uint flags )
566{
567   struct dump_ctx ctx;
568
569   /* sanity checks */
570   assert( strcmp( opcode_names[TGSI_OPCODE_CONT], "CONT" ) == 0 );
571   assert( strcmp( opcode_names[TGSI_OPCODE_END], "END" ) == 0 );
572
573   ctx.iter.prolog = prolog;
574   ctx.iter.iterate_instruction = iter_instruction;
575   ctx.iter.iterate_declaration = iter_declaration;
576   ctx.iter.iterate_immediate = iter_immediate;
577   ctx.iter.epilog = NULL;
578
579   ctx.instno = 0;
580
581   tgsi_iterate_shader( tokens, &ctx.iter );
582}
583