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 EOL();
250
251 return TRUE;
252 }
253
254 void
255 tgsi_dump_declaration(
256 const struct tgsi_full_declaration *decl )
257 {
258 struct dump_ctx ctx;
259
260 ctx.printf = dump_ctx_printf;
261
262 iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
263 }
264
265 static boolean
266 iter_immediate(
267 struct tgsi_iterate_context *iter,
268 struct tgsi_full_immediate *imm )
269 {
270 struct dump_ctx *ctx = (struct dump_ctx *) iter;
271
272 uint i;
273
274 TXT( "IMM " );
275 ENM( imm->Immediate.DataType, immediate_type_names );
276
277 TXT( " { " );
278 for (i = 0; i < imm->Immediate.Size - 1; i++) {
279 switch (imm->Immediate.DataType) {
280 case TGSI_IMM_FLOAT32:
281 FLT( imm->u.ImmediateFloat32[i].Float );
282 break;
283 default:
284 assert( 0 );
285 }
286
287 if (i < imm->Immediate.Size - 2)
288 TXT( ", " );
289 }
290 TXT( " }" );
291
292 EOL();
293
294 return TRUE;
295 }
296
297 void
298 tgsi_dump_immediate(
299 const struct tgsi_full_immediate *imm )
300 {
301 struct dump_ctx ctx;
302
303 ctx.printf = dump_ctx_printf;
304
305 iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
306 }
307
308 static boolean
309 iter_instruction(
310 struct tgsi_iterate_context *iter,
311 struct tgsi_full_instruction *inst )
312 {
313 struct dump_ctx *ctx = (struct dump_ctx *) iter;
314 uint instno = ctx->instno++;
315
316 uint i;
317 boolean first_reg = TRUE;
318
319 INSTID( instno );
320 TXT( ": " );
321 TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic );
322
323 switch (inst->Instruction.Saturate) {
324 case TGSI_SAT_NONE:
325 break;
326 case TGSI_SAT_ZERO_ONE:
327 TXT( "_SAT" );
328 break;
329 case TGSI_SAT_MINUS_PLUS_ONE:
330 TXT( "_SATNV" );
331 break;
332 default:
333 assert( 0 );
334 }
335
336 for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
337 const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
338
339 if (!first_reg)
340 CHR( ',' );
341 CHR( ' ' );
342
343 _dump_register(
344 ctx,
345 dst->DstRegister.File,
346 dst->DstRegister.Index,
347 dst->DstRegister.Index );
348 ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
349 _dump_writemask( ctx, dst->DstRegister.WriteMask );
350
351 first_reg = FALSE;
352 }
353
354 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
355 const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
356
357 if (!first_reg)
358 CHR( ',' );
359 CHR( ' ' );
360
361 if (src->SrcRegisterExtMod.Negate)
362 TXT( "-(" );
363 if (src->SrcRegisterExtMod.Absolute)
364 CHR( '|' );
365 if (src->SrcRegisterExtMod.Scale2X)
366 TXT( "2*(" );
367 if (src->SrcRegisterExtMod.Bias)
368 CHR( '(' );
369 if (src->SrcRegisterExtMod.Complement)
370 TXT( "1-(" );
371 if (src->SrcRegister.Negate)
372 CHR( '-' );
373
374 if (src->SrcRegister.Indirect) {
375 _dump_register_ind(
376 ctx,
377 src->SrcRegister.File,
378 src->SrcRegister.Index,
379 src->SrcRegisterInd.File,
380 src->SrcRegisterInd.Index );
381 }
382 else {
383 _dump_register(
384 ctx,
385 src->SrcRegister.File,
386 src->SrcRegister.Index,
387 src->SrcRegister.Index );
388 }
389
390 if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
391 src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
392 src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
393 src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
394 CHR( '.' );
395 ENM( src->SrcRegister.SwizzleX, swizzle_names );
396 ENM( src->SrcRegister.SwizzleY, swizzle_names );
397 ENM( src->SrcRegister.SwizzleZ, swizzle_names );
398 ENM( src->SrcRegister.SwizzleW, swizzle_names );
399 }
400 if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
401 src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
402 src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
403 src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
404 CHR( '.' );
405 if (src->SrcRegisterExtSwz.NegateX)
406 TXT("-");
407 ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names );
408 if (src->SrcRegisterExtSwz.NegateY)
409 TXT("-");
410 ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names );
411 if (src->SrcRegisterExtSwz.NegateZ)
412 TXT("-");
413 ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names );
414 if (src->SrcRegisterExtSwz.NegateW)
415 TXT("-");
416 ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names );
417 }
418
419 if (src->SrcRegisterExtMod.Complement)
420 CHR( ')' );
421 if (src->SrcRegisterExtMod.Bias)
422 TXT( ")-.5" );
423 if (src->SrcRegisterExtMod.Scale2X)
424 CHR( ')' );
425 if (src->SrcRegisterExtMod.Absolute)
426 CHR( '|' );
427 if (src->SrcRegisterExtMod.Negate)
428 CHR( ')' );
429
430 first_reg = FALSE;
431 }
432
433 if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) {
434 TXT( ", " );
435 ENM( inst->InstructionExtTexture.Texture, texture_names );
436 }
437
438 switch (inst->Instruction.Opcode) {
439 case TGSI_OPCODE_IF:
440 case TGSI_OPCODE_ELSE:
441 case TGSI_OPCODE_BGNLOOP2:
442 case TGSI_OPCODE_ENDLOOP2:
443 case TGSI_OPCODE_CAL:
444 TXT( " :" );
445 UID( inst->InstructionExtLabel.Label );
446 break;
447 }
448
449 EOL();
450
451 return TRUE;
452 }
453
454 void
455 tgsi_dump_instruction(
456 const struct tgsi_full_instruction *inst,
457 uint instno )
458 {
459 struct dump_ctx ctx;
460
461 ctx.instno = instno;
462 ctx.printf = dump_ctx_printf;
463
464 iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
465 }
466
467 static boolean
468 prolog(
469 struct tgsi_iterate_context *iter )
470 {
471 struct dump_ctx *ctx = (struct dump_ctx *) iter;
472 ENM( iter->processor.Processor, processor_type_names );
473 UID( iter->version.MajorVersion );
474 CHR( '.' );
475 UID( iter->version.MinorVersion );
476 EOL();
477 return TRUE;
478 }
479
480 void
481 tgsi_dump(
482 const struct tgsi_token *tokens,
483 uint flags )
484 {
485 struct dump_ctx ctx;
486
487 ctx.iter.prolog = prolog;
488 ctx.iter.iterate_instruction = iter_instruction;
489 ctx.iter.iterate_declaration = iter_declaration;
490 ctx.iter.iterate_immediate = iter_immediate;
491 ctx.iter.epilog = NULL;
492
493 ctx.instno = 0;
494 ctx.printf = dump_ctx_printf;
495
496 tgsi_iterate_shader( tokens, &ctx.iter );
497 }
498
499 struct str_dump_ctx
500 {
501 struct dump_ctx base;
502 char *str;
503 char *ptr;
504 size_t left;
505 };
506
507 static void
508 str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
509 {
510 struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
511
512 if(sctx->left > 1) {
513 size_t written;
514 va_list ap;
515 va_start(ap, format);
516 written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
517 va_end(ap);
518 sctx->ptr += written;
519 sctx->left -= written;
520 }
521 }
522
523 void
524 tgsi_dump_str(
525 const struct tgsi_token *tokens,
526 uint flags,
527 char *str,
528 size_t size)
529 {
530 struct str_dump_ctx ctx;
531
532 ctx.base.iter.prolog = prolog;
533 ctx.base.iter.iterate_instruction = iter_instruction;
534 ctx.base.iter.iterate_declaration = iter_declaration;
535 ctx.base.iter.iterate_immediate = iter_immediate;
536 ctx.base.iter.epilog = NULL;
537
538 ctx.base.instno = 0;
539 ctx.base.printf = &str_dump_ctx_printf;
540
541 ctx.str = str;
542 ctx.str[0] = 0;
543 ctx.ptr = str;
544 ctx.left = size;
545
546 tgsi_iterate_shader( tokens, &ctx.base.iter );
547 }