tgsi_dump.c revision 43714e92e3b512307851349fd8c706638030854e
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 34struct 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 43static void 44dump_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 53static void 54dump_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 76static const char *processor_type_names[] = 77{ 78 "FRAG", 79 "VERT", 80 "GEOM" 81}; 82 83static const char *file_names[] = 84{ 85 "NULL", 86 "CONST", 87 "IN", 88 "OUT", 89 "TEMP", 90 "SAMP", 91 "ADDR", 92 "IMM" 93}; 94 95static const char *interpolate_names[] = 96{ 97 "CONSTANT", 98 "LINEAR", 99 "PERSPECTIVE" 100}; 101 102static const char *semantic_names[] = 103{ 104 "POSITION", 105 "COLOR", 106 "BCOLOR", 107 "FOG", 108 "PSIZE", 109 "GENERIC", 110 "NORMAL" 111}; 112 113static const char *immediate_type_names[] = 114{ 115 "FLT32" 116}; 117 118static const char *swizzle_names[] = 119{ 120 "x", 121 "y", 122 "z", 123 "w" 124}; 125 126static 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 139static const char *extswizzle_names[] = 140{ 141 "x", 142 "y", 143 "z", 144 "w", 145 "0", 146 "1" 147}; 148 149static const char *modulate_names[TGSI_MODULATE_COUNT] = 150{ 151 "", 152 "_2X", 153 "_4X", 154 "_8X", 155 "_D2", 156 "_D4", 157 "_D8" 158}; 159 160static 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 177static 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 201static 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 219static boolean 220iter_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 268void 269tgsi_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 279static boolean 280iter_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 311void 312tgsi_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 322static boolean 323iter_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 469void 470tgsi_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 482static boolean 483prolog( 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 495void 496tgsi_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 514struct str_dump_ctx 515{ 516 struct dump_ctx base; 517 char *str; 518 char *ptr; 519 size_t left; 520}; 521 522static void 523str_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 538void 539tgsi_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} 563