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