tgsi_dump.c revision b8a7eef242f6bb97d90f6e0303d270b2cbc58421
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 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 SID(I) ctx->printf( ctx, "%d", I ) 72#define FLT(F) ctx->printf( ctx, "%10.4f", F ) 73#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) 74 75static const char *processor_type_names[] = 76{ 77 "FRAG", 78 "VERT", 79 "GEOM" 80}; 81 82static const char *file_names[] = 83{ 84 "NULL", 85 "CONST", 86 "IN", 87 "OUT", 88 "TEMP", 89 "SAMP", 90 "ADDR", 91 "IMM" 92}; 93 94static const char *interpolate_names[] = 95{ 96 "CONSTANT", 97 "LINEAR", 98 "PERSPECTIVE" 99}; 100 101static const char *semantic_names[] = 102{ 103 "POSITION", 104 "COLOR", 105 "BCOLOR", 106 "FOG", 107 "PSIZE", 108 "GENERIC", 109 "NORMAL" 110}; 111 112static const char *immediate_type_names[] = 113{ 114 "FLT32" 115}; 116 117static const char *swizzle_names[] = 118{ 119 "x", 120 "y", 121 "z", 122 "w" 123}; 124 125static const char *texture_names[] = 126{ 127 "UNKNOWN", 128 "1D", 129 "2D", 130 "3D", 131 "CUBE", 132 "RECT", 133 "SHADOW1D", 134 "SHADOW2D", 135 "SHADOWRECT" 136}; 137 138static const char *extswizzle_names[] = 139{ 140 "x", 141 "y", 142 "z", 143 "w", 144 "0", 145 "1" 146}; 147 148static const char *modulate_names[TGSI_MODULATE_COUNT] = 149{ 150 "", 151 "_2X", 152 "_4X", 153 "_8X", 154 "_D2", 155 "_D4", 156 "_D8" 157}; 158 159static void 160_dump_register( 161 struct dump_ctx *ctx, 162 uint file, 163 int first, 164 int last ) 165{ 166 ENM( file, file_names ); 167 CHR( '[' ); 168 SID( first ); 169 if (first != last) { 170 TXT( ".." ); 171 SID( last ); 172 } 173 CHR( ']' ); 174} 175 176static void 177_dump_register_ind( 178 struct dump_ctx *ctx, 179 uint file, 180 int index, 181 uint ind_file, 182 int ind_index ) 183{ 184 ENM( file, file_names ); 185 CHR( '[' ); 186 ENM( ind_file, file_names ); 187 CHR( '[' ); 188 SID( ind_index ); 189 CHR( ']' ); 190 if (index != 0) { 191 if (index > 0) 192 CHR( '+' ); 193 SID( index ); 194 } 195 CHR( ']' ); 196} 197 198static void 199_dump_writemask( 200 struct dump_ctx *ctx, 201 uint writemask ) 202{ 203 if (writemask != TGSI_WRITEMASK_XYZW) { 204 CHR( '.' ); 205 if (writemask & TGSI_WRITEMASK_X) 206 CHR( 'x' ); 207 if (writemask & TGSI_WRITEMASK_Y) 208 CHR( 'y' ); 209 if (writemask & TGSI_WRITEMASK_Z) 210 CHR( 'z' ); 211 if (writemask & TGSI_WRITEMASK_W) 212 CHR( 'w' ); 213 } 214} 215 216static boolean 217iter_declaration( 218 struct tgsi_iterate_context *iter, 219 struct tgsi_full_declaration *decl ) 220{ 221 struct dump_ctx *ctx = (struct dump_ctx *)iter; 222 223 TXT( "DCL " ); 224 225 _dump_register( 226 ctx, 227 decl->Declaration.File, 228 decl->DeclarationRange.First, 229 decl->DeclarationRange.Last ); 230 _dump_writemask( 231 ctx, 232 decl->Declaration.UsageMask ); 233 234 if (decl->Declaration.Semantic) { 235 TXT( ", " ); 236 ENM( decl->Semantic.SemanticName, semantic_names ); 237 if (decl->Semantic.SemanticIndex != 0 || 238 decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC) { 239 CHR( '[' ); 240 UID( decl->Semantic.SemanticIndex ); 241 CHR( ']' ); 242 } 243 } 244 245 TXT( ", " ); 246 ENM( decl->Declaration.Interpolate, interpolate_names ); 247 248 EOL(); 249 250 return TRUE; 251} 252 253void 254tgsi_dump_declaration( 255 const struct tgsi_full_declaration *decl ) 256{ 257 struct dump_ctx ctx; 258 259 ctx.printf = dump_ctx_printf; 260 261 iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl ); 262} 263 264static boolean 265iter_immediate( 266 struct tgsi_iterate_context *iter, 267 struct tgsi_full_immediate *imm ) 268{ 269 struct dump_ctx *ctx = (struct dump_ctx *) iter; 270 271 uint i; 272 273 TXT( "IMM " ); 274 ENM( imm->Immediate.DataType, immediate_type_names ); 275 276 TXT( " { " ); 277 for (i = 0; i < imm->Immediate.Size - 1; i++) { 278 switch (imm->Immediate.DataType) { 279 case TGSI_IMM_FLOAT32: 280 FLT( imm->u.ImmediateFloat32[i].Float ); 281 break; 282 default: 283 assert( 0 ); 284 } 285 286 if (i < imm->Immediate.Size - 2) 287 TXT( ", " ); 288 } 289 TXT( " }" ); 290 291 EOL(); 292 293 return TRUE; 294} 295 296void 297tgsi_dump_immediate( 298 const struct tgsi_full_immediate *imm ) 299{ 300 struct dump_ctx ctx; 301 302 ctx.printf = dump_ctx_printf; 303 304 iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm ); 305} 306 307static boolean 308iter_instruction( 309 struct tgsi_iterate_context *iter, 310 struct tgsi_full_instruction *inst ) 311{ 312 struct dump_ctx *ctx = (struct dump_ctx *) iter; 313 uint instno = ctx->instno++; 314 315 uint i; 316 boolean first_reg = TRUE; 317 318 UID( instno ); 319 CHR( ':' ); 320 TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic ); 321 322 switch (inst->Instruction.Saturate) { 323 case TGSI_SAT_NONE: 324 break; 325 case TGSI_SAT_ZERO_ONE: 326 TXT( "_SAT" ); 327 break; 328 case TGSI_SAT_MINUS_PLUS_ONE: 329 TXT( "_SATNV" ); 330 break; 331 default: 332 assert( 0 ); 333 } 334 335 for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 336 const struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; 337 338 if (!first_reg) 339 CHR( ',' ); 340 CHR( ' ' ); 341 342 _dump_register( 343 ctx, 344 dst->DstRegister.File, 345 dst->DstRegister.Index, 346 dst->DstRegister.Index ); 347 ENM( dst->DstRegisterExtModulate.Modulate, modulate_names ); 348 _dump_writemask( ctx, dst->DstRegister.WriteMask ); 349 350 first_reg = FALSE; 351 } 352 353 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { 354 const struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i]; 355 356 if (!first_reg) 357 CHR( ',' ); 358 CHR( ' ' ); 359 360 if (src->SrcRegisterExtMod.Negate) 361 TXT( "-(" ); 362 if (src->SrcRegisterExtMod.Absolute) 363 CHR( '|' ); 364 if (src->SrcRegisterExtMod.Scale2X) 365 TXT( "2*(" ); 366 if (src->SrcRegisterExtMod.Bias) 367 CHR( '(' ); 368 if (src->SrcRegisterExtMod.Complement) 369 TXT( "1-(" ); 370 if (src->SrcRegister.Negate) 371 CHR( '-' ); 372 373 if (src->SrcRegister.Indirect) { 374 _dump_register_ind( 375 ctx, 376 src->SrcRegister.File, 377 src->SrcRegister.Index, 378 src->SrcRegisterInd.File, 379 src->SrcRegisterInd.Index ); 380 } 381 else { 382 _dump_register( 383 ctx, 384 src->SrcRegister.File, 385 src->SrcRegister.Index, 386 src->SrcRegister.Index ); 387 } 388 389 if (src->SrcRegister.SwizzleX != TGSI_SWIZZLE_X || 390 src->SrcRegister.SwizzleY != TGSI_SWIZZLE_Y || 391 src->SrcRegister.SwizzleZ != TGSI_SWIZZLE_Z || 392 src->SrcRegister.SwizzleW != TGSI_SWIZZLE_W) { 393 CHR( '.' ); 394 ENM( src->SrcRegister.SwizzleX, swizzle_names ); 395 ENM( src->SrcRegister.SwizzleY, swizzle_names ); 396 ENM( src->SrcRegister.SwizzleZ, swizzle_names ); 397 ENM( src->SrcRegister.SwizzleW, swizzle_names ); 398 } 399 if (src->SrcRegisterExtSwz.ExtSwizzleX != TGSI_EXTSWIZZLE_X || 400 src->SrcRegisterExtSwz.ExtSwizzleY != TGSI_EXTSWIZZLE_Y || 401 src->SrcRegisterExtSwz.ExtSwizzleZ != TGSI_EXTSWIZZLE_Z || 402 src->SrcRegisterExtSwz.ExtSwizzleW != TGSI_EXTSWIZZLE_W) { 403 CHR( '.' ); 404 if (src->SrcRegisterExtSwz.NegateX) 405 TXT("-"); 406 ENM( src->SrcRegisterExtSwz.ExtSwizzleX, extswizzle_names ); 407 if (src->SrcRegisterExtSwz.NegateY) 408 TXT("-"); 409 ENM( src->SrcRegisterExtSwz.ExtSwizzleY, extswizzle_names ); 410 if (src->SrcRegisterExtSwz.NegateZ) 411 TXT("-"); 412 ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, extswizzle_names ); 413 if (src->SrcRegisterExtSwz.NegateW) 414 TXT("-"); 415 ENM( src->SrcRegisterExtSwz.ExtSwizzleW, extswizzle_names ); 416 } 417 418 if (src->SrcRegisterExtMod.Complement) 419 CHR( ')' ); 420 if (src->SrcRegisterExtMod.Bias) 421 TXT( ")-.5" ); 422 if (src->SrcRegisterExtMod.Scale2X) 423 CHR( ')' ); 424 if (src->SrcRegisterExtMod.Absolute) 425 CHR( '|' ); 426 if (src->SrcRegisterExtMod.Negate) 427 CHR( ')' ); 428 429 first_reg = FALSE; 430 } 431 432 if (inst->InstructionExtTexture.Texture != TGSI_TEXTURE_UNKNOWN) { 433 TXT( ", " ); 434 ENM( inst->InstructionExtTexture.Texture, texture_names ); 435 } 436 437 switch (inst->Instruction.Opcode) { 438 case TGSI_OPCODE_IF: 439 case TGSI_OPCODE_ELSE: 440 case TGSI_OPCODE_BGNLOOP2: 441 case TGSI_OPCODE_ENDLOOP2: 442 case TGSI_OPCODE_CAL: 443 TXT( " :" ); 444 UID( inst->InstructionExtLabel.Label ); 445 break; 446 } 447 448 EOL(); 449 450 return TRUE; 451} 452 453void 454tgsi_dump_instruction( 455 const struct tgsi_full_instruction *inst, 456 uint instno ) 457{ 458 struct dump_ctx ctx; 459 460 ctx.instno = instno; 461 ctx.printf = dump_ctx_printf; 462 463 iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst ); 464} 465 466static boolean 467prolog( 468 struct tgsi_iterate_context *iter ) 469{ 470 struct dump_ctx *ctx = (struct dump_ctx *) iter; 471 ENM( iter->processor.Processor, processor_type_names ); 472 UID( iter->version.MajorVersion ); 473 CHR( '.' ); 474 UID( iter->version.MinorVersion ); 475 EOL(); 476 return TRUE; 477} 478 479void 480tgsi_dump( 481 const struct tgsi_token *tokens, 482 uint flags ) 483{ 484 struct dump_ctx ctx; 485 486 ctx.iter.prolog = prolog; 487 ctx.iter.iterate_instruction = iter_instruction; 488 ctx.iter.iterate_declaration = iter_declaration; 489 ctx.iter.iterate_immediate = iter_immediate; 490 ctx.iter.epilog = NULL; 491 492 ctx.instno = 0; 493 ctx.printf = dump_ctx_printf; 494 495 tgsi_iterate_shader( tokens, &ctx.iter ); 496} 497 498struct str_dump_ctx 499{ 500 struct dump_ctx base; 501 char *str; 502 char *ptr; 503 size_t left; 504}; 505 506static void 507str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) 508{ 509 struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx; 510 511 if(sctx->left > 1) { 512 size_t written; 513 va_list ap; 514 va_start(ap, format); 515 written = util_vsnprintf(sctx->ptr, sctx->left, format, ap); 516 va_end(ap); 517 sctx->ptr += written; 518 sctx->left -= written; 519 } 520} 521 522void 523tgsi_dump_str( 524 const struct tgsi_token *tokens, 525 uint flags, 526 char *str, 527 size_t size) 528{ 529 struct str_dump_ctx ctx; 530 531 ctx.base.iter.prolog = prolog; 532 ctx.base.iter.iterate_instruction = iter_instruction; 533 ctx.base.iter.iterate_declaration = iter_declaration; 534 ctx.base.iter.iterate_immediate = iter_immediate; 535 ctx.base.iter.epilog = NULL; 536 537 ctx.base.instno = 0; 538 ctx.base.printf = &str_dump_ctx_printf; 539 540 ctx.str = str; 541 ctx.str[0] = 0; 542 ctx.ptr = str; 543 ctx.left = size; 544 545 tgsi_iterate_shader( tokens, &ctx.base.iter ); 546} 547