1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.3 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions 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 MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 /** 27 * \file prog_print.c 28 * Print vertex/fragment programs - for debugging. 29 * \author Brian Paul 30 */ 31 32 #include <inttypes.h> /* for PRIx64 macro */ 33 34 #include "main/glheader.h" 35 #include "main/context.h" 36 #include "main/imports.h" 37 #include "prog_instruction.h" 38 #include "prog_parameter.h" 39 #include "prog_print.h" 40 #include "prog_statevars.h" 41 42 43 44 /** 45 * Return string name for given program/register file. 46 */ 47 const char * 48 _mesa_register_file_name(gl_register_file f) 49 { 50 switch (f) { 51 case PROGRAM_TEMPORARY: 52 return "TEMP"; 53 case PROGRAM_LOCAL_PARAM: 54 return "LOCAL"; 55 case PROGRAM_ENV_PARAM: 56 return "ENV"; 57 case PROGRAM_STATE_VAR: 58 return "STATE"; 59 case PROGRAM_INPUT: 60 return "INPUT"; 61 case PROGRAM_OUTPUT: 62 return "OUTPUT"; 63 case PROGRAM_NAMED_PARAM: 64 return "NAMED"; 65 case PROGRAM_CONSTANT: 66 return "CONST"; 67 case PROGRAM_UNIFORM: 68 return "UNIFORM"; 69 case PROGRAM_VARYING: 70 return "VARYING"; 71 case PROGRAM_WRITE_ONLY: 72 return "WRITE_ONLY"; 73 case PROGRAM_ADDRESS: 74 return "ADDR"; 75 case PROGRAM_SAMPLER: 76 return "SAMPLER"; 77 case PROGRAM_SYSTEM_VALUE: 78 return "SYSVAL"; 79 case PROGRAM_UNDEFINED: 80 return "UNDEFINED"; 81 default: 82 { 83 static char s[20]; 84 _mesa_snprintf(s, sizeof(s), "FILE%u", f); 85 return s; 86 } 87 } 88 } 89 90 91 /** 92 * Return ARB_v/f_prog-style input attrib string. 93 */ 94 static const char * 95 arb_input_attrib_string(GLint index, GLenum progType) 96 { 97 /* 98 * These strings should match the VERT_ATTRIB_x and FRAG_ATTRIB_x tokens. 99 */ 100 static const char *const vertAttribs[] = { 101 "vertex.position", 102 "vertex.weight", 103 "vertex.normal", 104 "vertex.color.primary", 105 "vertex.color.secondary", 106 "vertex.fogcoord", 107 "vertex.(six)", /* VERT_ATTRIB_COLOR_INDEX */ 108 "vertex.(seven)", /* VERT_ATTRIB_EDGEFLAG */ 109 "vertex.texcoord[0]", 110 "vertex.texcoord[1]", 111 "vertex.texcoord[2]", 112 "vertex.texcoord[3]", 113 "vertex.texcoord[4]", 114 "vertex.texcoord[5]", 115 "vertex.texcoord[6]", 116 "vertex.texcoord[7]", 117 "vertex.(sixteen)", /* VERT_ATTRIB_POINT_SIZE */ 118 "vertex.attrib[0]", 119 "vertex.attrib[1]", 120 "vertex.attrib[2]", 121 "vertex.attrib[3]", 122 "vertex.attrib[4]", 123 "vertex.attrib[5]", 124 "vertex.attrib[6]", 125 "vertex.attrib[7]", 126 "vertex.attrib[8]", 127 "vertex.attrib[9]", 128 "vertex.attrib[10]", 129 "vertex.attrib[11]", 130 "vertex.attrib[12]", 131 "vertex.attrib[13]", 132 "vertex.attrib[14]", 133 "vertex.attrib[15]" /* MAX_VARYING = 16 */ 134 }; 135 static const char *const fragAttribs[] = { 136 "fragment.position", 137 "fragment.color.primary", 138 "fragment.color.secondary", 139 "fragment.fogcoord", 140 "fragment.texcoord[0]", 141 "fragment.texcoord[1]", 142 "fragment.texcoord[2]", 143 "fragment.texcoord[3]", 144 "fragment.texcoord[4]", 145 "fragment.texcoord[5]", 146 "fragment.texcoord[6]", 147 "fragment.texcoord[7]", 148 "fragment.(twelve)", /* FRAG_ATTRIB_FACE */ 149 "fragment.(thirteen)", /* FRAG_ATTRIB_PNTC */ 150 "fragment.(fourteen)", /* FRAG_ATTRIB_CLIP_DIST0 */ 151 "fragment.(fifteen)", /* FRAG_ATTRIB_CLIP_DIST1 */ 152 "fragment.varying[0]", 153 "fragment.varying[1]", 154 "fragment.varying[2]", 155 "fragment.varying[3]", 156 "fragment.varying[4]", 157 "fragment.varying[5]", 158 "fragment.varying[6]", 159 "fragment.varying[7]", 160 "fragment.varying[8]", 161 "fragment.varying[9]", 162 "fragment.varying[10]", 163 "fragment.varying[11]", 164 "fragment.varying[12]", 165 "fragment.varying[13]", 166 "fragment.varying[14]", 167 "fragment.varying[15]", 168 "fragment.varying[16]", 169 "fragment.varying[17]", 170 "fragment.varying[18]", 171 "fragment.varying[19]", 172 "fragment.varying[20]", 173 "fragment.varying[21]", 174 "fragment.varying[22]", 175 "fragment.varying[23]", 176 "fragment.varying[24]", 177 "fragment.varying[25]", 178 "fragment.varying[26]", 179 "fragment.varying[27]", 180 "fragment.varying[28]", 181 "fragment.varying[29]", 182 "fragment.varying[30]", 183 "fragment.varying[31]", /* MAX_VARYING = 32 */ 184 }; 185 186 /* sanity checks */ 187 STATIC_ASSERT(Elements(vertAttribs) == VERT_ATTRIB_MAX); 188 STATIC_ASSERT(Elements(fragAttribs) == FRAG_ATTRIB_MAX); 189 assert(strcmp(vertAttribs[VERT_ATTRIB_TEX0], "vertex.texcoord[0]") == 0); 190 assert(strcmp(vertAttribs[VERT_ATTRIB_GENERIC15], "vertex.attrib[15]") == 0); 191 assert(strcmp(fragAttribs[FRAG_ATTRIB_TEX0], "fragment.texcoord[0]") == 0); 192 assert(strcmp(fragAttribs[FRAG_ATTRIB_VAR0+15], "fragment.varying[15]") == 0); 193 194 if (progType == GL_VERTEX_PROGRAM_ARB) { 195 assert(index < Elements(vertAttribs)); 196 return vertAttribs[index]; 197 } 198 else { 199 assert(progType == GL_FRAGMENT_PROGRAM_ARB); 200 assert(index < Elements(fragAttribs)); 201 return fragAttribs[index]; 202 } 203 } 204 205 206 /** 207 * Print a vertex program's InputsRead field in human-readable format. 208 * For debugging. 209 */ 210 void 211 _mesa_print_vp_inputs(GLbitfield inputs) 212 { 213 printf("VP Inputs 0x%x: \n", inputs); 214 while (inputs) { 215 GLint attr = ffs(inputs) - 1; 216 const char *name = arb_input_attrib_string(attr, 217 GL_VERTEX_PROGRAM_ARB); 218 printf(" %d: %s\n", attr, name); 219 inputs &= ~(1 << attr); 220 } 221 } 222 223 224 /** 225 * Print a fragment program's InputsRead field in human-readable format. 226 * For debugging. 227 */ 228 void 229 _mesa_print_fp_inputs(GLbitfield inputs) 230 { 231 printf("FP Inputs 0x%x: \n", inputs); 232 while (inputs) { 233 GLint attr = ffs(inputs) - 1; 234 const char *name = arb_input_attrib_string(attr, 235 GL_FRAGMENT_PROGRAM_ARB); 236 printf(" %d: %s\n", attr, name); 237 inputs &= ~(1 << attr); 238 } 239 } 240 241 242 243 /** 244 * Return ARB_v/f_prog-style output attrib string. 245 */ 246 static const char * 247 arb_output_attrib_string(GLint index, GLenum progType) 248 { 249 /* 250 * These strings should match the VERT_RESULT_x and FRAG_RESULT_x tokens. 251 */ 252 static const char *const vertResults[] = { 253 "result.position", 254 "result.color.primary", 255 "result.color.secondary", 256 "result.fogcoord", 257 "result.texcoord[0]", 258 "result.texcoord[1]", 259 "result.texcoord[2]", 260 "result.texcoord[3]", 261 "result.texcoord[4]", 262 "result.texcoord[5]", 263 "result.texcoord[6]", 264 "result.texcoord[7]", 265 "result.pointsize", /* VERT_RESULT_PSIZ */ 266 "result.(thirteen)", /* VERT_RESULT_BFC0 */ 267 "result.(fourteen)", /* VERT_RESULT_BFC1 */ 268 "result.(fifteen)", /* VERT_RESULT_EDGE */ 269 "result.(sixteen)", /* VERT_RESULT_CLIP_VERTEX */ 270 "result.(seventeen)", /* VERT_RESULT_CLIP_DIST0 */ 271 "result.(eighteen)", /* VERT_RESULT_CLIP_DIST1 */ 272 "result.varying[0]", 273 "result.varying[1]", 274 "result.varying[2]", 275 "result.varying[3]", 276 "result.varying[4]", 277 "result.varying[5]", 278 "result.varying[6]", 279 "result.varying[7]", 280 "result.varying[8]", 281 "result.varying[9]", 282 "result.varying[10]", 283 "result.varying[11]", 284 "result.varying[12]", 285 "result.varying[13]", 286 "result.varying[14]", 287 "result.varying[15]", 288 "result.varying[16]", 289 "result.varying[17]", 290 "result.varying[18]", 291 "result.varying[19]", 292 "result.varying[20]", 293 "result.varying[21]", 294 "result.varying[22]", 295 "result.varying[23]", 296 "result.varying[24]", 297 "result.varying[25]", 298 "result.varying[26]", 299 "result.varying[27]", 300 "result.varying[28]", 301 "result.varying[29]", 302 "result.varying[30]", 303 "result.varying[31]", /* MAX_VARYING = 32 */ 304 }; 305 static const char *const fragResults[] = { 306 "result.depth", /* FRAG_RESULT_DEPTH */ 307 "result.(one)", /* FRAG_RESULT_STENCIL */ 308 "result.color", /* FRAG_RESULT_COLOR */ 309 "result.color[0]", /* FRAG_RESULT_DATA0 (named for GLSL's gl_FragData) */ 310 "result.color[1]", 311 "result.color[2]", 312 "result.color[3]", 313 "result.color[4]", 314 "result.color[5]", 315 "result.color[6]", 316 "result.color[7]" /* MAX_DRAW_BUFFERS = 8 */ 317 }; 318 319 /* sanity checks */ 320 STATIC_ASSERT(Elements(vertResults) == VERT_RESULT_MAX); 321 STATIC_ASSERT(Elements(fragResults) == FRAG_RESULT_MAX); 322 assert(strcmp(vertResults[VERT_RESULT_HPOS], "result.position") == 0); 323 assert(strcmp(vertResults[VERT_RESULT_VAR0], "result.varying[0]") == 0); 324 assert(strcmp(fragResults[FRAG_RESULT_DATA0], "result.color[0]") == 0); 325 326 if (progType == GL_VERTEX_PROGRAM_ARB) { 327 assert(index < Elements(vertResults)); 328 return vertResults[index]; 329 } 330 else { 331 assert(progType == GL_FRAGMENT_PROGRAM_ARB); 332 assert(index < Elements(fragResults)); 333 return fragResults[index]; 334 } 335 } 336 337 338 /** 339 * Return string representation of the given register. 340 * Note that some types of registers (like PROGRAM_UNIFORM) aren't defined 341 * by the ARB/NV program languages so we've taken some liberties here. 342 * \param f the register file (PROGRAM_INPUT, PROGRAM_TEMPORARY, etc) 343 * \param index number of the register in the register file 344 * \param mode the output format/mode/style 345 * \param prog pointer to containing program 346 */ 347 static const char * 348 reg_string(gl_register_file f, GLint index, gl_prog_print_mode mode, 349 GLboolean relAddr, const struct gl_program *prog, 350 GLboolean hasIndex2, GLboolean relAddr2, GLint index2) 351 { 352 static char str[100]; 353 const char *addr = relAddr ? "ADDR+" : ""; 354 355 str[0] = 0; 356 357 switch (mode) { 358 case PROG_PRINT_DEBUG: 359 sprintf(str, "%s[%s%d]", 360 _mesa_register_file_name(f), addr, index); 361 if (hasIndex2) { 362 int offset = strlen(str); 363 const char *addr2 = relAddr2 ? "ADDR+" : ""; 364 sprintf(str+offset, "[%s%d]", addr2, index2); 365 } 366 break; 367 368 case PROG_PRINT_ARB: 369 switch (f) { 370 case PROGRAM_INPUT: 371 sprintf(str, "%s", arb_input_attrib_string(index, prog->Target)); 372 break; 373 case PROGRAM_OUTPUT: 374 sprintf(str, "%s", arb_output_attrib_string(index, prog->Target)); 375 break; 376 case PROGRAM_TEMPORARY: 377 sprintf(str, "temp%d", index); 378 break; 379 case PROGRAM_ENV_PARAM: 380 sprintf(str, "program.env[%s%d]", addr, index); 381 break; 382 case PROGRAM_LOCAL_PARAM: 383 sprintf(str, "program.local[%s%d]", addr, index); 384 break; 385 case PROGRAM_VARYING: /* extension */ 386 sprintf(str, "varying[%s%d]", addr, index); 387 break; 388 case PROGRAM_CONSTANT: /* extension */ 389 sprintf(str, "constant[%s%d]", addr, index); 390 break; 391 case PROGRAM_UNIFORM: /* extension */ 392 sprintf(str, "uniform[%s%d]", addr, index); 393 break; 394 case PROGRAM_SYSTEM_VALUE: 395 sprintf(str, "sysvalue[%s%d]", addr, index); 396 break; 397 case PROGRAM_STATE_VAR: 398 { 399 struct gl_program_parameter *param 400 = prog->Parameters->Parameters + index; 401 char *state = _mesa_program_state_string(param->StateIndexes); 402 sprintf(str, "%s", state); 403 free(state); 404 } 405 break; 406 case PROGRAM_ADDRESS: 407 sprintf(str, "A%d", index); 408 break; 409 default: 410 _mesa_problem(NULL, "bad file in reg_string()"); 411 } 412 break; 413 414 case PROG_PRINT_NV: 415 switch (f) { 416 case PROGRAM_INPUT: 417 if (prog->Target == GL_VERTEX_PROGRAM_ARB) 418 sprintf(str, "v[%d]", index); 419 else 420 sprintf(str, "f[%d]", index); 421 break; 422 case PROGRAM_OUTPUT: 423 sprintf(str, "o[%d]", index); 424 break; 425 case PROGRAM_TEMPORARY: 426 sprintf(str, "R%d", index); 427 break; 428 case PROGRAM_ENV_PARAM: 429 sprintf(str, "c[%d]", index); 430 break; 431 case PROGRAM_VARYING: /* extension */ 432 sprintf(str, "varying[%s%d]", addr, index); 433 break; 434 case PROGRAM_UNIFORM: /* extension */ 435 sprintf(str, "uniform[%s%d]", addr, index); 436 break; 437 case PROGRAM_CONSTANT: /* extension */ 438 sprintf(str, "constant[%s%d]", addr, index); 439 break; 440 case PROGRAM_STATE_VAR: /* extension */ 441 sprintf(str, "state[%s%d]", addr, index); 442 break; 443 default: 444 _mesa_problem(NULL, "bad file in reg_string()"); 445 } 446 break; 447 448 default: 449 _mesa_problem(NULL, "bad mode in reg_string()"); 450 } 451 452 return str; 453 } 454 455 456 /** 457 * Return a string representation of the given swizzle word. 458 * If extended is true, use extended (comma-separated) format. 459 * \param swizzle the swizzle field 460 * \param negateBase 4-bit negation vector 461 * \param extended if true, also allow 0, 1 values 462 */ 463 const char * 464 _mesa_swizzle_string(GLuint swizzle, GLuint negateMask, GLboolean extended) 465 { 466 static const char swz[] = "xyzw01!?"; /* See SWIZZLE_x definitions */ 467 static char s[20]; 468 GLuint i = 0; 469 470 if (!extended && swizzle == SWIZZLE_NOOP && negateMask == 0) 471 return ""; /* no swizzle/negation */ 472 473 if (!extended) 474 s[i++] = '.'; 475 476 if (negateMask & NEGATE_X) 477 s[i++] = '-'; 478 s[i++] = swz[GET_SWZ(swizzle, 0)]; 479 480 if (extended) { 481 s[i++] = ','; 482 } 483 484 if (negateMask & NEGATE_Y) 485 s[i++] = '-'; 486 s[i++] = swz[GET_SWZ(swizzle, 1)]; 487 488 if (extended) { 489 s[i++] = ','; 490 } 491 492 if (negateMask & NEGATE_Z) 493 s[i++] = '-'; 494 s[i++] = swz[GET_SWZ(swizzle, 2)]; 495 496 if (extended) { 497 s[i++] = ','; 498 } 499 500 if (negateMask & NEGATE_W) 501 s[i++] = '-'; 502 s[i++] = swz[GET_SWZ(swizzle, 3)]; 503 504 s[i] = 0; 505 return s; 506 } 507 508 509 void 510 _mesa_print_swizzle(GLuint swizzle) 511 { 512 if (swizzle == SWIZZLE_XYZW) { 513 printf(".xyzw\n"); 514 } 515 else { 516 const char *s = _mesa_swizzle_string(swizzle, 0, 0); 517 printf("%s\n", s); 518 } 519 } 520 521 522 const char * 523 _mesa_writemask_string(GLuint writeMask) 524 { 525 static char s[10]; 526 GLuint i = 0; 527 528 if (writeMask == WRITEMASK_XYZW) 529 return ""; 530 531 s[i++] = '.'; 532 if (writeMask & WRITEMASK_X) 533 s[i++] = 'x'; 534 if (writeMask & WRITEMASK_Y) 535 s[i++] = 'y'; 536 if (writeMask & WRITEMASK_Z) 537 s[i++] = 'z'; 538 if (writeMask & WRITEMASK_W) 539 s[i++] = 'w'; 540 541 s[i] = 0; 542 return s; 543 } 544 545 546 const char * 547 _mesa_condcode_string(GLuint condcode) 548 { 549 switch (condcode) { 550 case COND_GT: return "GT"; 551 case COND_EQ: return "EQ"; 552 case COND_LT: return "LT"; 553 case COND_UN: return "UN"; 554 case COND_GE: return "GE"; 555 case COND_LE: return "LE"; 556 case COND_NE: return "NE"; 557 case COND_TR: return "TR"; 558 case COND_FL: return "FL"; 559 default: return "cond???"; 560 } 561 } 562 563 564 static void 565 fprint_dst_reg(FILE * f, 566 const struct prog_dst_register *dstReg, 567 gl_prog_print_mode mode, 568 const struct gl_program *prog) 569 { 570 fprintf(f, "%s%s", 571 reg_string((gl_register_file) dstReg->File, 572 dstReg->Index, mode, dstReg->RelAddr, prog, 573 GL_FALSE, GL_FALSE, 0), 574 _mesa_writemask_string(dstReg->WriteMask)); 575 576 if (dstReg->CondMask != COND_TR) { 577 fprintf(f, " (%s.%s)", 578 _mesa_condcode_string(dstReg->CondMask), 579 _mesa_swizzle_string(dstReg->CondSwizzle, 580 GL_FALSE, GL_FALSE)); 581 } 582 583 #if 0 584 fprintf(f, "%s[%d]%s", 585 _mesa_register_file_name((gl_register_file) dstReg->File), 586 dstReg->Index, 587 _mesa_writemask_string(dstReg->WriteMask)); 588 #endif 589 } 590 591 592 static void 593 fprint_src_reg(FILE *f, 594 const struct prog_src_register *srcReg, 595 gl_prog_print_mode mode, 596 const struct gl_program *prog) 597 { 598 const char *abs = srcReg->Abs ? "|" : ""; 599 600 fprintf(f, "%s%s%s%s", 601 abs, 602 reg_string((gl_register_file) srcReg->File, 603 srcReg->Index, mode, srcReg->RelAddr, prog, 604 srcReg->HasIndex2, srcReg->RelAddr2, srcReg->Index2), 605 _mesa_swizzle_string(srcReg->Swizzle, 606 srcReg->Negate, GL_FALSE), 607 abs); 608 #if 0 609 fprintf(f, "%s[%d]%s", 610 _mesa_register_file_name((gl_register_file) srcReg->File), 611 srcReg->Index, 612 _mesa_swizzle_string(srcReg->Swizzle, 613 srcReg->Negate, GL_FALSE)); 614 #endif 615 } 616 617 618 static void 619 fprint_comment(FILE *f, const struct prog_instruction *inst) 620 { 621 if (inst->Comment) 622 fprintf(f, "; # %s\n", inst->Comment); 623 else 624 fprintf(f, ";\n"); 625 } 626 627 628 void 629 _mesa_fprint_alu_instruction(FILE *f, 630 const struct prog_instruction *inst, 631 const char *opcode_string, GLuint numRegs, 632 gl_prog_print_mode mode, 633 const struct gl_program *prog) 634 { 635 GLuint j; 636 637 fprintf(f, "%s", opcode_string); 638 if (inst->CondUpdate) 639 fprintf(f, ".C"); 640 641 /* frag prog only */ 642 if (inst->SaturateMode == SATURATE_ZERO_ONE) 643 fprintf(f, "_SAT"); 644 645 fprintf(f, " "); 646 if (inst->DstReg.File != PROGRAM_UNDEFINED) { 647 fprint_dst_reg(f, &inst->DstReg, mode, prog); 648 } 649 else { 650 fprintf(f, " ???"); 651 } 652 653 if (numRegs > 0) 654 fprintf(f, ", "); 655 656 for (j = 0; j < numRegs; j++) { 657 fprint_src_reg(f, inst->SrcReg + j, mode, prog); 658 if (j + 1 < numRegs) 659 fprintf(f, ", "); 660 } 661 662 fprint_comment(f, inst); 663 } 664 665 666 void 667 _mesa_print_alu_instruction(const struct prog_instruction *inst, 668 const char *opcode_string, GLuint numRegs) 669 { 670 _mesa_fprint_alu_instruction(stderr, inst, opcode_string, 671 numRegs, PROG_PRINT_DEBUG, NULL); 672 } 673 674 675 /** 676 * Print a single vertex/fragment program instruction. 677 */ 678 GLint 679 _mesa_fprint_instruction_opt(FILE *f, 680 const struct prog_instruction *inst, 681 GLint indent, 682 gl_prog_print_mode mode, 683 const struct gl_program *prog) 684 { 685 GLint i; 686 687 if (inst->Opcode == OPCODE_ELSE || 688 inst->Opcode == OPCODE_ENDIF || 689 inst->Opcode == OPCODE_ENDLOOP || 690 inst->Opcode == OPCODE_ENDSUB) { 691 indent -= 3; 692 } 693 for (i = 0; i < indent; i++) { 694 fprintf(f, " "); 695 } 696 697 switch (inst->Opcode) { 698 case OPCODE_PRINT: 699 fprintf(f, "PRINT '%s'", (char *) inst->Data); 700 if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { 701 fprintf(f, ", "); 702 fprintf(f, "%s[%d]%s", 703 _mesa_register_file_name((gl_register_file) inst->SrcReg[0].File), 704 inst->SrcReg[0].Index, 705 _mesa_swizzle_string(inst->SrcReg[0].Swizzle, 706 inst->SrcReg[0].Negate, GL_FALSE)); 707 } 708 if (inst->Comment) 709 fprintf(f, " # %s", inst->Comment); 710 fprint_comment(f, inst); 711 break; 712 case OPCODE_SWZ: 713 fprintf(f, "SWZ"); 714 if (inst->SaturateMode == SATURATE_ZERO_ONE) 715 fprintf(f, "_SAT"); 716 fprintf(f, " "); 717 fprint_dst_reg(f, &inst->DstReg, mode, prog); 718 fprintf(f, ", %s[%d], %s", 719 _mesa_register_file_name((gl_register_file) inst->SrcReg[0].File), 720 inst->SrcReg[0].Index, 721 _mesa_swizzle_string(inst->SrcReg[0].Swizzle, 722 inst->SrcReg[0].Negate, GL_TRUE)); 723 fprint_comment(f, inst); 724 break; 725 case OPCODE_TEX: 726 case OPCODE_TXP: 727 case OPCODE_TXL: 728 case OPCODE_TXB: 729 case OPCODE_TXD: 730 fprintf(f, "%s", _mesa_opcode_string(inst->Opcode)); 731 if (inst->SaturateMode == SATURATE_ZERO_ONE) 732 fprintf(f, "_SAT"); 733 fprintf(f, " "); 734 fprint_dst_reg(f, &inst->DstReg, mode, prog); 735 fprintf(f, ", "); 736 fprint_src_reg(f, &inst->SrcReg[0], mode, prog); 737 if (inst->Opcode == OPCODE_TXD) { 738 fprintf(f, ", "); 739 fprint_src_reg(f, &inst->SrcReg[1], mode, prog); 740 fprintf(f, ", "); 741 fprint_src_reg(f, &inst->SrcReg[2], mode, prog); 742 } 743 fprintf(f, ", texture[%d], ", inst->TexSrcUnit); 744 switch (inst->TexSrcTarget) { 745 case TEXTURE_1D_INDEX: fprintf(f, "1D"); break; 746 case TEXTURE_2D_INDEX: fprintf(f, "2D"); break; 747 case TEXTURE_3D_INDEX: fprintf(f, "3D"); break; 748 case TEXTURE_CUBE_INDEX: fprintf(f, "CUBE"); break; 749 case TEXTURE_RECT_INDEX: fprintf(f, "RECT"); break; 750 case TEXTURE_1D_ARRAY_INDEX: fprintf(f, "1D_ARRAY"); break; 751 case TEXTURE_2D_ARRAY_INDEX: fprintf(f, "2D_ARRAY"); break; 752 default: 753 ; 754 } 755 if (inst->TexShadow) 756 fprintf(f, " SHADOW"); 757 fprint_comment(f, inst); 758 break; 759 760 case OPCODE_KIL: 761 fprintf(f, "%s", _mesa_opcode_string(inst->Opcode)); 762 fprintf(f, " "); 763 fprint_src_reg(f, &inst->SrcReg[0], mode, prog); 764 fprint_comment(f, inst); 765 break; 766 case OPCODE_KIL_NV: 767 fprintf(f, "%s", _mesa_opcode_string(inst->Opcode)); 768 fprintf(f, " "); 769 fprintf(f, "%s.%s", 770 _mesa_condcode_string(inst->DstReg.CondMask), 771 _mesa_swizzle_string(inst->DstReg.CondSwizzle, 772 GL_FALSE, GL_FALSE)); 773 fprint_comment(f, inst); 774 break; 775 776 case OPCODE_ARL: 777 fprintf(f, "ARL "); 778 fprint_dst_reg(f, &inst->DstReg, mode, prog); 779 fprintf(f, ", "); 780 fprint_src_reg(f, &inst->SrcReg[0], mode, prog); 781 fprint_comment(f, inst); 782 break; 783 case OPCODE_BRA: 784 fprintf(f, "BRA %d (%s%s)", 785 inst->BranchTarget, 786 _mesa_condcode_string(inst->DstReg.CondMask), 787 _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); 788 fprint_comment(f, inst); 789 break; 790 case OPCODE_IF: 791 if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { 792 /* Use ordinary register */ 793 fprintf(f, "IF "); 794 fprint_src_reg(f, &inst->SrcReg[0], mode, prog); 795 fprintf(f, "; "); 796 } 797 else { 798 /* Use cond codes */ 799 fprintf(f, "IF (%s%s);", 800 _mesa_condcode_string(inst->DstReg.CondMask), 801 _mesa_swizzle_string(inst->DstReg.CondSwizzle, 802 0, GL_FALSE)); 803 } 804 fprintf(f, " # (if false, goto %d)", inst->BranchTarget); 805 fprint_comment(f, inst); 806 return indent + 3; 807 case OPCODE_ELSE: 808 fprintf(f, "ELSE; # (goto %d)\n", inst->BranchTarget); 809 return indent + 3; 810 case OPCODE_ENDIF: 811 fprintf(f, "ENDIF;\n"); 812 break; 813 case OPCODE_BGNLOOP: 814 fprintf(f, "BGNLOOP; # (end at %d)\n", inst->BranchTarget); 815 return indent + 3; 816 case OPCODE_ENDLOOP: 817 fprintf(f, "ENDLOOP; # (goto %d)\n", inst->BranchTarget); 818 break; 819 case OPCODE_BRK: 820 case OPCODE_CONT: 821 fprintf(f, "%s (%s%s); # (goto %d)", 822 _mesa_opcode_string(inst->Opcode), 823 _mesa_condcode_string(inst->DstReg.CondMask), 824 _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE), 825 inst->BranchTarget); 826 fprint_comment(f, inst); 827 break; 828 829 case OPCODE_BGNSUB: 830 if (mode == PROG_PRINT_NV) { 831 fprintf(f, "%s:\n", inst->Comment); /* comment is label */ 832 return indent; 833 } 834 else { 835 fprintf(f, "BGNSUB"); 836 fprint_comment(f, inst); 837 return indent + 3; 838 } 839 case OPCODE_ENDSUB: 840 if (mode == PROG_PRINT_DEBUG) { 841 fprintf(f, "ENDSUB"); 842 fprint_comment(f, inst); 843 } 844 break; 845 case OPCODE_CAL: 846 if (mode == PROG_PRINT_NV) { 847 fprintf(f, "CAL %s; # (goto %d)\n", inst->Comment, inst->BranchTarget); 848 } 849 else { 850 fprintf(f, "CAL %u", inst->BranchTarget); 851 fprint_comment(f, inst); 852 } 853 break; 854 case OPCODE_RET: 855 fprintf(f, "RET (%s%s)", 856 _mesa_condcode_string(inst->DstReg.CondMask), 857 _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE)); 858 fprint_comment(f, inst); 859 break; 860 861 case OPCODE_END: 862 fprintf(f, "END\n"); 863 break; 864 case OPCODE_NOP: 865 if (mode == PROG_PRINT_DEBUG) { 866 fprintf(f, "NOP"); 867 fprint_comment(f, inst); 868 } 869 else if (inst->Comment) { 870 /* ARB/NV extensions don't have NOP instruction */ 871 fprintf(f, "# %s\n", inst->Comment); 872 } 873 break; 874 case OPCODE_EMIT_VERTEX: 875 fprintf(f, "EMIT_VERTEX\n"); 876 break; 877 case OPCODE_END_PRIMITIVE: 878 fprintf(f, "END_PRIMITIVE\n"); 879 break; 880 /* XXX may need other special-case instructions */ 881 default: 882 if (inst->Opcode < MAX_OPCODE) { 883 /* typical alu instruction */ 884 _mesa_fprint_alu_instruction(f, inst, 885 _mesa_opcode_string(inst->Opcode), 886 _mesa_num_inst_src_regs(inst->Opcode), 887 mode, prog); 888 } 889 else { 890 _mesa_fprint_alu_instruction(f, inst, 891 _mesa_opcode_string(inst->Opcode), 892 3/*_mesa_num_inst_src_regs(inst->Opcode)*/, 893 mode, prog); 894 } 895 break; 896 } 897 return indent; 898 } 899 900 901 GLint 902 _mesa_print_instruction_opt(const struct prog_instruction *inst, 903 GLint indent, 904 gl_prog_print_mode mode, 905 const struct gl_program *prog) 906 { 907 return _mesa_fprint_instruction_opt(stderr, inst, indent, mode, prog); 908 } 909 910 911 void 912 _mesa_print_instruction(const struct prog_instruction *inst) 913 { 914 /* note: 4th param should be ignored for PROG_PRINT_DEBUG */ 915 _mesa_fprint_instruction_opt(stderr, inst, 0, PROG_PRINT_DEBUG, NULL); 916 } 917 918 919 920 /** 921 * Print program, with options. 922 */ 923 void 924 _mesa_fprint_program_opt(FILE *f, 925 const struct gl_program *prog, 926 gl_prog_print_mode mode, 927 GLboolean lineNumbers) 928 { 929 GLuint i, indent = 0; 930 931 switch (prog->Target) { 932 case GL_VERTEX_PROGRAM_ARB: 933 if (mode == PROG_PRINT_ARB) 934 fprintf(f, "!!ARBvp1.0\n"); 935 else if (mode == PROG_PRINT_NV) 936 fprintf(f, "!!VP1.0\n"); 937 else 938 fprintf(f, "# Vertex Program/Shader %u\n", prog->Id); 939 break; 940 case GL_FRAGMENT_PROGRAM_ARB: 941 case GL_FRAGMENT_PROGRAM_NV: 942 if (mode == PROG_PRINT_ARB) 943 fprintf(f, "!!ARBfp1.0\n"); 944 else if (mode == PROG_PRINT_NV) 945 fprintf(f, "!!FP1.0\n"); 946 else 947 fprintf(f, "# Fragment Program/Shader %u\n", prog->Id); 948 break; 949 case MESA_GEOMETRY_PROGRAM: 950 fprintf(f, "# Geometry Shader\n"); 951 } 952 953 for (i = 0; i < prog->NumInstructions; i++) { 954 if (lineNumbers) 955 fprintf(f, "%3d: ", i); 956 indent = _mesa_fprint_instruction_opt(f, prog->Instructions + i, 957 indent, mode, prog); 958 } 959 } 960 961 962 /** 963 * Print program to stderr, default options. 964 */ 965 void 966 _mesa_print_program(const struct gl_program *prog) 967 { 968 _mesa_fprint_program_opt(stderr, prog, PROG_PRINT_DEBUG, GL_TRUE); 969 } 970 971 972 /** 973 * Return binary representation of 64-bit value (as a string). 974 * Insert a comma to separate each group of 8 bits. 975 * Note we return a pointer to local static storage so this is not 976 * re-entrant, etc. 977 * XXX move to imports.[ch] if useful elsewhere. 978 */ 979 static const char * 980 binary(GLbitfield64 val) 981 { 982 static char buf[80]; 983 GLint i, len = 0; 984 for (i = 63; i >= 0; --i) { 985 if (val & (BITFIELD64_BIT(i))) 986 buf[len++] = '1'; 987 else if (len > 0 || i == 0) 988 buf[len++] = '0'; 989 if (len > 0 && ((i-1) % 8) == 7) 990 buf[len++] = ','; 991 } 992 buf[len] = '\0'; 993 return buf; 994 } 995 996 997 /** 998 * Print all of a program's parameters/fields to given file. 999 */ 1000 static void 1001 _mesa_fprint_program_parameters(FILE *f, 1002 struct gl_context *ctx, 1003 const struct gl_program *prog) 1004 { 1005 GLuint i; 1006 1007 fprintf(f, "InputsRead: %" PRIx64 " (0b%s)\n", 1008 (uint64_t) prog->InputsRead, binary(prog->InputsRead)); 1009 fprintf(f, "OutputsWritten: %" PRIx64 " (0b%s)\n", 1010 (uint64_t) prog->OutputsWritten, binary(prog->OutputsWritten)); 1011 fprintf(f, "NumInstructions=%d\n", prog->NumInstructions); 1012 fprintf(f, "NumTemporaries=%d\n", prog->NumTemporaries); 1013 fprintf(f, "NumParameters=%d\n", prog->NumParameters); 1014 fprintf(f, "NumAttributes=%d\n", prog->NumAttributes); 1015 fprintf(f, "NumAddressRegs=%d\n", prog->NumAddressRegs); 1016 fprintf(f, "IndirectRegisterFiles: 0x%x (0b%s)\n", 1017 prog->IndirectRegisterFiles, binary(prog->IndirectRegisterFiles)); 1018 fprintf(f, "SamplersUsed: 0x%x (0b%s)\n", 1019 prog->SamplersUsed, binary(prog->SamplersUsed)); 1020 fprintf(f, "Samplers=[ "); 1021 for (i = 0; i < MAX_SAMPLERS; i++) { 1022 fprintf(f, "%d ", prog->SamplerUnits[i]); 1023 } 1024 fprintf(f, "]\n"); 1025 1026 _mesa_load_state_parameters(ctx, prog->Parameters); 1027 1028 #if 0 1029 fprintf(f, "Local Params:\n"); 1030 for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){ 1031 const GLfloat *p = prog->LocalParams[i]; 1032 fprintf(f, "%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]); 1033 } 1034 #endif 1035 _mesa_print_parameter_list(prog->Parameters); 1036 } 1037 1038 1039 /** 1040 * Print all of a program's parameters/fields to stderr. 1041 */ 1042 void 1043 _mesa_print_program_parameters(struct gl_context *ctx, const struct gl_program *prog) 1044 { 1045 _mesa_fprint_program_parameters(stderr, ctx, prog); 1046 } 1047 1048 1049 /** 1050 * Print a program parameter list to given file. 1051 */ 1052 static void 1053 _mesa_fprint_parameter_list(FILE *f, 1054 const struct gl_program_parameter_list *list) 1055 { 1056 GLuint i; 1057 1058 if (!list) 1059 return; 1060 1061 if (0) 1062 fprintf(f, "param list %p\n", (void *) list); 1063 fprintf(f, "dirty state flags: 0x%x\n", list->StateFlags); 1064 for (i = 0; i < list->NumParameters; i++){ 1065 struct gl_program_parameter *param = list->Parameters + i; 1066 const GLfloat *v = (GLfloat *) list->ParameterValues[i]; 1067 fprintf(f, "param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g}", 1068 i, param->Size, 1069 _mesa_register_file_name(list->Parameters[i].Type), 1070 param->Name, v[0], v[1], v[2], v[3]); 1071 if (param->Flags & PROG_PARAM_BIT_CENTROID) 1072 fprintf(f, " Centroid"); 1073 if (param->Flags & PROG_PARAM_BIT_INVARIANT) 1074 fprintf(f, " Invariant"); 1075 if (param->Flags & PROG_PARAM_BIT_FLAT) 1076 fprintf(f, " Flat"); 1077 if (param->Flags & PROG_PARAM_BIT_LINEAR) 1078 fprintf(f, " Linear"); 1079 fprintf(f, "\n"); 1080 } 1081 } 1082 1083 1084 /** 1085 * Print a program parameter list to stderr. 1086 */ 1087 void 1088 _mesa_print_parameter_list(const struct gl_program_parameter_list *list) 1089 { 1090 _mesa_fprint_parameter_list(stderr, list); 1091 } 1092 1093 1094 /** 1095 * Write shader and associated info to a file. 1096 */ 1097 void 1098 _mesa_write_shader_to_file(const struct gl_shader *shader) 1099 { 1100 const char *type; 1101 char filename[100]; 1102 FILE *f; 1103 1104 if (shader->Type == GL_FRAGMENT_SHADER) 1105 type = "frag"; 1106 else if (shader->Type == GL_VERTEX_SHADER) 1107 type = "vert"; 1108 else 1109 type = "geom"; 1110 1111 _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type); 1112 f = fopen(filename, "w"); 1113 if (!f) { 1114 fprintf(stderr, "Unable to open %s for writing\n", filename); 1115 return; 1116 } 1117 1118 fprintf(f, "/* Shader %u source, checksum %u */\n", shader->Name, shader->SourceChecksum); 1119 fputs(shader->Source, f); 1120 fprintf(f, "\n"); 1121 1122 fprintf(f, "/* Compile status: %s */\n", 1123 shader->CompileStatus ? "ok" : "fail"); 1124 fprintf(f, "/* Log Info: */\n"); 1125 if (shader->InfoLog) { 1126 fputs(shader->InfoLog, f); 1127 } 1128 if (shader->CompileStatus && shader->Program) { 1129 fprintf(f, "/* GPU code */\n"); 1130 fprintf(f, "/*\n"); 1131 _mesa_fprint_program_opt(f, shader->Program, PROG_PRINT_DEBUG, GL_TRUE); 1132 fprintf(f, "*/\n"); 1133 fprintf(f, "/* Parameters / constants */\n"); 1134 fprintf(f, "/*\n"); 1135 _mesa_fprint_parameter_list(f, shader->Program->Parameters); 1136 fprintf(f, "*/\n"); 1137 } 1138 1139 fclose(f); 1140 } 1141 1142 1143 /** 1144 * Append the shader's uniform info/values to the shader log file. 1145 * The log file will typically have been created by the 1146 * _mesa_write_shader_to_file function. 1147 */ 1148 void 1149 _mesa_append_uniforms_to_file(const struct gl_shader *shader) 1150 { 1151 const struct gl_program *const prog = shader->Program; 1152 const char *type; 1153 char filename[100]; 1154 FILE *f; 1155 1156 if (shader->Type == GL_FRAGMENT_SHADER) 1157 type = "frag"; 1158 else 1159 type = "vert"; 1160 1161 _mesa_snprintf(filename, sizeof(filename), "shader_%u.%s", shader->Name, type); 1162 f = fopen(filename, "a"); /* append */ 1163 if (!f) { 1164 fprintf(stderr, "Unable to open %s for appending\n", filename); 1165 return; 1166 } 1167 1168 fprintf(f, "/* First-draw parameters / constants */\n"); 1169 fprintf(f, "/*\n"); 1170 _mesa_fprint_parameter_list(f, prog->Parameters); 1171 fprintf(f, "*/\n"); 1172 1173 fclose(f); 1174 } 1175