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@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 44struct dump_info 45{ 46 uint32 version; 47 boolean is_ps; 48 int indent; 49}; 50 51#define DUMP_MAX_OP_SRC 4 52 53struct 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 63static void 64dump_indent(int indent) 65{ 66 int i; 67 68 for (i = 0; i < indent; ++i) { 69 _debug_printf(" "); 70 } 71} 72 73static 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 132static void 133format_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 150static 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 266static 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 271static 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 276static void dump_bdata( boolean bdata ) 277{ 278 _debug_printf( bdata ? "TRUE" : "FALSE" ); 279} 280 281static void 282dump_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_2D_SHADOW: 291 _debug_printf( "_2dshadow" ); 292 break; 293 case SVGA3DSAMP_CUBE: 294 _debug_printf( "_cube" ); 295 break; 296 case SVGA3DSAMP_VOLUME: 297 _debug_printf( "_volume" ); 298 break; 299 default: 300 assert( 0 ); 301 } 302} 303 304static void 305dump_semantic(uint usage, 306 uint usage_index) 307{ 308 switch (usage) { 309 case SVGA3D_DECLUSAGE_POSITION: 310 _debug_printf("_position"); 311 break; 312 case SVGA3D_DECLUSAGE_BLENDWEIGHT: 313 _debug_printf("_blendweight"); 314 break; 315 case SVGA3D_DECLUSAGE_BLENDINDICES: 316 _debug_printf("_blendindices"); 317 break; 318 case SVGA3D_DECLUSAGE_NORMAL: 319 _debug_printf("_normal"); 320 break; 321 case SVGA3D_DECLUSAGE_PSIZE: 322 _debug_printf("_psize"); 323 break; 324 case SVGA3D_DECLUSAGE_TEXCOORD: 325 _debug_printf("_texcoord"); 326 break; 327 case SVGA3D_DECLUSAGE_TANGENT: 328 _debug_printf("_tangent"); 329 break; 330 case SVGA3D_DECLUSAGE_BINORMAL: 331 _debug_printf("_binormal"); 332 break; 333 case SVGA3D_DECLUSAGE_TESSFACTOR: 334 _debug_printf("_tessfactor"); 335 break; 336 case SVGA3D_DECLUSAGE_POSITIONT: 337 _debug_printf("_positiont"); 338 break; 339 case SVGA3D_DECLUSAGE_COLOR: 340 _debug_printf("_color"); 341 break; 342 case SVGA3D_DECLUSAGE_FOG: 343 _debug_printf("_fog"); 344 break; 345 case SVGA3D_DECLUSAGE_DEPTH: 346 _debug_printf("_depth"); 347 break; 348 case SVGA3D_DECLUSAGE_SAMPLE: 349 _debug_printf("_sample"); 350 break; 351 default: 352 assert(!"Unknown usage"); 353 _debug_printf("_???"); 354 } 355 356 if (usage_index) { 357 _debug_printf("%u", usage_index); 358 } 359} 360 361static void 362dump_dstreg(struct sh_dstreg dstreg, 363 struct sh_srcreg *indreg, 364 const struct dump_info *di) 365{ 366 union { 367 struct sh_reg reg; 368 struct sh_dstreg dstreg; 369 } u; 370 371 memset(&u, 0, sizeof(u)); 372 373 assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier ); 374 375 if (dstreg.modifier & SVGA3DDSTMOD_SATURATE) 376 _debug_printf( "_sat" ); 377 if (dstreg.modifier & SVGA3DDSTMOD_PARTIALPRECISION) 378 _debug_printf( "_pp" ); 379 switch (dstreg.shift_scale) { 380 case 0: 381 break; 382 case 1: 383 _debug_printf( "_x2" ); 384 break; 385 case 2: 386 _debug_printf( "_x4" ); 387 break; 388 case 3: 389 _debug_printf( "_x8" ); 390 break; 391 case 13: 392 _debug_printf( "_d8" ); 393 break; 394 case 14: 395 _debug_printf( "_d4" ); 396 break; 397 case 15: 398 _debug_printf( "_d2" ); 399 break; 400 default: 401 assert( 0 ); 402 } 403 _debug_printf( " " ); 404 405 u.dstreg = dstreg; 406 dump_reg( u.reg, indreg, di); 407 if (dstreg.write_mask != SVGA3DWRITEMASK_ALL) { 408 _debug_printf( "." ); 409 if (dstreg.write_mask & SVGA3DWRITEMASK_0) 410 _debug_printf( "x" ); 411 if (dstreg.write_mask & SVGA3DWRITEMASK_1) 412 _debug_printf( "y" ); 413 if (dstreg.write_mask & SVGA3DWRITEMASK_2) 414 _debug_printf( "z" ); 415 if (dstreg.write_mask & SVGA3DWRITEMASK_3) 416 _debug_printf( "w" ); 417 } 418} 419 420static void dump_srcreg( struct sh_srcreg srcreg, struct sh_srcreg *indreg, const struct dump_info *di ) 421{ 422 struct sh_reg srcreg_sh = {0}; 423 /* bit-fields carefully aligned, ensure they stay that way. */ 424 STATIC_ASSERT(sizeof(struct sh_reg) == sizeof(struct sh_srcreg)); 425 memcpy(&srcreg_sh, &srcreg, sizeof(srcreg_sh)); 426 427 switch (srcreg.modifier) { 428 case SVGA3DSRCMOD_NEG: 429 case SVGA3DSRCMOD_BIASNEG: 430 case SVGA3DSRCMOD_SIGNNEG: 431 case SVGA3DSRCMOD_X2NEG: 432 case SVGA3DSRCMOD_ABSNEG: 433 _debug_printf( "-" ); 434 break; 435 case SVGA3DSRCMOD_COMP: 436 _debug_printf( "1-" ); 437 break; 438 case SVGA3DSRCMOD_NOT: 439 _debug_printf( "!" ); 440 } 441 dump_reg(srcreg_sh, indreg, di ); 442 switch (srcreg.modifier) { 443 case SVGA3DSRCMOD_NONE: 444 case SVGA3DSRCMOD_NEG: 445 case SVGA3DSRCMOD_COMP: 446 case SVGA3DSRCMOD_NOT: 447 break; 448 case SVGA3DSRCMOD_BIAS: 449 case SVGA3DSRCMOD_BIASNEG: 450 _debug_printf( "_bias" ); 451 break; 452 case SVGA3DSRCMOD_SIGN: 453 case SVGA3DSRCMOD_SIGNNEG: 454 _debug_printf( "_bx2" ); 455 break; 456 case SVGA3DSRCMOD_X2: 457 case SVGA3DSRCMOD_X2NEG: 458 _debug_printf( "_x2" ); 459 break; 460 case SVGA3DSRCMOD_DZ: 461 _debug_printf( "_dz" ); 462 break; 463 case SVGA3DSRCMOD_DW: 464 _debug_printf( "_dw" ); 465 break; 466 case SVGA3DSRCMOD_ABS: 467 case SVGA3DSRCMOD_ABSNEG: 468 _debug_printf("_abs"); 469 break; 470 default: 471 assert( 0 ); 472 } 473 if (srcreg.swizzle_x != 0 || srcreg.swizzle_y != 1 || srcreg.swizzle_z != 2 || srcreg.swizzle_w != 3) { 474 _debug_printf( "." ); 475 if (srcreg.swizzle_x == srcreg.swizzle_y && srcreg.swizzle_y == srcreg.swizzle_z && srcreg.swizzle_z == srcreg.swizzle_w) { 476 _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] ); 477 } 478 else { 479 _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] ); 480 _debug_printf( "%c", "xyzw"[srcreg.swizzle_y] ); 481 _debug_printf( "%c", "xyzw"[srcreg.swizzle_z] ); 482 _debug_printf( "%c", "xyzw"[srcreg.swizzle_w] ); 483 } 484 } 485} 486 487static void 488parse_op(struct dump_info *di, 489 const uint **token, 490 struct dump_op *op, 491 uint num_dst, 492 uint num_src) 493{ 494 uint i; 495 496 assert(num_dst <= 1); 497 assert(num_src <= DUMP_MAX_OP_SRC); 498 499 op->op = *(struct sh_op *)*token; 500 *token += sizeof(struct sh_op) / sizeof(uint); 501 502 if (num_dst >= 1) { 503 op->dst = *(struct sh_dstreg *)*token; 504 *token += sizeof(struct sh_dstreg) / sizeof(uint); 505 if (op->dst.relative && 506 (!di->is_ps && di->version >= SVGA3D_VS_30)) { 507 op->dstind = *(struct sh_srcreg *)*token; 508 *token += sizeof(struct sh_srcreg) / sizeof(uint); 509 } 510 } 511 512 if (op->op.predicated) { 513 op->p0 = *(struct sh_srcreg *)*token; 514 *token += sizeof(struct sh_srcreg) / sizeof(uint); 515 } 516 517 for (i = 0; i < num_src; ++i) { 518 op->src[i] = *(struct sh_srcreg *)*token; 519 *token += sizeof(struct sh_srcreg) / sizeof(uint); 520 if (op->src[i].relative && 521 ((!di->is_ps && di->version >= SVGA3D_VS_20) || 522 (di->is_ps && di->version >= SVGA3D_PS_30))) { 523 op->srcind[i] = *(struct sh_srcreg *)*token; 524 *token += sizeof(struct sh_srcreg) / sizeof(uint); 525 } 526 } 527} 528 529static void 530dump_inst(struct dump_info *di, 531 const unsigned **assem, 532 struct sh_op op, 533 const struct sh_opcode_info *info) 534{ 535 struct dump_op dop; 536 boolean not_first_arg = FALSE; 537 uint i; 538 539 assert(info->num_dst <= 1); 540 541 di->indent -= info->pre_dedent; 542 dump_indent(di->indent); 543 di->indent += info->post_indent; 544 545 dump_op(op, info->mnemonic); 546 547 parse_op(di, assem, &dop, info->num_dst, info->num_src); 548 if (info->num_dst > 0) { 549 dump_dstreg(dop.dst, &dop.dstind, di); 550 not_first_arg = TRUE; 551 } 552 553 for (i = 0; i < info->num_src; i++) { 554 if (not_first_arg) { 555 _debug_printf(", "); 556 } else { 557 _debug_printf(" "); 558 } 559 dump_srcreg(dop.src[i], &dop.srcind[i], di); 560 not_first_arg = TRUE; 561 } 562 563 _debug_printf("\n"); 564} 565 566void 567svga_shader_dump( 568 const unsigned *assem, 569 unsigned dwords, 570 unsigned do_binary ) 571{ 572 boolean finished = FALSE; 573 struct dump_info di; 574 575 di.version = *assem++; 576 di.is_ps = (di.version & 0xFFFF0000) == 0xFFFF0000; 577 di.indent = 0; 578 579 _debug_printf( 580 "%s_%u_%u\n", 581 di.is_ps ? "ps" : "vs", 582 (di.version >> 8) & 0xff, 583 di.version & 0xff ); 584 585 while (!finished) { 586 struct sh_op op = *(struct sh_op *) assem; 587 588 switch (op.opcode) { 589 case SVGA3DOP_DCL: 590 { 591 struct sh_dcl dcl = *(struct sh_dcl *) assem; 592 593 _debug_printf( "dcl" ); 594 switch (sh_dstreg_type(dcl.reg)) { 595 case SVGA3DREG_INPUT: 596 if ((di.is_ps && di.version >= SVGA3D_PS_30) || 597 (!di.is_ps && di.version >= SVGA3D_VS_30)) { 598 dump_semantic(dcl.u.semantic.usage, 599 dcl.u.semantic.usage_index); 600 } 601 break; 602 case SVGA3DREG_TEXCRDOUT: 603 if (!di.is_ps && di.version >= SVGA3D_VS_30) { 604 dump_semantic(dcl.u.semantic.usage, 605 dcl.u.semantic.usage_index); 606 } 607 break; 608 case SVGA3DREG_SAMPLER: 609 dump_sampleinfo( dcl.u.sampleinfo ); 610 break; 611 } 612 dump_dstreg(dcl.reg, NULL, &di); 613 _debug_printf( "\n" ); 614 assem += sizeof( struct sh_dcl ) / sizeof( unsigned ); 615 } 616 break; 617 618 case SVGA3DOP_DEFB: 619 { 620 struct sh_defb defb = *(struct sh_defb *) assem; 621 622 _debug_printf( "defb " ); 623 dump_reg( defb.reg, NULL, &di ); 624 _debug_printf( ", " ); 625 dump_bdata( defb.data ); 626 _debug_printf( "\n" ); 627 assem += sizeof( struct sh_defb ) / sizeof( unsigned ); 628 } 629 break; 630 631 case SVGA3DOP_DEFI: 632 { 633 struct sh_defi defi = *(struct sh_defi *) assem; 634 635 _debug_printf( "defi " ); 636 dump_reg( defi.reg, NULL, &di ); 637 _debug_printf( ", " ); 638 dump_idata( defi.idata ); 639 _debug_printf( "\n" ); 640 assem += sizeof( struct sh_defi ) / sizeof( unsigned ); 641 } 642 break; 643 644 case SVGA3DOP_TEXCOORD: 645 { 646 struct sh_opcode_info info = *svga_opcode_info(op.opcode); 647 648 assert(di.is_ps); 649 if (di.version > SVGA3D_PS_13) { 650 assert(info.num_src == 0); 651 652 info.num_src = 1; 653 } 654 655 dump_inst(&di, &assem, op, &info); 656 } 657 break; 658 659 case SVGA3DOP_TEX: 660 { 661 struct sh_opcode_info info = *svga_opcode_info(op.opcode); 662 663 assert(di.is_ps); 664 if (di.version > SVGA3D_PS_13) { 665 assert(info.num_src == 0); 666 667 if (di.version > SVGA3D_PS_14) { 668 info.num_src = 2; 669 info.mnemonic = "texld"; 670 } else { 671 info.num_src = 1; 672 } 673 } 674 675 dump_inst(&di, &assem, op, &info); 676 } 677 break; 678 679 case SVGA3DOP_DEF: 680 { 681 struct sh_def def = *(struct sh_def *) assem; 682 683 _debug_printf( "def " ); 684 dump_reg( def.reg, NULL, &di ); 685 _debug_printf( ", " ); 686 dump_cdata( def.cdata ); 687 _debug_printf( "\n" ); 688 assem += sizeof( struct sh_def ) / sizeof( unsigned ); 689 } 690 break; 691 692 case SVGA3DOP_SINCOS: 693 { 694 struct sh_opcode_info info = *svga_opcode_info(op.opcode); 695 696 if ((di.is_ps && di.version >= SVGA3D_PS_30) || 697 (!di.is_ps && di.version >= SVGA3D_VS_30)) { 698 assert(info.num_src == 3); 699 700 info.num_src = 1; 701 } 702 703 dump_inst(&di, &assem, op, &info); 704 } 705 break; 706 707 case SVGA3DOP_PHASE: 708 _debug_printf( "phase\n" ); 709 assem += sizeof( struct sh_op ) / sizeof( unsigned ); 710 break; 711 712 case SVGA3DOP_COMMENT: 713 { 714 struct sh_comment comment = *(struct sh_comment *)assem; 715 716 /* Ignore comment contents. */ 717 assem += sizeof(struct sh_comment) / sizeof(unsigned) + comment.size; 718 } 719 break; 720 721 case SVGA3DOP_END: 722 finished = TRUE; 723 break; 724 725 default: 726 { 727 const struct sh_opcode_info *info = svga_opcode_info(op.opcode); 728 729 dump_inst(&di, &assem, op, info); 730 } 731 } 732 } 733} 734