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