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