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