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