00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "pipe/p_debug.h"
00029 #include "util/u_string.h"
00030 #include "util/u_math.h"
00031 #include "tgsi_dump.h"
00032 #include "tgsi_info.h"
00033 #include "tgsi_iterate.h"
00034
00035 struct dump_ctx
00036 {
00037 struct tgsi_iterate_context iter;
00038
00039 uint instno;
00040 int indent;
00041
00042 void (*printf)(struct dump_ctx *ctx, const char *format, ...);
00043 };
00044
00045 static void
00046 dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
00047 {
00048 va_list ap;
00049 (void)ctx;
00050 va_start(ap, format);
00051 debug_vprintf(format, ap);
00052 va_end(ap);
00053 }
00054
00055 static void
00056 dump_enum(
00057 struct dump_ctx *ctx,
00058 uint e,
00059 const char **enums,
00060 uint enum_count )
00061 {
00062 if (e >= enum_count)
00063 ctx->printf( ctx, "%u", e );
00064 else
00065 ctx->printf( ctx, "%s", enums[e] );
00066 }
00067
00068 #define EOL() ctx->printf( ctx, "\n" )
00069 #define TXT(S) ctx->printf( ctx, "%s", S )
00070 #define CHR(C) ctx->printf( ctx, "%c", C )
00071 #define UIX(I) ctx->printf( ctx, "0x%x", I )
00072 #define UID(I) ctx->printf( ctx, "%u", I )
00073 #define INSTID(I) ctx->printf( ctx, "% 3u", I )
00074 #define SID(I) ctx->printf( ctx, "%d", I )
00075 #define FLT(F) ctx->printf( ctx, "%10.4f", F )
00076 #define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
00077
00078 static const char *processor_type_names[] =
00079 {
00080 "FRAG",
00081 "VERT",
00082 "GEOM"
00083 };
00084
00085 static const char *file_names[TGSI_FILE_COUNT] =
00086 {
00087 "NULL",
00088 "CONST",
00089 "IN",
00090 "OUT",
00091 "TEMP",
00092 "SAMP",
00093 "ADDR",
00094 "IMM",
00095 "LOOP"
00096 };
00097
00098 static const char *interpolate_names[] =
00099 {
00100 "CONSTANT",
00101 "LINEAR",
00102 "PERSPECTIVE"
00103 };
00104
00105 static const char *semantic_names[] =
00106 {
00107 "POSITION",
00108 "COLOR",
00109 "BCOLOR",
00110 "FOG",
00111 "PSIZE",
00112 "GENERIC",
00113 "NORMAL"
00114 };
00115
00116 static const char *immediate_type_names[] =
00117 {
00118 "FLT32"
00119 };
00120
00121 static const char *swizzle_names[] =
00122 {
00123 "x",
00124 "y",
00125 "z",
00126 "w"
00127 };
00128
00129 static const char *texture_names[] =
00130 {
00131 "UNKNOWN",
00132 "1D",
00133 "2D",
00134 "3D",
00135 "CUBE",
00136 "RECT",
00137 "SHADOW1D",
00138 "SHADOW2D",
00139 "SHADOWRECT"
00140 };
00141
00142 static const char *extswizzle_names[] =
00143 {
00144 "x",
00145 "y",
00146 "z",
00147 "w",
00148 "0",
00149 "1"
00150 };
00151
00152 static const char *modulate_names[TGSI_MODULATE_COUNT] =
00153 {
00154 "",
00155 "_2X",
00156 "_4X",
00157 "_8X",
00158 "_D2",
00159 "_D4",
00160 "_D8"
00161 };
00162
00163 static void
00164 _dump_register(
00165 struct dump_ctx *ctx,
00166 uint file,
00167 int first,
00168 int last )
00169 {
00170 ENM( file, file_names );
00171 CHR( '[' );
00172 SID( first );
00173 if (first != last) {
00174 TXT( ".." );
00175 SID( last );
00176 }
00177 CHR( ']' );
00178 }
00179
00180 static void
00181 _dump_register_ind(
00182 struct dump_ctx *ctx,
00183 uint file,
00184 int index,
00185 uint ind_file,
00186 int ind_index,
00187 uint ind_swizzle )
00188 {
00189 ENM( file, file_names );
00190 CHR( '[' );
00191 ENM( ind_file, file_names );
00192 CHR( '[' );
00193 SID( ind_index );
00194 TXT( "]." );
00195 ENM( ind_swizzle, swizzle_names );
00196 if (index != 0) {
00197 if (index > 0)
00198 CHR( '+' );
00199 SID( index );
00200 }
00201 CHR( ']' );
00202 }
00203
00204 static void
00205 _dump_writemask(
00206 struct dump_ctx *ctx,
00207 uint writemask )
00208 {
00209 if (writemask != TGSI_WRITEMASK_XYZW) {
00210 CHR( '.' );
00211 if (writemask & TGSI_WRITEMASK_X)
00212 CHR( 'x' );
00213 if (writemask & TGSI_WRITEMASK_Y)
00214 CHR( 'y' );
00215 if (writemask & TGSI_WRITEMASK_Z)
00216 CHR( 'z' );
00217 if (writemask & TGSI_WRITEMASK_W)
00218 CHR( 'w' );
00219 }
00220 }
00221
00222 static boolean
00223 iter_declaration(
00224 struct tgsi_iterate_context *iter,
00225 struct tgsi_full_declaration *decl )
00226 {
00227 struct dump_ctx *ctx = (struct dump_ctx *)iter;
00228
00229 TXT( "DCL " );
00230
00231 _dump_register(
00232 ctx,
00233 decl->Declaration.File,
00234 decl->DeclarationRange.First,
00235 decl->DeclarationRange.Last );
00236 _dump_writemask(
00237 ctx,
00238 decl->Declaration.UsageMask );
00239
00240 if (decl->Declaration.Semantic) {
00241 TXT( ", " );
00242 ENM( decl->Semantic.SemanticName, semantic_names );
00243 if (decl->Semantic.SemanticIndex != 0 ||
00244 decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC) {
00245 CHR( '[' );
00246 UID( decl->Semantic.SemanticIndex );
00247 CHR( ']' );
00248 }
00249 }
00250
00251 if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
00252 decl->Declaration.File == TGSI_FILE_INPUT)
00253 {
00254 TXT( ", " );
00255 ENM( decl->Declaration.Interpolate, interpolate_names );
00256 }
00257
00258 if (decl->Declaration.Centroid) {
00259 TXT( ", CENTROID" );
00260 }
00261
00262 if (decl->Declaration.Invariant) {
00263 TXT( ", INVARIANT" );
00264 }
00265
00266 EOL();
00267
00268 return TRUE;
00269 }
00270
00271 void
00272 tgsi_dump_declaration(
00273 const struct tgsi_full_declaration *decl )
00274 {
00275 struct dump_ctx ctx;
00276
00277 ctx.printf = dump_ctx_printf;
00278
00279 iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
00280 }
00281
00282 static boolean
00283 iter_immediate(
00284 struct tgsi_iterate_context *iter,
00285 struct tgsi_full_immediate *imm )
00286 {
00287 struct dump_ctx *ctx = (struct dump_ctx *) iter;
00288
00289 uint i;
00290
00291 TXT( "IMM " );
00292 ENM( imm->Immediate.DataType, immediate_type_names );
00293
00294 TXT( " { " );
00295 for (i = 0; i < imm->Immediate.Size - 1; i++) {
00296 switch (imm->Immediate.DataType) {
00297 case TGSI_IMM_FLOAT32:
00298 FLT( imm->u.ImmediateFloat32[i].Float );
00299 break;
00300 default:
00301 assert( 0 );
00302 }
00303
00304 if (i < imm->Immediate.Size - 2)
00305 TXT( ", " );
00306 }
00307 TXT( " }" );
00308
00309 EOL();
00310
00311 return TRUE;
00312 }
00313
00314 void
00315 tgsi_dump_immediate(
00316 const struct tgsi_full_immediate *imm )
00317 {
00318 struct dump_ctx ctx;
00319
00320 ctx.printf = dump_ctx_printf;
00321
00322 iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
00323 }
00324
00325 static boolean
00326 iter_instruction(
00327 struct tgsi_iterate_context *iter,
00328 struct tgsi_full_instruction *inst )
00329 {
00330 struct dump_ctx *ctx = (struct dump_ctx *) iter;
00331 uint instno = ctx->instno++;
00332 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
00333 uint i;
00334 boolean first_reg = TRUE;
00335
00336 INSTID( instno );
00337 TXT( ": " );
00338
00339 ctx->indent -= info->pre_dedent;
00340 for(i = 0; (int)i < ctx->indent; ++i)
00341 TXT( " " );
00342 ctx->indent += info->post_indent;
00343
00344 TXT( info->mnemonic );
00345
00346 switch (inst->Instruction.Saturate) {
00347 case TGSI_SAT_NONE:
00348 break;
00349 case TGSI_SAT_ZERO_ONE:
00350 TXT( "_SAT" );
00351 break;
00352 case TGSI_SAT_MINUS_PLUS_ONE:
00353 TXT( "_SATNV" );
00354 break;
00355 default:
00356 assert( 0 );
00357 }
00358
00359 for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
00360 const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
00361
00362 if (!first_reg)
00363 CHR( ',' );
00364 CHR( ' ' );
00365
00366 _dump_register(
00367 ctx,
00368 dst->DstRegister.File,
00369 dst->DstRegister.Index,
00370 dst->DstRegister.Index );
00371 ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
00372 _dump_writemask( ctx, dst->DstRegister.WriteMask );
00373
00374 first_reg = FALSE;
00375 }
00376
00377 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
00378 const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i];
00379
00380 if (!first_reg)
00381 CHR( ',' );
00382 CHR( ' ' );
00383
00384 if (src->SrcRegisterExtMod.Negate)
00385 TXT( "-(" );
00386 if (src->SrcRegisterExtMod.Absolute)
00387 CHR( '|' );
00388 if (src->SrcRegisterExtMod.Scale2X)
00389 TXT( "2*(" );
00390 if (src->SrcRegisterExtMod.Bias)
00391 CHR( '(' );
00392 if (src->SrcRegisterExtMod.Complement)
00393 TXT( "1-(" );
00394 if (src->SrcRegister.Negate)
00395 CHR( '-' );
00396
00397 if (src->SrcRegister.Indirect) {
00398 _dump_register_ind(
00399 ctx,
00400 src->SrcRegister.File,
00401 src->SrcRegister.Index,
00402 src->SrcRegisterInd.File,
00403 src->SrcRegisterInd.Index,
00404 src->SrcRegisterInd.SwizzleX );
00405 }
00406 else {
00407 _dump_register(
00408 ctx,
00409 src->SrcRegister.File,
00410 src->SrcRegister.Index,
00411 src->SrcRegister.Index );
00412 }
00413
00414 if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X ||
00415 src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y ||
00416 src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z ||
00417 src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) {
00418 CHR( '.' );
00419 ENM( src->SrcRegister.SwizzleX, swizzle_names );
00420 ENM( src->SrcRegister.SwizzleY, swizzle_names );
00421 ENM( src->SrcRegister.SwizzleZ, swizzle_names );
00422 ENM( src->SrcRegister.SwizzleW, swizzle_names );
00423 }
00424 if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X ||
00425 src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y ||
00426 src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z ||
00427 src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) {
00428 CHR( '.' );
00429 if (src->SrcRegisterExtSwz.NegateX)
00430 TXT("-");
00431 ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names );
00432 if (src->SrcRegisterExtSwz.NegateY)
00433 TXT("-");
00434 ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names );
00435 if (src->SrcRegisterExtSwz.NegateZ)
00436 TXT("-");
00437 ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names );
00438 if (src->SrcRegisterExtSwz.NegateW)
00439 TXT("-");
00440 ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names );
00441 }
00442
00443 if (src->SrcRegisterExtMod.Complement)
00444 CHR( ')' );
00445 if (src->SrcRegisterExtMod.Bias)
00446 TXT( ")-.5" );
00447 if (src->SrcRegisterExtMod.Scale2X)
00448 CHR( ')' );
00449 if (src->SrcRegisterExtMod.Absolute)
00450 CHR( '|' );
00451 if (src->SrcRegisterExtMod.Negate)
00452 CHR( ')' );
00453
00454 first_reg = FALSE;
00455 }
00456
00457 if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) {
00458 TXT( ", " );
00459 ENM( inst->InstructionExtTexture.Texture, texture_names );
00460 }
00461
00462 switch (inst->Instruction.Opcode) {
00463 case TGSI_OPCODE_IF:
00464 case TGSI_OPCODE_ELSE:
00465 case TGSI_OPCODE_BGNLOOP2:
00466 case TGSI_OPCODE_ENDLOOP2:
00467 case TGSI_OPCODE_CAL:
00468 TXT( " :" );
00469 UID( inst->InstructionExtLabel.Label );
00470 break;
00471 }
00472
00473 EOL();
00474
00475 return TRUE;
00476 }
00477
00478 void
00479 tgsi_dump_instruction(
00480 const struct tgsi_full_instruction *inst,
00481 uint instno )
00482 {
00483 struct dump_ctx ctx;
00484
00485 ctx.instno = instno;
00486 ctx.indent = 0;
00487 ctx.printf = dump_ctx_printf;
00488
00489 iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
00490 }
00491
00492 static boolean
00493 prolog(
00494 struct tgsi_iterate_context *iter )
00495 {
00496 struct dump_ctx *ctx = (struct dump_ctx *) iter;
00497 ENM( iter->processor.Processor, processor_type_names );
00498 UID( iter->version.MajorVersion );
00499 CHR( '.' );
00500 UID( iter->version.MinorVersion );
00501 EOL();
00502 return TRUE;
00503 }
00504
00505 void
00506 tgsi_dump(
00507 const struct tgsi_token *tokens,
00508 uint flags )
00509 {
00510 struct dump_ctx ctx;
00511
00512 ctx.iter.prolog = prolog;
00513 ctx.iter.iterate_instruction = iter_instruction;
00514 ctx.iter.iterate_declaration = iter_declaration;
00515 ctx.iter.iterate_immediate = iter_immediate;
00516 ctx.iter.epilog = NULL;
00517
00518 ctx.instno = 0;
00519 ctx.indent = 0;
00520 ctx.printf = dump_ctx_printf;
00521
00522 tgsi_iterate_shader( tokens, &ctx.iter );
00523 }
00524
00525 struct str_dump_ctx
00526 {
00527 struct dump_ctx base;
00528 char *str;
00529 char *ptr;
00530 int left;
00531 };
00532
00533 static void
00534 str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
00535 {
00536 struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
00537
00538 if(sctx->left > 1) {
00539 int written;
00540 va_list ap;
00541 va_start(ap, format);
00542 written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
00543 va_end(ap);
00544
00545
00546
00547
00548 if (written > 0) {
00549 written = MIN2(sctx->left, written);
00550 sctx->ptr += written;
00551 sctx->left -= written;
00552 }
00553 }
00554 }
00555
00556 void
00557 tgsi_dump_str(
00558 const struct tgsi_token *tokens,
00559 uint flags,
00560 char *str,
00561 size_t size)
00562 {
00563 struct str_dump_ctx ctx;
00564
00565 ctx.base.iter.prolog = prolog;
00566 ctx.base.iter.iterate_instruction = iter_instruction;
00567 ctx.base.iter.iterate_declaration = iter_declaration;
00568 ctx.base.iter.iterate_immediate = iter_immediate;
00569 ctx.base.iter.epilog = NULL;
00570
00571 ctx.base.instno = 0;
00572 ctx.base.indent = 0;
00573 ctx.base.printf = &str_dump_ctx_printf;
00574
00575 ctx.str = str;
00576 ctx.str[0] = 0;
00577 ctx.ptr = str;
00578 ctx.left = (int)size;
00579
00580 tgsi_iterate_shader( tokens, &ctx.base.iter );
00581 }