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