Merge commit 'origin/gallium-0.1'
[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 "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
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 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
268 void
269 tgsi_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
279 static boolean
280 iter_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
311 void
312 tgsi_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
322 static boolean
323 iter_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
469 void
470 tgsi_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
482 static boolean
483 prolog(
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
495 void
496 tgsi_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
514 struct str_dump_ctx
515 {
516 struct dump_ctx base;
517 char *str;
518 char *ptr;
519 size_t left;
520 };
521
522 static void
523 str_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
538 void
539 tgsi_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 }