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