1 /********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26 /** 27 * @file 28 * SVGA Shader Dump Facilities 29 * 30 * @author Michal Krol <michal (at) vmware.com> 31 */ 32 33 #include "svga_shader.h" 34 #include "svga_shader_dump.h" 35 #include "svga_shader_op.h" 36 #include "util/u_debug.h" 37 38 #include "../svga_hw_reg.h" 39 #include "svga3d_shaderdefs.h" 40 41 struct dump_info 42 { 43 uint32 version; 44 boolean is_ps; 45 int indent; 46 }; 47 48 #define DUMP_MAX_OP_SRC 4 49 50 struct dump_op 51 { 52 struct sh_op op; 53 struct sh_dstreg dst; 54 struct sh_srcreg dstind; 55 struct sh_srcreg src[DUMP_MAX_OP_SRC]; 56 struct sh_srcreg srcind[DUMP_MAX_OP_SRC]; 57 struct sh_srcreg p0; 58 }; 59 60 static void 61 dump_indent(int indent) 62 { 63 int i; 64 65 for (i = 0; i < indent; ++i) { 66 _debug_printf(" "); 67 } 68 } 69 70 static void dump_op( struct sh_op op, const char *mnemonic ) 71 { 72 assert( op.is_reg == 0 ); 73 74 if (op.predicated) { 75 _debug_printf("(p0) "); 76 } 77 if (op.coissue) 78 _debug_printf( "+" ); 79 _debug_printf( "%s", mnemonic ); 80 81 switch (op.opcode) { 82 case SVGA3DOP_TEX: 83 switch (op.control) { 84 case 0: 85 break; 86 case 1 /* PROJECT */: 87 _debug_printf("p"); 88 break; 89 case 2 /* BIAS */: 90 _debug_printf("b"); 91 break; 92 default: 93 assert(0); 94 } 95 break; 96 97 case SVGA3DOP_IFC: 98 case SVGA3DOP_BREAKC: 99 case SVGA3DOP_SETP: 100 switch (op.control) { 101 case SVGA3DOPCOMP_GT: 102 _debug_printf("_gt"); 103 break; 104 case SVGA3DOPCOMP_EQ: 105 _debug_printf("_eq"); 106 break; 107 case SVGA3DOPCOMP_GE: 108 _debug_printf("_ge"); 109 break; 110 case SVGA3DOPCOMP_LT: 111 _debug_printf("_lt"); 112 break; 113 case SVGA3DOPCOMPC_NE: 114 _debug_printf("_ne"); 115 break; 116 case SVGA3DOPCOMP_LE: 117 _debug_printf("_le"); 118 break; 119 default: 120 assert(0); 121 } 122 break; 123 124 default: 125 assert(op.control == 0); 126 } 127 } 128 129 static void 130 format_reg(const char *name, 131 const struct sh_reg reg, 132 const struct sh_srcreg *indreg) 133 { 134 if (reg.relative) { 135 assert(indreg); 136 137 if (sh_srcreg_type(*indreg) == SVGA3DREG_LOOP) { 138 _debug_printf("%s[aL+%u]", name, reg.number); 139 } else { 140 _debug_printf("%s[a%u.x+%u]", name, indreg->number, reg.number); 141 } 142 } else { 143 _debug_printf("%s%u", name, reg.number); 144 } 145 } 146 147 static void dump_reg( struct sh_reg reg, struct sh_srcreg *indreg, const struct dump_info *di ) 148 { 149 assert( reg.is_reg == 1 ); 150 151 switch (sh_reg_type( reg )) { 152 case SVGA3DREG_TEMP: 153 format_reg("r", reg, NULL); 154 break; 155 156 case SVGA3DREG_INPUT: 157 format_reg("v", reg, indreg); 158 break; 159 160 case SVGA3DREG_CONST: 161 format_reg("c", reg, indreg); 162 break; 163 164 case SVGA3DREG_ADDR: /* VS */ 165 /* SVGA3DREG_TEXTURE */ /* PS */ 166 assert(!reg.relative); 167 if (di->is_ps) { 168 format_reg("t", reg, NULL); 169 } else { 170 format_reg("a", reg, NULL); 171 } 172 break; 173 174 case SVGA3DREG_RASTOUT: 175 assert(!reg.relative); 176 switch (reg.number) { 177 case 0 /*POSITION*/: 178 _debug_printf( "oPos" ); 179 break; 180 case 1 /*FOG*/: 181 _debug_printf( "oFog" ); 182 break; 183 case 2 /*POINT_SIZE*/: 184 _debug_printf( "oPts" ); 185 break; 186 default: 187 assert( 0 ); 188 _debug_printf( "???" ); 189 } 190 break; 191 192 case SVGA3DREG_ATTROUT: 193 assert( reg.number < 2 ); 194 format_reg("oD", reg, NULL); 195 break; 196 197 case SVGA3DREG_TEXCRDOUT: /* VS */ 198 /* SVGA3DREG_OUTPUT */ /* VS3.0+ */ 199 if (!di->is_ps && di->version >= SVGA3D_VS_30) { 200 format_reg("o", reg, indreg); 201 } else { 202 format_reg("oT", reg, NULL); 203 } 204 break; 205 206 case SVGA3DREG_COLOROUT: 207 format_reg("oC", reg, NULL); 208 break; 209 210 case SVGA3DREG_DEPTHOUT: 211 assert(!reg.relative); 212 assert(reg.number == 0); 213 _debug_printf("oDepth"); 214 break; 215 216 case SVGA3DREG_SAMPLER: 217 format_reg("s", reg, NULL); 218 break; 219 220 case SVGA3DREG_CONSTBOOL: 221 format_reg("b", reg, NULL); 222 break; 223 224 case SVGA3DREG_CONSTINT: 225 format_reg("i", reg, NULL); 226 break; 227 228 case SVGA3DREG_LOOP: 229 assert(!reg.relative); 230 assert( reg.number == 0 ); 231 _debug_printf( "aL" ); 232 break; 233 234 case SVGA3DREG_MISCTYPE: 235 assert(!reg.relative); 236 switch (reg.number) { 237 case SVGA3DMISCREG_POSITION: 238 _debug_printf("vPos"); 239 break; 240 case SVGA3DMISCREG_FACE: 241 _debug_printf("vFace"); 242 break; 243 default: 244 assert(0); 245 _debug_printf("???"); 246 } 247 break; 248 249 case SVGA3DREG_LABEL: 250 format_reg("l", reg, NULL); 251 break; 252 253 case SVGA3DREG_PREDICATE: 254 format_reg("p", reg, NULL); 255 break; 256 257 default: 258 assert( 0 ); 259 _debug_printf( "???" ); 260 } 261 } 262 263 static void dump_cdata( struct sh_cdata cdata ) 264 { 265 _debug_printf( "%f, %f, %f, %f", cdata.xyzw[0], cdata.xyzw[1], cdata.xyzw[2], cdata.xyzw[3] ); 266 } 267 268 static void dump_idata( struct sh_idata idata ) 269 { 270 _debug_printf( "%d, %d, %d, %d", idata.xyzw[0], idata.xyzw[1], idata.xyzw[2], idata.xyzw[3] ); 271 } 272 273 static void dump_bdata( boolean bdata ) 274 { 275 _debug_printf( bdata ? "TRUE" : "FALSE" ); 276 } 277 278 static void 279 dump_sampleinfo(struct sh_sampleinfo sampleinfo) 280 { 281 assert( sampleinfo.is_reg == 1 ); 282 283 switch (sampleinfo.texture_type) { 284 case SVGA3DSAMP_2D: 285 _debug_printf( "_2d" ); 286 break; 287 case SVGA3DSAMP_CUBE: 288 _debug_printf( "_cube" ); 289 break; 290 case SVGA3DSAMP_VOLUME: 291 _debug_printf( "_volume" ); 292 break; 293 default: 294 assert( 0 ); 295 } 296 } 297 298 static void 299 dump_semantic(uint usage, 300 uint usage_index) 301 { 302 switch (usage) { 303 case SVGA3D_DECLUSAGE_POSITION: 304 _debug_printf("_position"); 305 break; 306 case SVGA3D_DECLUSAGE_BLENDWEIGHT: 307 _debug_printf("_blendweight"); 308 break; 309 case SVGA3D_DECLUSAGE_BLENDINDICES: 310 _debug_printf("_blendindices"); 311 break; 312 case SVGA3D_DECLUSAGE_NORMAL: 313 _debug_printf("_normal"); 314 break; 315 case SVGA3D_DECLUSAGE_PSIZE: 316 _debug_printf("_psize"); 317 break; 318 case SVGA3D_DECLUSAGE_TEXCOORD: 319 _debug_printf("_texcoord"); 320 break; 321 case SVGA3D_DECLUSAGE_TANGENT: 322 _debug_printf("_tangent"); 323 break; 324 case SVGA3D_DECLUSAGE_BINORMAL: 325 _debug_printf("_binormal"); 326 break; 327 case SVGA3D_DECLUSAGE_TESSFACTOR: 328 _debug_printf("_tessfactor"); 329 break; 330 case SVGA3D_DECLUSAGE_POSITIONT: 331 _debug_printf("_positiont"); 332 break; 333 case SVGA3D_DECLUSAGE_COLOR: 334 _debug_printf("_color"); 335 break; 336 case SVGA3D_DECLUSAGE_FOG: 337 _debug_printf("_fog"); 338 break; 339 case SVGA3D_DECLUSAGE_DEPTH: 340 _debug_printf("_depth"); 341 break; 342 case SVGA3D_DECLUSAGE_SAMPLE: 343 _debug_printf("_sample"); 344 break; 345 default: 346 assert(!"Unknown usage"); 347 _debug_printf("_???"); 348 } 349 350 if (usage_index) { 351 _debug_printf("%u", usage_index); 352 } 353 } 354 355 static void 356 dump_dstreg(struct sh_dstreg dstreg, 357 struct sh_srcreg *indreg, 358 const struct dump_info *di) 359 { 360 union { 361 struct sh_reg reg; 362 struct sh_dstreg dstreg; 363 } u; 364 365 memset(&u, 0, sizeof(u)); 366 367 assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier ); 368 369 if (dstreg.modifier & SVGA3DDSTMOD_SATURATE) 370 _debug_printf( "_sat" ); 371 if (dstreg.modifier & SVGA3DDSTMOD_PARTIALPRECISION) 372 _debug_printf( "_pp" ); 373 switch (dstreg.shift_scale) { 374 case 0: 375 break; 376 case 1: 377 _debug_printf( "_x2" ); 378 break; 379 case 2: 380 _debug_printf( "_x4" ); 381 break; 382 case 3: 383 _debug_printf( "_x8" ); 384 break; 385 case 13: 386 _debug_printf( "_d8" ); 387 break; 388 case 14: 389 _debug_printf( "_d4" ); 390 break; 391 case 15: 392 _debug_printf( "_d2" ); 393 break; 394 default: 395 assert( 0 ); 396 } 397 _debug_printf( " " ); 398 399 u.dstreg = dstreg; 400 dump_reg( u.reg, indreg, di); 401 if (dstreg.write_mask != SVGA3DWRITEMASK_ALL) { 402 _debug_printf( "." ); 403 if (dstreg.write_mask & SVGA3DWRITEMASK_0) 404 _debug_printf( "x" ); 405 if (dstreg.write_mask & SVGA3DWRITEMASK_1) 406 _debug_printf( "y" ); 407 if (dstreg.write_mask & SVGA3DWRITEMASK_2) 408 _debug_printf( "z" ); 409 if (dstreg.write_mask & SVGA3DWRITEMASK_3) 410 _debug_printf( "w" ); 411 } 412 } 413 414 static void dump_srcreg( struct sh_srcreg srcreg, struct sh_srcreg *indreg, const struct dump_info *di ) 415 { 416 switch (srcreg.modifier) { 417 case SVGA3DSRCMOD_NEG: 418 case SVGA3DSRCMOD_BIASNEG: 419 case SVGA3DSRCMOD_SIGNNEG: 420 case SVGA3DSRCMOD_X2NEG: 421 case SVGA3DSRCMOD_ABSNEG: 422 _debug_printf( "-" ); 423 break; 424 case SVGA3DSRCMOD_COMP: 425 _debug_printf( "1-" ); 426 break; 427 case SVGA3DSRCMOD_NOT: 428 _debug_printf( "!" ); 429 } 430 dump_reg( *(struct sh_reg *) &srcreg, indreg, di ); 431 switch (srcreg.modifier) { 432 case SVGA3DSRCMOD_NONE: 433 case SVGA3DSRCMOD_NEG: 434 case SVGA3DSRCMOD_COMP: 435 case SVGA3DSRCMOD_NOT: 436 break; 437 case SVGA3DSRCMOD_BIAS: 438 case SVGA3DSRCMOD_BIASNEG: 439 _debug_printf( "_bias" ); 440 break; 441 case SVGA3DSRCMOD_SIGN: 442 case SVGA3DSRCMOD_SIGNNEG: 443 _debug_printf( "_bx2" ); 444 break; 445 case SVGA3DSRCMOD_X2: 446 case SVGA3DSRCMOD_X2NEG: 447 _debug_printf( "_x2" ); 448 break; 449 case SVGA3DSRCMOD_DZ: 450 _debug_printf( "_dz" ); 451 break; 452 case SVGA3DSRCMOD_DW: 453 _debug_printf( "_dw" ); 454 break; 455 case SVGA3DSRCMOD_ABS: 456 case SVGA3DSRCMOD_ABSNEG: 457 _debug_printf("_abs"); 458 break; 459 default: 460 assert( 0 ); 461 } 462 if (srcreg.swizzle_x != 0 || srcreg.swizzle_y != 1 || srcreg.swizzle_z != 2 || srcreg.swizzle_w != 3) { 463 _debug_printf( "." ); 464 if (srcreg.swizzle_x == srcreg.swizzle_y && srcreg.swizzle_y == srcreg.swizzle_z && srcreg.swizzle_z == srcreg.swizzle_w) { 465 _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] ); 466 } 467 else { 468 _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] ); 469 _debug_printf( "%c", "xyzw"[srcreg.swizzle_y] ); 470 _debug_printf( "%c", "xyzw"[srcreg.swizzle_z] ); 471 _debug_printf( "%c", "xyzw"[srcreg.swizzle_w] ); 472 } 473 } 474 } 475 476 static void 477 parse_op(struct dump_info *di, 478 const uint **token, 479 struct dump_op *op, 480 uint num_dst, 481 uint num_src) 482 { 483 uint i; 484 485 assert(num_dst <= 1); 486 assert(num_src <= DUMP_MAX_OP_SRC); 487 488 op->op = *(struct sh_op *)*token; 489 *token += sizeof(struct sh_op) / sizeof(uint); 490 491 if (num_dst >= 1) { 492 op->dst = *(struct sh_dstreg *)*token; 493 *token += sizeof(struct sh_dstreg) / sizeof(uint); 494 if (op->dst.relative && 495 (!di->is_ps && di->version >= SVGA3D_VS_30)) { 496 op->dstind = *(struct sh_srcreg *)*token; 497 *token += sizeof(struct sh_srcreg) / sizeof(uint); 498 } 499 } 500 501 if (op->op.predicated) { 502 op->p0 = *(struct sh_srcreg *)*token; 503 *token += sizeof(struct sh_srcreg) / sizeof(uint); 504 } 505 506 for (i = 0; i < num_src; ++i) { 507 op->src[i] = *(struct sh_srcreg *)*token; 508 *token += sizeof(struct sh_srcreg) / sizeof(uint); 509 if (op->src[i].relative && 510 ((!di->is_ps && di->version >= SVGA3D_VS_20) || 511 (di->is_ps && di->version >= SVGA3D_PS_30))) { 512 op->srcind[i] = *(struct sh_srcreg *)*token; 513 *token += sizeof(struct sh_srcreg) / sizeof(uint); 514 } 515 } 516 } 517 518 static void 519 dump_inst(struct dump_info *di, 520 const unsigned **assem, 521 struct sh_op op, 522 const struct sh_opcode_info *info) 523 { 524 struct dump_op dop; 525 boolean not_first_arg = FALSE; 526 uint i; 527 528 assert(info->num_dst <= 1); 529 530 di->indent -= info->pre_dedent; 531 dump_indent(di->indent); 532 di->indent += info->post_indent; 533 534 dump_op(op, info->mnemonic); 535 536 parse_op(di, assem, &dop, info->num_dst, info->num_src); 537 if (info->num_dst > 0) { 538 dump_dstreg(dop.dst, &dop.dstind, di); 539 not_first_arg = TRUE; 540 } 541 542 for (i = 0; i < info->num_src; i++) { 543 if (not_first_arg) { 544 _debug_printf(", "); 545 } else { 546 _debug_printf(" "); 547 } 548 dump_srcreg(dop.src[i], &dop.srcind[i], di); 549 not_first_arg = TRUE; 550 } 551 552 _debug_printf("\n"); 553 } 554 555 void 556 svga_shader_dump( 557 const unsigned *assem, 558 unsigned dwords, 559 unsigned do_binary ) 560 { 561 boolean finished = FALSE; 562 struct dump_info di; 563 564 di.version = *assem++; 565 di.is_ps = (di.version & 0xFFFF0000) == 0xFFFF0000; 566 di.indent = 0; 567 568 _debug_printf( 569 "%s_%u_%u\n", 570 di.is_ps ? "ps" : "vs", 571 (di.version >> 8) & 0xff, 572 di.version & 0xff ); 573 574 while (!finished) { 575 struct sh_op op = *(struct sh_op *) assem; 576 577 switch (op.opcode) { 578 case SVGA3DOP_DCL: 579 { 580 struct sh_dcl dcl = *(struct sh_dcl *) assem; 581 582 _debug_printf( "dcl" ); 583 switch (sh_dstreg_type(dcl.reg)) { 584 case SVGA3DREG_INPUT: 585 if ((di.is_ps && di.version >= SVGA3D_PS_30) || 586 (!di.is_ps && di.version >= SVGA3D_VS_30)) { 587 dump_semantic(dcl.u.semantic.usage, 588 dcl.u.semantic.usage_index); 589 } 590 break; 591 case SVGA3DREG_TEXCRDOUT: 592 if (!di.is_ps && di.version >= SVGA3D_VS_30) { 593 dump_semantic(dcl.u.semantic.usage, 594 dcl.u.semantic.usage_index); 595 } 596 break; 597 case SVGA3DREG_SAMPLER: 598 dump_sampleinfo( dcl.u.sampleinfo ); 599 break; 600 } 601 dump_dstreg(dcl.reg, NULL, &di); 602 _debug_printf( "\n" ); 603 assem += sizeof( struct sh_dcl ) / sizeof( unsigned ); 604 } 605 break; 606 607 case SVGA3DOP_DEFB: 608 { 609 struct sh_defb defb = *(struct sh_defb *) assem; 610 611 _debug_printf( "defb " ); 612 dump_reg( defb.reg, NULL, &di ); 613 _debug_printf( ", " ); 614 dump_bdata( defb.data ); 615 _debug_printf( "\n" ); 616 assem += sizeof( struct sh_defb ) / sizeof( unsigned ); 617 } 618 break; 619 620 case SVGA3DOP_DEFI: 621 { 622 struct sh_defi defi = *(struct sh_defi *) assem; 623 624 _debug_printf( "defi " ); 625 dump_reg( defi.reg, NULL, &di ); 626 _debug_printf( ", " ); 627 dump_idata( defi.idata ); 628 _debug_printf( "\n" ); 629 assem += sizeof( struct sh_defi ) / sizeof( unsigned ); 630 } 631 break; 632 633 case SVGA3DOP_TEXCOORD: 634 { 635 struct sh_opcode_info info = *svga_opcode_info(op.opcode); 636 637 assert(di.is_ps); 638 if (di.version > SVGA3D_PS_13) { 639 assert(info.num_src == 0); 640 641 info.num_src = 1; 642 } 643 644 dump_inst(&di, &assem, op, &info); 645 } 646 break; 647 648 case SVGA3DOP_TEX: 649 { 650 struct sh_opcode_info info = *svga_opcode_info(op.opcode); 651 652 assert(di.is_ps); 653 if (di.version > SVGA3D_PS_13) { 654 assert(info.num_src == 0); 655 656 if (di.version > SVGA3D_PS_14) { 657 info.num_src = 2; 658 info.mnemonic = "texld"; 659 } else { 660 info.num_src = 1; 661 } 662 } 663 664 dump_inst(&di, &assem, op, &info); 665 } 666 break; 667 668 case SVGA3DOP_DEF: 669 { 670 struct sh_def def = *(struct sh_def *) assem; 671 672 _debug_printf( "def " ); 673 dump_reg( def.reg, NULL, &di ); 674 _debug_printf( ", " ); 675 dump_cdata( def.cdata ); 676 _debug_printf( "\n" ); 677 assem += sizeof( struct sh_def ) / sizeof( unsigned ); 678 } 679 break; 680 681 case SVGA3DOP_SINCOS: 682 { 683 struct sh_opcode_info info = *svga_opcode_info(op.opcode); 684 685 if ((di.is_ps && di.version >= SVGA3D_PS_30) || 686 (!di.is_ps && di.version >= SVGA3D_VS_30)) { 687 assert(info.num_src == 3); 688 689 info.num_src = 1; 690 } 691 692 dump_inst(&di, &assem, op, &info); 693 } 694 break; 695 696 case SVGA3DOP_PHASE: 697 _debug_printf( "phase\n" ); 698 assem += sizeof( struct sh_op ) / sizeof( unsigned ); 699 break; 700 701 case SVGA3DOP_COMMENT: 702 { 703 struct sh_comment comment = *(struct sh_comment *)assem; 704 705 /* Ignore comment contents. */ 706 assem += sizeof(struct sh_comment) / sizeof(unsigned) + comment.size; 707 } 708 break; 709 710 case SVGA3DOP_END: 711 finished = TRUE; 712 break; 713 714 default: 715 { 716 const struct sh_opcode_info *info = svga_opcode_info(op.opcode); 717 718 dump_inst(&di, &assem, op, info); 719 } 720 } 721 } 722 } 723