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