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