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