tgsi_dump.c revision a29e40a42382630c2d9d95d3a1e03a7b3db87add
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 "util/u_math.h" 31#include "util/u_memory.h" 32#include "tgsi_dump.h" 33#include "tgsi_info.h" 34#include "tgsi_iterate.h" 35#include "tgsi_strings.h" 36 37 38/** Number of spaces to indent for IF/LOOP/etc */ 39static const int indent_spaces = 3; 40 41 42struct dump_ctx 43{ 44 struct tgsi_iterate_context iter; 45 46 uint instno; 47 uint immno; 48 int indent; 49 50 uint indentation; 51 52 void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...); 53}; 54 55static void 56dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) 57{ 58 va_list ap; 59 (void)ctx; 60 va_start(ap, format); 61 _debug_vprintf(format, ap); 62 va_end(ap); 63} 64 65static void 66dump_enum( 67 struct dump_ctx *ctx, 68 uint e, 69 const char **enums, 70 uint enum_count ) 71{ 72 if (e >= enum_count) 73 ctx->dump_printf( ctx, "%u", e ); 74 else 75 ctx->dump_printf( ctx, "%s", enums[e] ); 76} 77 78#define EOL() ctx->dump_printf( ctx, "\n" ) 79#define TXT(S) ctx->dump_printf( ctx, "%s", S ) 80#define CHR(C) ctx->dump_printf( ctx, "%c", C ) 81#define UIX(I) ctx->dump_printf( ctx, "0x%x", I ) 82#define UID(I) ctx->dump_printf( ctx, "%u", I ) 83#define INSTID(I) ctx->dump_printf( ctx, "% 3u", I ) 84#define SID(I) ctx->dump_printf( ctx, "%d", I ) 85#define FLT(F) ctx->dump_printf( ctx, "%10.4f", F ) 86#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) 87 88const char * 89tgsi_swizzle_names[4] = 90{ 91 "x", 92 "y", 93 "z", 94 "w" 95}; 96 97static void 98_dump_register_src( 99 struct dump_ctx *ctx, 100 const struct tgsi_full_src_register *src ) 101{ 102 TXT(tgsi_file_name(src->Register.File)); 103 if (src->Register.Dimension) { 104 if (src->Dimension.Indirect) { 105 CHR( '[' ); 106 TXT(tgsi_file_name(src->DimIndirect.File)); 107 CHR( '[' ); 108 SID( src->DimIndirect.Index ); 109 TXT( "]." ); 110 ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names ); 111 if (src->Dimension.Index != 0) { 112 if (src->Dimension.Index > 0) 113 CHR( '+' ); 114 SID( src->Dimension.Index ); 115 } 116 CHR( ']' ); 117 if (src->DimIndirect.ArrayID) { 118 CHR( '(' ); 119 SID( src->DimIndirect.ArrayID ); 120 CHR( ')' ); 121 } 122 } else { 123 CHR('['); 124 SID(src->Dimension.Index); 125 CHR(']'); 126 } 127 } 128 if (src->Register.Indirect) { 129 CHR( '[' ); 130 TXT(tgsi_file_name(src->Indirect.File)); 131 CHR( '[' ); 132 SID( src->Indirect.Index ); 133 TXT( "]." ); 134 ENM( src->Indirect.Swizzle, tgsi_swizzle_names ); 135 if (src->Register.Index != 0) { 136 if (src->Register.Index > 0) 137 CHR( '+' ); 138 SID( src->Register.Index ); 139 } 140 CHR( ']' ); 141 if (src->Indirect.ArrayID) { 142 CHR( '(' ); 143 SID( src->Indirect.ArrayID ); 144 CHR( ')' ); 145 } 146 } else { 147 CHR( '[' ); 148 SID( src->Register.Index ); 149 CHR( ']' ); 150 } 151} 152 153 154static void 155_dump_register_dst( 156 struct dump_ctx *ctx, 157 const struct tgsi_full_dst_register *dst ) 158{ 159 TXT(tgsi_file_name(dst->Register.File)); 160 if (dst->Register.Dimension) { 161 if (dst->Dimension.Indirect) { 162 CHR( '[' ); 163 TXT(tgsi_file_name(dst->DimIndirect.File)); 164 CHR( '[' ); 165 SID( dst->DimIndirect.Index ); 166 TXT( "]." ); 167 ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names ); 168 if (dst->Dimension.Index != 0) { 169 if (dst->Dimension.Index > 0) 170 CHR( '+' ); 171 SID( dst->Dimension.Index ); 172 } 173 CHR( ']' ); 174 if (dst->DimIndirect.ArrayID) { 175 CHR( '(' ); 176 SID( dst->DimIndirect.ArrayID ); 177 CHR( ')' ); 178 } 179 } else { 180 CHR('['); 181 SID(dst->Dimension.Index); 182 CHR(']'); 183 } 184 } 185 if (dst->Register.Indirect) { 186 CHR( '[' ); 187 TXT(tgsi_file_name(dst->Indirect.File)); 188 CHR( '[' ); 189 SID( dst->Indirect.Index ); 190 TXT( "]." ); 191 ENM( dst->Indirect.Swizzle, tgsi_swizzle_names ); 192 if (dst->Register.Index != 0) { 193 if (dst->Register.Index > 0) 194 CHR( '+' ); 195 SID( dst->Register.Index ); 196 } 197 CHR( ']' ); 198 if (dst->Indirect.ArrayID) { 199 CHR( '(' ); 200 SID( dst->Indirect.ArrayID ); 201 CHR( ')' ); 202 } 203 } else { 204 CHR( '[' ); 205 SID( dst->Register.Index ); 206 CHR( ']' ); 207 } 208} 209static void 210_dump_writemask( 211 struct dump_ctx *ctx, 212 uint writemask ) 213{ 214 if (writemask != TGSI_WRITEMASK_XYZW) { 215 CHR( '.' ); 216 if (writemask & TGSI_WRITEMASK_X) 217 CHR( 'x' ); 218 if (writemask & TGSI_WRITEMASK_Y) 219 CHR( 'y' ); 220 if (writemask & TGSI_WRITEMASK_Z) 221 CHR( 'z' ); 222 if (writemask & TGSI_WRITEMASK_W) 223 CHR( 'w' ); 224 } 225} 226 227static void 228dump_imm_data(struct tgsi_iterate_context *iter, 229 union tgsi_immediate_data *data, 230 unsigned num_tokens, 231 unsigned data_type) 232{ 233 struct dump_ctx *ctx = (struct dump_ctx *)iter; 234 unsigned i ; 235 236 TXT( " {" ); 237 238 assert( num_tokens <= 4 ); 239 for (i = 0; i < num_tokens; i++) { 240 switch (data_type) { 241 case TGSI_IMM_FLOAT32: 242 FLT( data[i].Float ); 243 break; 244 case TGSI_IMM_UINT32: 245 UID(data[i].Uint); 246 break; 247 case TGSI_IMM_INT32: 248 SID(data[i].Int); 249 break; 250 default: 251 assert( 0 ); 252 } 253 254 if (i < num_tokens - 1) 255 TXT( ", " ); 256 } 257 TXT( "}" ); 258} 259 260static boolean 261iter_declaration( 262 struct tgsi_iterate_context *iter, 263 struct tgsi_full_declaration *decl ) 264{ 265 struct dump_ctx *ctx = (struct dump_ctx *)iter; 266 267 TXT( "DCL " ); 268 269 TXT(tgsi_file_name(decl->Declaration.File)); 270 271 /* all geometry shader inputs are two dimensional */ 272 if (decl->Declaration.File == TGSI_FILE_INPUT && 273 iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) { 274 TXT("[]"); 275 } 276 277 if (decl->Declaration.Dimension) { 278 CHR('['); 279 SID(decl->Dim.Index2D); 280 CHR(']'); 281 } 282 283 CHR('['); 284 SID(decl->Range.First); 285 if (decl->Range.First != decl->Range.Last) { 286 TXT(".."); 287 SID(decl->Range.Last); 288 } 289 CHR(']'); 290 291 _dump_writemask( 292 ctx, 293 decl->Declaration.UsageMask ); 294 295 if (decl->Declaration.Array) { 296 TXT( ", ARRAY(" ); 297 SID(decl->Array.ArrayID); 298 CHR(')'); 299 } 300 301 if (decl->Declaration.Local) 302 TXT( ", LOCAL" ); 303 304 if (decl->Declaration.Semantic) { 305 TXT( ", " ); 306 ENM( decl->Semantic.Name, tgsi_semantic_names ); 307 if (decl->Semantic.Index != 0 || 308 decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD || 309 decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) { 310 CHR( '[' ); 311 UID( decl->Semantic.Index ); 312 CHR( ']' ); 313 } 314 } 315 316 if (decl->Declaration.File == TGSI_FILE_RESOURCE) { 317 TXT(", "); 318 ENM(decl->Resource.Resource, tgsi_texture_names); 319 if (decl->Resource.Writable) 320 TXT(", WR"); 321 if (decl->Resource.Raw) 322 TXT(", RAW"); 323 } 324 325 if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) { 326 TXT(", "); 327 ENM(decl->SamplerView.Resource, tgsi_texture_names); 328 TXT(", "); 329 if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) && 330 (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) && 331 (decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) { 332 ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names); 333 } else { 334 ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names); 335 TXT(", "); 336 ENM(decl->SamplerView.ReturnTypeY, tgsi_type_names); 337 TXT(", "); 338 ENM(decl->SamplerView.ReturnTypeZ, tgsi_type_names); 339 TXT(", "); 340 ENM(decl->SamplerView.ReturnTypeW, tgsi_type_names); 341 } 342 } 343 344 if (decl->Declaration.Interpolate) { 345 if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT && 346 decl->Declaration.File == TGSI_FILE_INPUT) 347 { 348 TXT( ", " ); 349 ENM( decl->Interp.Interpolate, tgsi_interpolate_names ); 350 } 351 352 if (decl->Interp.Centroid) { 353 TXT( ", CENTROID" ); 354 } 355 356 if (decl->Interp.CylindricalWrap) { 357 TXT(", CYLWRAP_"); 358 if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) { 359 CHR('X'); 360 } 361 if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) { 362 CHR('Y'); 363 } 364 if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) { 365 CHR('Z'); 366 } 367 if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) { 368 CHR('W'); 369 } 370 } 371 } 372 373 if (decl->Declaration.Invariant) { 374 TXT( ", INVARIANT" ); 375 } 376 377 EOL(); 378 379 return TRUE; 380} 381 382void 383tgsi_dump_declaration( 384 const struct tgsi_full_declaration *decl ) 385{ 386 struct dump_ctx ctx; 387 388 ctx.dump_printf = dump_ctx_printf; 389 390 iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl ); 391} 392 393static boolean 394iter_property( 395 struct tgsi_iterate_context *iter, 396 struct tgsi_full_property *prop ) 397{ 398 unsigned i; 399 struct dump_ctx *ctx = (struct dump_ctx *)iter; 400 401 TXT( "PROPERTY " ); 402 ENM(prop->Property.PropertyName, tgsi_property_names); 403 404 if (prop->Property.NrTokens > 1) 405 TXT(" "); 406 407 for (i = 0; i < prop->Property.NrTokens - 1; ++i) { 408 switch (prop->Property.PropertyName) { 409 case TGSI_PROPERTY_GS_INPUT_PRIM: 410 case TGSI_PROPERTY_GS_OUTPUT_PRIM: 411 ENM(prop->u[i].Data, tgsi_primitive_names); 412 break; 413 case TGSI_PROPERTY_FS_COORD_ORIGIN: 414 ENM(prop->u[i].Data, tgsi_fs_coord_origin_names); 415 break; 416 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: 417 ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names); 418 break; 419 default: 420 SID( prop->u[i].Data ); 421 break; 422 } 423 if (i < prop->Property.NrTokens - 2) 424 TXT( ", " ); 425 } 426 EOL(); 427 428 return TRUE; 429} 430 431void tgsi_dump_property( 432 const struct tgsi_full_property *prop ) 433{ 434 struct dump_ctx ctx; 435 436 ctx.dump_printf = dump_ctx_printf; 437 438 iter_property( &ctx.iter, (struct tgsi_full_property *)prop ); 439} 440 441static boolean 442iter_immediate( 443 struct tgsi_iterate_context *iter, 444 struct tgsi_full_immediate *imm ) 445{ 446 struct dump_ctx *ctx = (struct dump_ctx *) iter; 447 448 TXT( "IMM[" ); 449 SID( ctx->immno++ ); 450 TXT( "] " ); 451 ENM( imm->Immediate.DataType, tgsi_immediate_type_names ); 452 453 dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1, 454 imm->Immediate.DataType); 455 456 EOL(); 457 458 return TRUE; 459} 460 461void 462tgsi_dump_immediate( 463 const struct tgsi_full_immediate *imm ) 464{ 465 struct dump_ctx ctx; 466 467 ctx.dump_printf = dump_ctx_printf; 468 469 iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm ); 470} 471 472static boolean 473iter_instruction( 474 struct tgsi_iterate_context *iter, 475 struct tgsi_full_instruction *inst ) 476{ 477 struct dump_ctx *ctx = (struct dump_ctx *) iter; 478 uint instno = ctx->instno++; 479 const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode ); 480 uint i; 481 boolean first_reg = TRUE; 482 483 INSTID( instno ); 484 TXT( ": " ); 485 486 ctx->indent -= info->pre_dedent; 487 for(i = 0; (int)i < ctx->indent; ++i) 488 TXT( " " ); 489 ctx->indent += info->post_indent; 490 491 if (inst->Instruction.Predicate) { 492 CHR( '(' ); 493 494 if (inst->Predicate.Negate) 495 CHR( '!' ); 496 497 TXT( "PRED[" ); 498 SID( inst->Predicate.Index ); 499 CHR( ']' ); 500 501 if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X || 502 inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y || 503 inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z || 504 inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) { 505 CHR( '.' ); 506 ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names ); 507 ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names ); 508 ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names ); 509 ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names ); 510 } 511 512 TXT( ") " ); 513 } 514 515 TXT( info->mnemonic ); 516 517 switch (inst->Instruction.Saturate) { 518 case TGSI_SAT_NONE: 519 break; 520 case TGSI_SAT_ZERO_ONE: 521 TXT( "_SAT" ); 522 break; 523 case TGSI_SAT_MINUS_PLUS_ONE: 524 TXT( "_SATNV" ); 525 break; 526 default: 527 assert( 0 ); 528 } 529 530 for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 531 const struct tgsi_full_dst_register *dst = &inst->Dst[i]; 532 533 if (!first_reg) 534 CHR( ',' ); 535 CHR( ' ' ); 536 537 _dump_register_dst( ctx, dst ); 538 _dump_writemask( ctx, dst->Register.WriteMask ); 539 540 first_reg = FALSE; 541 } 542 543 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { 544 const struct tgsi_full_src_register *src = &inst->Src[i]; 545 546 if (!first_reg) 547 CHR( ',' ); 548 CHR( ' ' ); 549 550 if (src->Register.Negate) 551 CHR( '-' ); 552 if (src->Register.Absolute) 553 CHR( '|' ); 554 555 _dump_register_src(ctx, src); 556 557 if (src->Register.SwizzleX != TGSI_SWIZZLE_X || 558 src->Register.SwizzleY != TGSI_SWIZZLE_Y || 559 src->Register.SwizzleZ != TGSI_SWIZZLE_Z || 560 src->Register.SwizzleW != TGSI_SWIZZLE_W) { 561 CHR( '.' ); 562 ENM( src->Register.SwizzleX, tgsi_swizzle_names ); 563 ENM( src->Register.SwizzleY, tgsi_swizzle_names ); 564 ENM( src->Register.SwizzleZ, tgsi_swizzle_names ); 565 ENM( src->Register.SwizzleW, tgsi_swizzle_names ); 566 } 567 568 if (src->Register.Absolute) 569 CHR( '|' ); 570 571 first_reg = FALSE; 572 } 573 574 if (inst->Instruction.Texture) { 575 TXT( ", " ); 576 ENM( inst->Texture.Texture, tgsi_texture_names ); 577 for (i = 0; i < inst->Texture.NumOffsets; i++) { 578 TXT( ", " ); 579 TXT(tgsi_file_name(inst->TexOffsets[i].File)); 580 CHR( '[' ); 581 SID( inst->TexOffsets[i].Index ); 582 CHR( ']' ); 583 CHR( '.' ); 584 ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names); 585 ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names); 586 ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names); 587 } 588 } 589 590 switch (inst->Instruction.Opcode) { 591 case TGSI_OPCODE_IF: 592 case TGSI_OPCODE_UIF: 593 case TGSI_OPCODE_ELSE: 594 case TGSI_OPCODE_BGNLOOP: 595 case TGSI_OPCODE_ENDLOOP: 596 case TGSI_OPCODE_CAL: 597 TXT( " :" ); 598 UID( inst->Label.Label ); 599 break; 600 } 601 602 /* update indentation */ 603 if (inst->Instruction.Opcode == TGSI_OPCODE_IF || 604 inst->Instruction.Opcode == TGSI_OPCODE_UIF || 605 inst->Instruction.Opcode == TGSI_OPCODE_ELSE || 606 inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) { 607 ctx->indentation += indent_spaces; 608 } 609 610 EOL(); 611 612 return TRUE; 613} 614 615void 616tgsi_dump_instruction( 617 const struct tgsi_full_instruction *inst, 618 uint instno ) 619{ 620 struct dump_ctx ctx; 621 622 ctx.instno = instno; 623 ctx.immno = instno; 624 ctx.indent = 0; 625 ctx.dump_printf = dump_ctx_printf; 626 ctx.indentation = 0; 627 628 iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst ); 629} 630 631static boolean 632prolog( 633 struct tgsi_iterate_context *iter ) 634{ 635 struct dump_ctx *ctx = (struct dump_ctx *) iter; 636 ENM( iter->processor.Processor, tgsi_processor_type_names ); 637 EOL(); 638 return TRUE; 639} 640 641void 642tgsi_dump( 643 const struct tgsi_token *tokens, 644 uint flags ) 645{ 646 struct dump_ctx ctx; 647 648 ctx.iter.prolog = prolog; 649 ctx.iter.iterate_instruction = iter_instruction; 650 ctx.iter.iterate_declaration = iter_declaration; 651 ctx.iter.iterate_immediate = iter_immediate; 652 ctx.iter.iterate_property = iter_property; 653 ctx.iter.epilog = NULL; 654 655 ctx.instno = 0; 656 ctx.immno = 0; 657 ctx.indent = 0; 658 ctx.dump_printf = dump_ctx_printf; 659 ctx.indentation = 0; 660 661 tgsi_iterate_shader( tokens, &ctx.iter ); 662} 663 664struct str_dump_ctx 665{ 666 struct dump_ctx base; 667 char *str; 668 char *ptr; 669 int left; 670}; 671 672static void 673str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...) 674{ 675 struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx; 676 677 if(sctx->left > 1) { 678 int written; 679 va_list ap; 680 va_start(ap, format); 681 written = util_vsnprintf(sctx->ptr, sctx->left, format, ap); 682 va_end(ap); 683 684 /* Some complicated logic needed to handle the return value of 685 * vsnprintf: 686 */ 687 if (written > 0) { 688 written = MIN2(sctx->left, written); 689 sctx->ptr += written; 690 sctx->left -= written; 691 } 692 } 693} 694 695void 696tgsi_dump_str( 697 const struct tgsi_token *tokens, 698 uint flags, 699 char *str, 700 size_t size) 701{ 702 struct str_dump_ctx ctx; 703 704 ctx.base.iter.prolog = prolog; 705 ctx.base.iter.iterate_instruction = iter_instruction; 706 ctx.base.iter.iterate_declaration = iter_declaration; 707 ctx.base.iter.iterate_immediate = iter_immediate; 708 ctx.base.iter.iterate_property = iter_property; 709 ctx.base.iter.epilog = NULL; 710 711 ctx.base.instno = 0; 712 ctx.base.immno = 0; 713 ctx.base.indent = 0; 714 ctx.base.dump_printf = &str_dump_ctx_printf; 715 ctx.base.indentation = 0; 716 717 ctx.str = str; 718 ctx.str[0] = 0; 719 ctx.ptr = str; 720 ctx.left = (int)size; 721 722 tgsi_iterate_shader( tokens, &ctx.base.iter ); 723} 724 725void 726tgsi_dump_instruction_str( 727 const struct tgsi_full_instruction *inst, 728 uint instno, 729 char *str, 730 size_t size) 731{ 732 struct str_dump_ctx ctx; 733 734 ctx.base.instno = instno; 735 ctx.base.immno = instno; 736 ctx.base.indent = 0; 737 ctx.base.dump_printf = &str_dump_ctx_printf; 738 ctx.base.indentation = 0; 739 740 ctx.str = str; 741 ctx.str[0] = 0; 742 ctx.ptr = str; 743 ctx.left = (int)size; 744 745 iter_instruction( &ctx.base.iter, (struct tgsi_full_instruction *)inst ); 746} 747