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