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