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