17ec681f3Smrg/* 27ec681f3Smrg * Copyright (c) 2012 Rob Clark <robdclark@gmail.com> 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217ec681f3Smrg * SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <fcntl.h> 257ec681f3Smrg#include <stdint.h> 267ec681f3Smrg#include <stdio.h> 277ec681f3Smrg#include <stdlib.h> 287ec681f3Smrg#include <string.h> 297ec681f3Smrg#include <unistd.h> 307ec681f3Smrg#include <sys/stat.h> 317ec681f3Smrg#include <sys/types.h> 327ec681f3Smrg 337ec681f3Smrg#include "disasm.h" 347ec681f3Smrg#include "io.h" 357ec681f3Smrg#include "redump.h" 367ec681f3Smrg 377ec681f3Smrg#define ASCII_XOR 0xff 387ec681f3Smrg#include "util.h" 397ec681f3Smrg 407ec681f3Smrgstruct pgm_header { 417ec681f3Smrg uint32_t size; 427ec681f3Smrg uint32_t unknown1; 437ec681f3Smrg uint32_t unknown2; 447ec681f3Smrg uint32_t revision; 457ec681f3Smrg uint32_t unknown4; 467ec681f3Smrg uint32_t unknown5; 477ec681f3Smrg uint32_t unknown6; 487ec681f3Smrg uint32_t unknown7; 497ec681f3Smrg uint32_t unknown8; 507ec681f3Smrg uint32_t num_attribs; 517ec681f3Smrg uint32_t num_uniforms; 527ec681f3Smrg uint32_t num_samplers; 537ec681f3Smrg uint32_t num_varyings; 547ec681f3Smrg uint32_t num_uniformblocks; 557ec681f3Smrg}; 567ec681f3Smrg 577ec681f3Smrgstruct vs_header { 587ec681f3Smrg uint32_t unknown1; /* seems to be # of sections up to and including shader */ 597ec681f3Smrg uint32_t unknown2; /* seems to be low byte or so of SQ_PROGRAM_CNTL */ 607ec681f3Smrg uint32_t unknown3; 617ec681f3Smrg uint32_t unknown4; 627ec681f3Smrg uint32_t unknown5; 637ec681f3Smrg uint32_t unknown6; 647ec681f3Smrg uint32_t unknown7; 657ec681f3Smrg uint32_t unknown8; 667ec681f3Smrg uint32_t unknown9; /* seems to be # of sections following shader */ 677ec681f3Smrg}; 687ec681f3Smrg 697ec681f3Smrgstruct fs_header { 707ec681f3Smrg uint32_t unknown1; 717ec681f3Smrg}; 727ec681f3Smrg/* 737ec681f3Smrg // Covers a lot of type_info 747ec681f3Smrg // varying, attribute, uniform, sampler 757ec681f3Smrg type_info & 0xFF 767ec681f3Smrg if ((type_info >> 8) == 0x8b) // vector 777ec681f3Smrg 0x50 = vec2 787ec681f3Smrg 0x51 = vec3 797ec681f3Smrg 0x52 = vec4 807ec681f3Smrg 0x53 = ivec2 817ec681f3Smrg 0x54 = ivec3 827ec681f3Smrg 0x55 = ivec4 837ec681f3Smrg 0x56 = bool // Why is this in vector? 847ec681f3Smrg 0x57 = bvec2 857ec681f3Smrg 0x58 = bvec3 867ec681f3Smrg 0x59 = bvec4 877ec681f3Smrg 0x5a = mat2 887ec681f3Smrg 0x5b = mat3 897ec681f3Smrg 0x5c = mat4 907ec681f3Smrg 0x5a = mat2x2 // Same as mat2 917ec681f3Smrg 0x65 = mat2x3 927ec681f3Smrg 0x66 = mat2x4 937ec681f3Smrg 0x67 = mat3x2 947ec681f3Smrg 0x5b = mat3x3 // Same as mat3 957ec681f3Smrg 0x68 = mat3x4 967ec681f3Smrg 0x69 = mat4x2 977ec681f3Smrg 0x6a = mat4x3 987ec681f3Smrg 0x5c = mat4x4 // same as mat4 997ec681f3Smrg 0x5e = sampler2D 1007ec681f3Smrg 0x5f = sampler3D 1017ec681f3Smrg 0x60 = samplerCube // XXX: Doesn't work 1027ec681f3Smrg 0x62 = sampler2DShadow 1037ec681f3Smrg 0xc6 = uvec2 1047ec681f3Smrg 0xc7 = uvec3 1057ec681f3Smrg 0xc8 = uvec4 1067ec681f3Smrg else if ((type_info >> 8) == 0x8d) // GLES3 samplers 1077ec681f3Smrg 0xC1 = sampler2DArray 1087ec681f3Smrg 0xC4 = sampler2DArrayShadow 1097ec681f3Smrg 0xC5 = samplerCubeShadow 1107ec681f3Smrg 0xCA = isampler2D 1117ec681f3Smrg 0xCB = isampler3D 1127ec681f3Smrg 0xCC = isamplerCube 1137ec681f3Smrg 0xD2 = usampler2D 1147ec681f3Smrg 0xD3 = usampler3D 1157ec681f3Smrg 0xD4 = usamplerCube 1167ec681f3Smrg 0xD7 = isampler2DArray 1177ec681f3Smrg 0xD7 = usampler2DArray // Is the same as isampler2DArray? 1187ec681f3Smrg else // 0x14 = single 1197ec681f3Smrg 0x04 = int 1207ec681f3Smrg 0x05 = uint 1217ec681f3Smrg 0x06 = float 1227ec681f3Smrg*/ 1237ec681f3Smrgstruct attribute { 1247ec681f3Smrg uint32_t type_info; 1257ec681f3Smrg uint32_t reg; /* seems to be the register the fetch instruction loads to */ 1267ec681f3Smrg uint32_t const_idx; /* the CONST() indx value for sampler */ 1277ec681f3Smrg uint32_t unknown2; 1287ec681f3Smrg uint32_t unknown3; 1297ec681f3Smrg uint32_t unknown4; 1307ec681f3Smrg uint32_t unknown5; 1317ec681f3Smrg char name[]; 1327ec681f3Smrg}; 1337ec681f3Smrg 1347ec681f3Smrgstruct uniform { 1357ec681f3Smrg uint32_t type_info; 1367ec681f3Smrg uint32_t unknown2; 1377ec681f3Smrg uint32_t unknown3; 1387ec681f3Smrg uint32_t unknown4; 1397ec681f3Smrg uint32_t const_base; /* const base register (for uniforms that take more than 1407ec681f3Smrg one const reg, ie. matrices) */ 1417ec681f3Smrg uint32_t unknown6; 1427ec681f3Smrg uint32_t const_reg; /* the const register holding the value */ 1437ec681f3Smrg uint32_t unknown7; 1447ec681f3Smrg uint32_t unknown8; 1457ec681f3Smrg uint32_t unknown9; 1467ec681f3Smrg union { 1477ec681f3Smrg struct { 1487ec681f3Smrg char name[1]; 1497ec681f3Smrg } v1; 1507ec681f3Smrg struct { 1517ec681f3Smrg uint32_t unknown10; 1527ec681f3Smrg uint32_t unknown11; 1537ec681f3Smrg uint32_t unknown12; 1547ec681f3Smrg char name[]; 1557ec681f3Smrg } v2; 1567ec681f3Smrg }; 1577ec681f3Smrg}; 1587ec681f3Smrg 1597ec681f3Smrgstruct uniformblockmember { 1607ec681f3Smrg uint32_t type_info; 1617ec681f3Smrg uint32_t is_array; 1627ec681f3Smrg uint32_t array_size; /* elements in the array */ 1637ec681f3Smrg uint32_t unknown2; /* Same as array_size */ 1647ec681f3Smrg uint32_t 1657ec681f3Smrg unknown3; /* Seems to be a offset within UBO in vertex (by components) */ 1667ec681f3Smrg uint32_t unknown4; 1677ec681f3Smrg uint32_t 1687ec681f3Smrg unknown5; /* Seems to be a offset within UBO in fragment (by vec4) */ 1697ec681f3Smrg uint32_t unknown6; 1707ec681f3Smrg uint32_t unknown7; 1717ec681f3Smrg uint32_t unknown8; 1727ec681f3Smrg uint32_t unknown9; /* UBO block index? */ 1737ec681f3Smrg uint32_t unknown10; 1747ec681f3Smrg uint32_t unknown11; 1757ec681f3Smrg uint32_t unknown12; 1767ec681f3Smrg char name[]; 1777ec681f3Smrg}; 1787ec681f3Smrg 1797ec681f3Smrgstruct uniformblock { 1807ec681f3Smrg uint32_t type_info; 1817ec681f3Smrg uint32_t unknown1; 1827ec681f3Smrg uint32_t unknown2; 1837ec681f3Smrg uint32_t unknown3; 1847ec681f3Smrg uint32_t unknown4; 1857ec681f3Smrg uint32_t num_members; 1867ec681f3Smrg uint32_t num_members2; 1877ec681f3Smrg uint32_t unknown5; 1887ec681f3Smrg uint32_t unknown6; 1897ec681f3Smrg uint32_t unknown7; 1907ec681f3Smrg char name[]; 1917ec681f3Smrg}; 1927ec681f3Smrg 1937ec681f3Smrgstruct sampler { 1947ec681f3Smrg uint32_t type_info; 1957ec681f3Smrg uint32_t is_array; 1967ec681f3Smrg uint32_t array_size; /* elements in the array */ 1977ec681f3Smrg uint32_t unknown4; /* same as array_size */ 1987ec681f3Smrg uint32_t unknown5; 1997ec681f3Smrg uint32_t unknown6; 2007ec681f3Smrg uint32_t const_idx; /* the CONST() indx value for the sampler */ 2017ec681f3Smrg uint32_t unknown7; 2027ec681f3Smrg char name[]; 2037ec681f3Smrg}; 2047ec681f3Smrg 2057ec681f3Smrgstruct varying { 2067ec681f3Smrg uint32_t type_info; 2077ec681f3Smrg uint32_t unknown2; 2087ec681f3Smrg uint32_t unknown3; 2097ec681f3Smrg uint32_t reg; /* the register holding the value (on entry to the shader) */ 2107ec681f3Smrg char name[]; 2117ec681f3Smrg}; 2127ec681f3Smrg 2137ec681f3Smrgstruct output { 2147ec681f3Smrg uint32_t type_info; 2157ec681f3Smrg uint32_t unknown2; 2167ec681f3Smrg uint32_t unknown3; 2177ec681f3Smrg uint32_t unknown4; 2187ec681f3Smrg uint32_t unknown5; 2197ec681f3Smrg uint32_t unknown6; 2207ec681f3Smrg uint32_t unknown7; 2217ec681f3Smrg uint32_t unknown8; 2227ec681f3Smrg char name[]; 2237ec681f3Smrg}; 2247ec681f3Smrg 2257ec681f3Smrgstruct constant { 2267ec681f3Smrg uint32_t unknown1; 2277ec681f3Smrg uint32_t unknown2; 2287ec681f3Smrg uint32_t unknown3; 2297ec681f3Smrg uint32_t const_idx; 2307ec681f3Smrg float val[]; 2317ec681f3Smrg}; 2327ec681f3Smrg 2337ec681f3Smrgstruct state { 2347ec681f3Smrg char *buf; 2357ec681f3Smrg int sz; 2367ec681f3Smrg struct pgm_header *hdr; 2377ec681f3Smrg struct attribute *attribs[32]; /* don't really know the upper limit.. */ 2387ec681f3Smrg struct uniform *uniforms[32]; 2397ec681f3Smrg struct sampler *samplers[32]; 2407ec681f3Smrg struct varying *varyings[32]; 2417ec681f3Smrg struct { 2427ec681f3Smrg struct uniformblock *header; 2437ec681f3Smrg struct uniformblockmember **members; /* GL ES 3.0 spec mandates minimum 2447ec681f3Smrg 16K support. a3xx supports 65K */ 2457ec681f3Smrg } uniformblocks[24]; /* Maximum a330 supports */ 2467ec681f3Smrg struct output *outputs[0]; /* I guess only one?? */ 2477ec681f3Smrg}; 2487ec681f3Smrg 2497ec681f3Smrgstatic const char *infile; 2507ec681f3Smrgstatic int full_dump = 1; 2517ec681f3Smrgstatic int dump_shaders = 0; 2527ec681f3Smrgstatic int gpu_id; 2537ec681f3Smrg 2547ec681f3Smrgstatic char * 2557ec681f3Smrgfind_sect_end(char *buf, int sz) 2567ec681f3Smrg{ 2577ec681f3Smrg uint8_t *ptr = (uint8_t *)buf; 2587ec681f3Smrg uint8_t *end = ptr + sz - 3; 2597ec681f3Smrg 2607ec681f3Smrg while (ptr < end) { 2617ec681f3Smrg uint32_t d = 0; 2627ec681f3Smrg 2637ec681f3Smrg d |= ptr[0] << 0; 2647ec681f3Smrg d |= ptr[1] << 8; 2657ec681f3Smrg d |= ptr[2] << 16; 2667ec681f3Smrg d |= ptr[3] << 24; 2677ec681f3Smrg 2687ec681f3Smrg /* someone at QC likes baseball */ 2697ec681f3Smrg if (d == 0xba5eba11) 2707ec681f3Smrg return (char *)ptr; 2717ec681f3Smrg 2727ec681f3Smrg ptr++; 2737ec681f3Smrg } 2747ec681f3Smrg return NULL; 2757ec681f3Smrg} 2767ec681f3Smrg 2777ec681f3Smrgstatic void * 2787ec681f3Smrgnext_sect(struct state *state, int *sect_size) 2797ec681f3Smrg{ 2807ec681f3Smrg char *end = find_sect_end(state->buf, state->sz); 2817ec681f3Smrg void *sect; 2827ec681f3Smrg 2837ec681f3Smrg if (!end) 2847ec681f3Smrg return NULL; 2857ec681f3Smrg 2867ec681f3Smrg *sect_size = end - state->buf; 2877ec681f3Smrg 2887ec681f3Smrg /* copy the section to keep things nicely 32b aligned: */ 2897ec681f3Smrg sect = malloc(ALIGN(*sect_size, 4)); 2907ec681f3Smrg memcpy(sect, state->buf, *sect_size); 2917ec681f3Smrg 2927ec681f3Smrg state->sz -= *sect_size + 4; 2937ec681f3Smrg state->buf = end + 4; 2947ec681f3Smrg 2957ec681f3Smrg return sect; 2967ec681f3Smrg} 2977ec681f3Smrg 2987ec681f3Smrgstatic int 2997ec681f3Smrgvalid_type(uint32_t type_info) 3007ec681f3Smrg{ 3017ec681f3Smrg switch ((type_info >> 8) & 0xff) { 3027ec681f3Smrg case 0x8b: /* vector */ 3037ec681f3Smrg case 0x8d: /* GLES3 samplers */ 3047ec681f3Smrg case 0x14: /* float */ 3057ec681f3Smrg return 1; 3067ec681f3Smrg default: 3077ec681f3Smrg return 0; 3087ec681f3Smrg } 3097ec681f3Smrg} 3107ec681f3Smrg 3117ec681f3Smrg#if 0 3127ec681f3Smrgstatic int valid_uniformblock(uint32_t type_info) 3137ec681f3Smrg{ 3147ec681f3Smrg if (type_info == 0x128) 3157ec681f3Smrg return 1; 3167ec681f3Smrg return 0; 3177ec681f3Smrg} 3187ec681f3Smrg#endif 3197ec681f3Smrg 3207ec681f3Smrgstatic void 3217ec681f3Smrgdump_attribute(struct attribute *attrib) 3227ec681f3Smrg{ 3237ec681f3Smrg printf("\tR%d, CONST(%d): %s\n", attrib->reg, attrib->const_idx, 3247ec681f3Smrg attrib->name); 3257ec681f3Smrg} 3267ec681f3Smrg 3277ec681f3Smrgstatic inline int 3287ec681f3Smrgis_uniform_v2(struct uniform *uniform) 3297ec681f3Smrg{ 3307ec681f3Smrg /* TODO maybe this should be based on revision #? */ 3317ec681f3Smrg if (uniform->v2.unknown10 == 0) 3327ec681f3Smrg return 1; 3337ec681f3Smrg return 0; 3347ec681f3Smrg} 3357ec681f3Smrg 3367ec681f3Smrgstatic void 3377ec681f3Smrgdump_uniform(struct uniform *uniform) 3387ec681f3Smrg{ 3397ec681f3Smrg char *name = is_uniform_v2(uniform) ? uniform->v2.name : uniform->v1.name; 3407ec681f3Smrg if (uniform->const_reg == -1) { 3417ec681f3Smrg printf("\tC%d+: %s\n", uniform->const_base, name); 3427ec681f3Smrg } else { 3437ec681f3Smrg printf("\tC%d: %s\n", uniform->const_reg, name); 3447ec681f3Smrg } 3457ec681f3Smrg} 3467ec681f3Smrg 3477ec681f3Smrgstatic void 3487ec681f3Smrgdump_sampler(struct sampler *sampler) 3497ec681f3Smrg{ 3507ec681f3Smrg printf("\tCONST(%d): %s\n", sampler->const_idx, sampler->name); 3517ec681f3Smrg} 3527ec681f3Smrg 3537ec681f3Smrgstatic void 3547ec681f3Smrgdump_varying(struct varying *varying) 3557ec681f3Smrg{ 3567ec681f3Smrg printf("\tR%d: %s\n", varying->reg, varying->name); 3577ec681f3Smrg} 3587ec681f3Smrg 3597ec681f3Smrgstatic void 3607ec681f3Smrgdump_uniformblock(struct uniformblock *uniformblock) 3617ec681f3Smrg{ 3627ec681f3Smrg printf("\tUniform Block: %s(%d)\n", uniformblock->name, 3637ec681f3Smrg uniformblock->num_members); 3647ec681f3Smrg} 3657ec681f3Smrg 3667ec681f3Smrgstatic void 3677ec681f3Smrgdump_uniformblockmember(struct uniformblockmember *member) 3687ec681f3Smrg{ 3697ec681f3Smrg printf("Uniform Block member: %s\n", member->name); 3707ec681f3Smrg} 3717ec681f3Smrg 3727ec681f3Smrgstatic void 3737ec681f3Smrgdump_output(struct output *output) 3747ec681f3Smrg{ 3757ec681f3Smrg printf("\tR?: %s\n", output->name); 3767ec681f3Smrg} 3777ec681f3Smrg 3787ec681f3Smrgstatic void 3797ec681f3Smrgdump_constant(struct constant *constant) 3807ec681f3Smrg{ 3817ec681f3Smrg printf("\tC%d: %f, %f, %f, %f\n", constant->const_idx, constant->val[0], 3827ec681f3Smrg constant->val[1], constant->val[2], constant->val[3]); 3837ec681f3Smrg} 3847ec681f3Smrg 3857ec681f3Smrg/* dump attr/uniform/sampler/varying/const summary: */ 3867ec681f3Smrgstatic void 3877ec681f3Smrgdump_short_summary(struct state *state, int nconsts, 3887ec681f3Smrg struct constant **constants) 3897ec681f3Smrg{ 3907ec681f3Smrg int i; 3917ec681f3Smrg 3927ec681f3Smrg /* dump attr/uniform/sampler/varying/const summary: */ 3937ec681f3Smrg for (i = 0; i < state->hdr->num_varyings; i++) { 3947ec681f3Smrg dump_varying(state->varyings[i]); 3957ec681f3Smrg } 3967ec681f3Smrg for (i = 0; i < state->hdr->num_attribs; i++) { 3977ec681f3Smrg dump_attribute(state->attribs[i]); 3987ec681f3Smrg } 3997ec681f3Smrg for (i = 0; i < state->hdr->num_uniforms; i++) { 4007ec681f3Smrg dump_uniform(state->uniforms[i]); 4017ec681f3Smrg } 4027ec681f3Smrg for (i = 0; i < state->hdr->num_samplers; i++) { 4037ec681f3Smrg dump_sampler(state->samplers[i]); 4047ec681f3Smrg } 4057ec681f3Smrg for (i = 0; i < nconsts - 1; i++) { 4067ec681f3Smrg if (constants[i]->unknown2 == 0) { 4077ec681f3Smrg dump_constant(constants[i]); 4087ec681f3Smrg } 4097ec681f3Smrg } 4107ec681f3Smrg printf("\n"); 4117ec681f3Smrg} 4127ec681f3Smrg 4137ec681f3Smrgstatic void 4147ec681f3Smrgdump_raw_shader(uint32_t *dwords, uint32_t sizedwords, int n, char *ext) 4157ec681f3Smrg{ 4167ec681f3Smrg static char filename[256]; 4177ec681f3Smrg int fd; 4187ec681f3Smrg 4197ec681f3Smrg if (!dump_shaders) 4207ec681f3Smrg return; 4217ec681f3Smrg 4227ec681f3Smrg sprintf(filename, "%.*s-%d.%s", (int)strlen(infile) - 3, infile, n, ext); 4237ec681f3Smrg fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644); 4247ec681f3Smrg if (fd != -1) { 4257ec681f3Smrg write(fd, dwords, sizedwords * 4); 4267ec681f3Smrg close(fd); 4277ec681f3Smrg } 4287ec681f3Smrg} 4297ec681f3Smrg 4307ec681f3Smrgstatic void 4317ec681f3Smrgdump_shaders_a2xx(struct state *state) 4327ec681f3Smrg{ 4337ec681f3Smrg int i, sect_size; 4347ec681f3Smrg uint8_t *ptr; 4357ec681f3Smrg 4367ec681f3Smrg /* dump vertex shaders: */ 4377ec681f3Smrg for (i = 0; i < 3; i++) { 4387ec681f3Smrg struct vs_header *vs_hdr = next_sect(state, §_size); 4397ec681f3Smrg struct constant *constants[32]; 4407ec681f3Smrg int j, level = 0; 4417ec681f3Smrg 4427ec681f3Smrg printf("\n"); 4437ec681f3Smrg 4447ec681f3Smrg if (full_dump) { 4457ec681f3Smrg printf("#######################################################\n"); 4467ec681f3Smrg printf("######## VS%d HEADER: (size %d)\n", i, sect_size); 4477ec681f3Smrg dump_hex((void *)vs_hdr, sect_size); 4487ec681f3Smrg } 4497ec681f3Smrg 4507ec681f3Smrg for (j = 0; j < (int)vs_hdr->unknown1 - 1; j++) { 4517ec681f3Smrg constants[j] = next_sect(state, §_size); 4527ec681f3Smrg if (full_dump) { 4537ec681f3Smrg printf("######## VS%d CONST: (size=%d)\n", i, sect_size); 4547ec681f3Smrg dump_constant(constants[j]); 4557ec681f3Smrg dump_hex((char *)constants[j], sect_size); 4567ec681f3Smrg } 4577ec681f3Smrg } 4587ec681f3Smrg 4597ec681f3Smrg ptr = next_sect(state, §_size); 4607ec681f3Smrg printf("######## VS%d SHADER: (size=%d)\n", i, sect_size); 4617ec681f3Smrg if (full_dump) { 4627ec681f3Smrg dump_hex(ptr, sect_size); 4637ec681f3Smrg level = 1; 4647ec681f3Smrg } else { 4657ec681f3Smrg dump_short_summary(state, vs_hdr->unknown1 - 1, constants); 4667ec681f3Smrg } 4677ec681f3Smrg disasm_a2xx((uint32_t *)(ptr + 32), (sect_size - 32) / 4, level + 1, 4687ec681f3Smrg MESA_SHADER_VERTEX); 4697ec681f3Smrg dump_raw_shader((uint32_t *)(ptr + 32), (sect_size - 32) / 4, i, "vo"); 4707ec681f3Smrg free(ptr); 4717ec681f3Smrg 4727ec681f3Smrg for (j = 0; j < vs_hdr->unknown9; j++) { 4737ec681f3Smrg ptr = next_sect(state, §_size); 4747ec681f3Smrg if (full_dump) { 4757ec681f3Smrg printf("######## VS%d CONST?: (size=%d)\n", i, sect_size); 4767ec681f3Smrg dump_hex(ptr, sect_size); 4777ec681f3Smrg } 4787ec681f3Smrg free(ptr); 4797ec681f3Smrg } 4807ec681f3Smrg 4817ec681f3Smrg for (j = 0; j < vs_hdr->unknown1 - 1; j++) { 4827ec681f3Smrg free(constants[j]); 4837ec681f3Smrg } 4847ec681f3Smrg 4857ec681f3Smrg free(vs_hdr); 4867ec681f3Smrg } 4877ec681f3Smrg 4887ec681f3Smrg /* dump fragment shaders: */ 4897ec681f3Smrg for (i = 0; i < 1; i++) { 4907ec681f3Smrg struct fs_header *fs_hdr = next_sect(state, §_size); 4917ec681f3Smrg struct constant *constants[32]; 4927ec681f3Smrg int j, level = 0; 4937ec681f3Smrg 4947ec681f3Smrg printf("\n"); 4957ec681f3Smrg 4967ec681f3Smrg if (full_dump) { 4977ec681f3Smrg printf("#######################################################\n"); 4987ec681f3Smrg printf("######## FS%d HEADER: (size %d)\n", i, sect_size); 4997ec681f3Smrg dump_hex((void *)fs_hdr, sect_size); 5007ec681f3Smrg } 5017ec681f3Smrg 5027ec681f3Smrg for (j = 0; j < fs_hdr->unknown1 - 1; j++) { 5037ec681f3Smrg constants[j] = next_sect(state, §_size); 5047ec681f3Smrg if (full_dump) { 5057ec681f3Smrg printf("######## FS%d CONST: (size=%d)\n", i, sect_size); 5067ec681f3Smrg dump_constant(constants[j]); 5077ec681f3Smrg dump_hex((char *)constants[j], sect_size); 5087ec681f3Smrg } 5097ec681f3Smrg } 5107ec681f3Smrg 5117ec681f3Smrg ptr = next_sect(state, §_size); 5127ec681f3Smrg printf("######## FS%d SHADER: (size=%d)\n", i, sect_size); 5137ec681f3Smrg if (full_dump) { 5147ec681f3Smrg dump_hex(ptr, sect_size); 5157ec681f3Smrg level = 1; 5167ec681f3Smrg } else { 5177ec681f3Smrg dump_short_summary(state, fs_hdr->unknown1 - 1, constants); 5187ec681f3Smrg } 5197ec681f3Smrg disasm_a2xx((uint32_t *)(ptr + 32), (sect_size - 32) / 4, level + 1, 5207ec681f3Smrg MESA_SHADER_FRAGMENT); 5217ec681f3Smrg dump_raw_shader((uint32_t *)(ptr + 32), (sect_size - 32) / 4, i, "fo"); 5227ec681f3Smrg free(ptr); 5237ec681f3Smrg 5247ec681f3Smrg for (j = 0; j < fs_hdr->unknown1 - 1; j++) { 5257ec681f3Smrg free(constants[j]); 5267ec681f3Smrg } 5277ec681f3Smrg 5287ec681f3Smrg free(fs_hdr); 5297ec681f3Smrg } 5307ec681f3Smrg} 5317ec681f3Smrg 5327ec681f3Smrgstatic void 5337ec681f3Smrgdump_shaders_a3xx(struct state *state) 5347ec681f3Smrg{ 5357ec681f3Smrg int i, j; 5367ec681f3Smrg 5377ec681f3Smrg /* dump vertex shaders: */ 5387ec681f3Smrg for (i = 0; i < 2; i++) { 5397ec681f3Smrg int instrs_size, hdr_size, sect_size, nconsts = 0, level = 0, compact = 0; 5407ec681f3Smrg uint8_t *vs_hdr; 5417ec681f3Smrg struct constant *constants[32]; 5427ec681f3Smrg uint8_t *instrs = NULL; 5437ec681f3Smrg 5447ec681f3Smrg vs_hdr = next_sect(state, &hdr_size); 5457ec681f3Smrg printf("hdr_size=%d\n", hdr_size); 5467ec681f3Smrg 5477ec681f3Smrg /* seems like there are two cases, either: 5487ec681f3Smrg * 1) 152 byte header, 5497ec681f3Smrg * 2) zero or more 32 byte compiler const sections 5507ec681f3Smrg * 3) followed by shader instructions 5517ec681f3Smrg * or, if there are no compiler consts, this can be 5527ec681f3Smrg * all smashed in one large section 5537ec681f3Smrg */ 5547ec681f3Smrg int n; 5557ec681f3Smrg if (state->hdr->revision >= 0xb) 5567ec681f3Smrg n = 160; 5577ec681f3Smrg else if (state->hdr->revision >= 7) 5587ec681f3Smrg n = 156; 5597ec681f3Smrg else 5607ec681f3Smrg n = 152; 5617ec681f3Smrg if (hdr_size > n) { 5627ec681f3Smrg instrs = &vs_hdr[n]; 5637ec681f3Smrg instrs_size = hdr_size - n; 5647ec681f3Smrg hdr_size = n; 5657ec681f3Smrg compact = 1; 5667ec681f3Smrg } else { 5677ec681f3Smrg while (1) { 5687ec681f3Smrg void *ptr = next_sect(state, §_size); 5697ec681f3Smrg 5707ec681f3Smrg if ((sect_size != 32) && (sect_size != 44)) { 5717ec681f3Smrg /* end of constants: */ 5727ec681f3Smrg instrs = ptr; 5737ec681f3Smrg instrs_size = sect_size; 5747ec681f3Smrg break; 5757ec681f3Smrg } 5767ec681f3Smrg dump_hex_ascii(ptr, sect_size, 0); 5777ec681f3Smrg constants[nconsts++] = ptr; 5787ec681f3Smrg } 5797ec681f3Smrg } 5807ec681f3Smrg 5817ec681f3Smrg printf("\n"); 5827ec681f3Smrg 5837ec681f3Smrg if (full_dump) { 5847ec681f3Smrg printf("#######################################################\n"); 5857ec681f3Smrg printf("######## VS%d HEADER: (size %d)\n", i, hdr_size); 5867ec681f3Smrg dump_hex((void *)vs_hdr, hdr_size); 5877ec681f3Smrg for (j = 0; j < nconsts; j++) { 5887ec681f3Smrg printf("######## VS%d CONST: (size=%d)\n", i, 5897ec681f3Smrg (int)sizeof(constants[i])); 5907ec681f3Smrg dump_constant(constants[j]); 5917ec681f3Smrg dump_hex((char *)constants[j], sizeof(constants[j])); 5927ec681f3Smrg } 5937ec681f3Smrg } 5947ec681f3Smrg 5957ec681f3Smrg printf("######## VS%d SHADER: (size=%d)\n", i, instrs_size); 5967ec681f3Smrg if (full_dump) { 5977ec681f3Smrg dump_hex(instrs, instrs_size); 5987ec681f3Smrg level = 1; 5997ec681f3Smrg } else { 6007ec681f3Smrg dump_short_summary(state, nconsts, constants); 6017ec681f3Smrg } 6027ec681f3Smrg 6037ec681f3Smrg if (!compact) { 6047ec681f3Smrg if (state->hdr->revision >= 7) { 6057ec681f3Smrg instrs += ALIGN(instrs_size, 8) - instrs_size; 6067ec681f3Smrg instrs_size = ALIGN(instrs_size, 8); 6077ec681f3Smrg } 6087ec681f3Smrg instrs += 32; 6097ec681f3Smrg instrs_size -= 32; 6107ec681f3Smrg } 6117ec681f3Smrg 6127ec681f3Smrg disasm_a3xx((uint32_t *)instrs, instrs_size / 4, level + 1, stdout, 6137ec681f3Smrg gpu_id); 6147ec681f3Smrg dump_raw_shader((uint32_t *)instrs, instrs_size / 4, i, "vo3"); 6157ec681f3Smrg free(vs_hdr); 6167ec681f3Smrg } 6177ec681f3Smrg 6187ec681f3Smrg /* dump fragment shaders: */ 6197ec681f3Smrg for (i = 0; i < 1; i++) { 6207ec681f3Smrg int instrs_size, hdr_size, sect_size, nconsts = 0, level = 0, compact = 0; 6217ec681f3Smrg uint8_t *fs_hdr; 6227ec681f3Smrg struct constant *constants[32]; 6237ec681f3Smrg uint8_t *instrs = NULL; 6247ec681f3Smrg 6257ec681f3Smrg fs_hdr = next_sect(state, &hdr_size); 6267ec681f3Smrg 6277ec681f3Smrg printf("hdr_size=%d\n", hdr_size); 6287ec681f3Smrg /* two cases, similar to vertex shader, but magic # is 200 6297ec681f3Smrg * (or 208 for newer?).. 6307ec681f3Smrg */ 6317ec681f3Smrg int n; 6327ec681f3Smrg if (state->hdr->revision >= 0xb) 6337ec681f3Smrg n = 256; 6347ec681f3Smrg else if (state->hdr->revision >= 8) 6357ec681f3Smrg n = 208; 6367ec681f3Smrg else if (state->hdr->revision == 7) 6377ec681f3Smrg n = 204; 6387ec681f3Smrg else 6397ec681f3Smrg n = 200; 6407ec681f3Smrg 6417ec681f3Smrg if (hdr_size > n) { 6427ec681f3Smrg instrs = &fs_hdr[n]; 6437ec681f3Smrg instrs_size = hdr_size - n; 6447ec681f3Smrg hdr_size = n; 6457ec681f3Smrg compact = 1; 6467ec681f3Smrg } else { 6477ec681f3Smrg while (1) { 6487ec681f3Smrg void *ptr = next_sect(state, §_size); 6497ec681f3Smrg 6507ec681f3Smrg if ((sect_size != 32) && (sect_size != 44)) { 6517ec681f3Smrg /* end of constants: */ 6527ec681f3Smrg instrs = ptr; 6537ec681f3Smrg instrs_size = sect_size; 6547ec681f3Smrg break; 6557ec681f3Smrg } 6567ec681f3Smrg 6577ec681f3Smrg dump_hex_ascii(ptr, sect_size, 0); 6587ec681f3Smrg constants[nconsts++] = ptr; 6597ec681f3Smrg } 6607ec681f3Smrg } 6617ec681f3Smrg 6627ec681f3Smrg printf("\n"); 6637ec681f3Smrg 6647ec681f3Smrg if (full_dump) { 6657ec681f3Smrg printf("#######################################################\n"); 6667ec681f3Smrg printf("######## FS%d HEADER: (size %d)\n", i, hdr_size); 6677ec681f3Smrg dump_hex((void *)fs_hdr, hdr_size); 6687ec681f3Smrg for (j = 0; j < nconsts; j++) { 6697ec681f3Smrg printf("######## FS%d CONST: (size=%d)\n", i, 6707ec681f3Smrg (int)sizeof(constants[i])); 6717ec681f3Smrg dump_constant(constants[j]); 6727ec681f3Smrg dump_hex((char *)constants[j], sizeof(constants[j])); 6737ec681f3Smrg } 6747ec681f3Smrg } 6757ec681f3Smrg 6767ec681f3Smrg printf("######## FS%d SHADER: (size=%d)\n", i, instrs_size); 6777ec681f3Smrg if (full_dump) { 6787ec681f3Smrg dump_hex(instrs, instrs_size); 6797ec681f3Smrg level = 1; 6807ec681f3Smrg } else { 6817ec681f3Smrg dump_short_summary(state, nconsts, constants); 6827ec681f3Smrg } 6837ec681f3Smrg 6847ec681f3Smrg if (!compact) { 6857ec681f3Smrg if (state->hdr->revision >= 7) { 6867ec681f3Smrg instrs += 44; 6877ec681f3Smrg instrs_size -= 44; 6887ec681f3Smrg } else { 6897ec681f3Smrg instrs += 32; 6907ec681f3Smrg instrs_size -= 32; 6917ec681f3Smrg } 6927ec681f3Smrg } 6937ec681f3Smrg disasm_a3xx((uint32_t *)instrs, instrs_size / 4, level + 1, stdout, 6947ec681f3Smrg gpu_id); 6957ec681f3Smrg dump_raw_shader((uint32_t *)instrs, instrs_size / 4, i, "fo3"); 6967ec681f3Smrg free(fs_hdr); 6977ec681f3Smrg } 6987ec681f3Smrg} 6997ec681f3Smrg 7007ec681f3Smrgstatic void 7017ec681f3Smrgdump_program(struct state *state) 7027ec681f3Smrg{ 7037ec681f3Smrg int i, sect_size; 7047ec681f3Smrg uint8_t *ptr; 7057ec681f3Smrg 7067ec681f3Smrg state->hdr = next_sect(state, §_size); 7077ec681f3Smrg 7087ec681f3Smrg printf("######## HEADER: (size %d)\n", sect_size); 7097ec681f3Smrg printf("\tsize: %d\n", state->hdr->size); 7107ec681f3Smrg printf("\trevision: %d\n", state->hdr->revision); 7117ec681f3Smrg printf("\tattributes: %d\n", state->hdr->num_attribs); 7127ec681f3Smrg printf("\tuniforms: %d\n", state->hdr->num_uniforms); 7137ec681f3Smrg printf("\tsamplers: %d\n", state->hdr->num_samplers); 7147ec681f3Smrg printf("\tvaryings: %d\n", state->hdr->num_varyings); 7157ec681f3Smrg printf("\tuniform blocks: %d\n", state->hdr->num_uniformblocks); 7167ec681f3Smrg if (full_dump) 7177ec681f3Smrg dump_hex((void *)state->hdr, sect_size); 7187ec681f3Smrg printf("\n"); 7197ec681f3Smrg 7207ec681f3Smrg /* there seems to be two 0xba5eba11's at the end of the header, possibly 7217ec681f3Smrg * with some other stuff between them: 7227ec681f3Smrg */ 7237ec681f3Smrg ptr = next_sect(state, §_size); 7247ec681f3Smrg if (full_dump) { 7257ec681f3Smrg dump_hex_ascii(ptr, sect_size, 0); 7267ec681f3Smrg } 7277ec681f3Smrg 7287ec681f3Smrg for (i = 0; (i < state->hdr->num_attribs) && (state->sz > 0); i++) { 7297ec681f3Smrg state->attribs[i] = next_sect(state, §_size); 7307ec681f3Smrg 7317ec681f3Smrg /* hmm, for a3xx (or maybe just newer driver version), we have some 7327ec681f3Smrg * extra sections that don't seem useful, so skip these: 7337ec681f3Smrg */ 7347ec681f3Smrg while (!valid_type(state->attribs[i]->type_info)) { 7357ec681f3Smrg dump_hex_ascii(state->attribs[i], sect_size, 0); 7367ec681f3Smrg state->attribs[i] = next_sect(state, §_size); 7377ec681f3Smrg } 7387ec681f3Smrg 7397ec681f3Smrg clean_ascii(state->attribs[i]->name, sect_size - 28); 7407ec681f3Smrg if (full_dump) { 7417ec681f3Smrg printf("######## ATTRIBUTE: (size %d)\n", sect_size); 7427ec681f3Smrg dump_attribute(state->attribs[i]); 7437ec681f3Smrg dump_hex((char *)state->attribs[i], sect_size); 7447ec681f3Smrg } 7457ec681f3Smrg } 7467ec681f3Smrg 7477ec681f3Smrg for (i = 0; (i < state->hdr->num_uniforms) && (state->sz > 0); i++) { 7487ec681f3Smrg state->uniforms[i] = next_sect(state, §_size); 7497ec681f3Smrg 7507ec681f3Smrg /* hmm, for a3xx (or maybe just newer driver version), we have some 7517ec681f3Smrg * extra sections that don't seem useful, so skip these: 7527ec681f3Smrg */ 7537ec681f3Smrg while (!valid_type(state->uniforms[i]->type_info)) { 7547ec681f3Smrg dump_hex_ascii(state->uniforms[i], sect_size, 0); 7557ec681f3Smrg state->uniforms[i] = next_sect(state, §_size); 7567ec681f3Smrg } 7577ec681f3Smrg 7587ec681f3Smrg if (is_uniform_v2(state->uniforms[i])) { 7597ec681f3Smrg clean_ascii(state->uniforms[i]->v2.name, sect_size - 53); 7607ec681f3Smrg } else { 7617ec681f3Smrg clean_ascii(state->uniforms[i]->v1.name, sect_size - 41); 7627ec681f3Smrg } 7637ec681f3Smrg 7647ec681f3Smrg if (full_dump) { 7657ec681f3Smrg printf("######## UNIFORM: (size %d)\n", sect_size); 7667ec681f3Smrg dump_uniform(state->uniforms[i]); 7677ec681f3Smrg dump_hex((char *)state->uniforms[i], sect_size); 7687ec681f3Smrg } 7697ec681f3Smrg } 7707ec681f3Smrg 7717ec681f3Smrg for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) { 7727ec681f3Smrg state->samplers[i] = next_sect(state, §_size); 7737ec681f3Smrg 7747ec681f3Smrg /* hmm, for a3xx (or maybe just newer driver version), we have some 7757ec681f3Smrg * extra sections that don't seem useful, so skip these: 7767ec681f3Smrg */ 7777ec681f3Smrg while (!valid_type(state->samplers[i]->type_info)) { 7787ec681f3Smrg dump_hex_ascii(state->samplers[i], sect_size, 0); 7797ec681f3Smrg state->samplers[i] = next_sect(state, §_size); 7807ec681f3Smrg } 7817ec681f3Smrg 7827ec681f3Smrg clean_ascii(state->samplers[i]->name, sect_size - 33); 7837ec681f3Smrg if (full_dump) { 7847ec681f3Smrg printf("######## SAMPLER: (size %d)\n", sect_size); 7857ec681f3Smrg dump_sampler(state->samplers[i]); 7867ec681f3Smrg dump_hex((char *)state->samplers[i], sect_size); 7877ec681f3Smrg } 7887ec681f3Smrg } 7897ec681f3Smrg 7907ec681f3Smrg // These sections show up after all of the other sampler sections 7917ec681f3Smrg // Loops through them all since we don't deal with them 7927ec681f3Smrg if (state->hdr->revision >= 7) { 7937ec681f3Smrg for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) { 7947ec681f3Smrg ptr = next_sect(state, §_size); 7957ec681f3Smrg dump_hex_ascii(ptr, sect_size, 0); 7967ec681f3Smrg } 7977ec681f3Smrg } 7987ec681f3Smrg 7997ec681f3Smrg for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) { 8007ec681f3Smrg state->varyings[i] = next_sect(state, §_size); 8017ec681f3Smrg 8027ec681f3Smrg /* hmm, for a3xx (or maybe just newer driver version), we have some 8037ec681f3Smrg * extra sections that don't seem useful, so skip these: 8047ec681f3Smrg */ 8057ec681f3Smrg while (!valid_type(state->varyings[i]->type_info)) { 8067ec681f3Smrg dump_hex_ascii(state->varyings[i], sect_size, 0); 8077ec681f3Smrg state->varyings[i] = next_sect(state, §_size); 8087ec681f3Smrg } 8097ec681f3Smrg 8107ec681f3Smrg clean_ascii(state->varyings[i]->name, sect_size - 16); 8117ec681f3Smrg if (full_dump) { 8127ec681f3Smrg printf("######## VARYING: (size %d)\n", sect_size); 8137ec681f3Smrg dump_varying(state->varyings[i]); 8147ec681f3Smrg dump_hex((char *)state->varyings[i], sect_size); 8157ec681f3Smrg } 8167ec681f3Smrg } 8177ec681f3Smrg 8187ec681f3Smrg /* show up again for revision >= 14?? */ 8197ec681f3Smrg if (state->hdr->revision >= 14) { 8207ec681f3Smrg for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) { 8217ec681f3Smrg ptr = next_sect(state, §_size); 8227ec681f3Smrg dump_hex_ascii(ptr, sect_size, 0); 8237ec681f3Smrg } 8247ec681f3Smrg } 8257ec681f3Smrg 8267ec681f3Smrg /* not sure exactly which revision started this, but seems at least 8277ec681f3Smrg * rev7 and rev8 implicitly include a new section for gl_FragColor: 8287ec681f3Smrg */ 8297ec681f3Smrg if (state->hdr->revision >= 7) { 8307ec681f3Smrg /* I guess only one? */ 8317ec681f3Smrg state->outputs[0] = next_sect(state, §_size); 8327ec681f3Smrg 8337ec681f3Smrg clean_ascii(state->outputs[0]->name, sect_size - 32); 8347ec681f3Smrg if (full_dump) { 8357ec681f3Smrg printf("######## OUTPUT: (size %d)\n", sect_size); 8367ec681f3Smrg dump_output(state->outputs[0]); 8377ec681f3Smrg dump_hex((char *)state->outputs[0], sect_size); 8387ec681f3Smrg } 8397ec681f3Smrg } 8407ec681f3Smrg 8417ec681f3Smrg for (i = 0; (i < state->hdr->num_uniformblocks) && (state->sz > 0); i++) { 8427ec681f3Smrg state->uniformblocks[i].header = next_sect(state, §_size); 8437ec681f3Smrg 8447ec681f3Smrg clean_ascii(state->uniformblocks[i].header->name, sect_size - 40); 8457ec681f3Smrg if (full_dump) { 8467ec681f3Smrg printf("######## UNIFORM BLOCK: (size %d)\n", sect_size); 8477ec681f3Smrg dump_uniformblock(state->uniformblocks[i].header); 8487ec681f3Smrg dump_hex((char *)state->uniformblocks[i].header, sect_size); 8497ec681f3Smrg } 8507ec681f3Smrg 8517ec681f3Smrg /* 8527ec681f3Smrg * OpenGL ES 3.0 spec mandates a minimum amount of 16K members supported 8537ec681f3Smrg * a330 supports a minimum of 65K 8547ec681f3Smrg */ 8557ec681f3Smrg state->uniformblocks[i].members = 8567ec681f3Smrg malloc(state->uniformblocks[i].header->num_members * sizeof(void *)); 8577ec681f3Smrg 8587ec681f3Smrg int member = 0; 8597ec681f3Smrg for (member = 0; (member < state->uniformblocks[i].header->num_members) && 8607ec681f3Smrg (state->sz > 0); 8617ec681f3Smrg member++) { 8627ec681f3Smrg state->uniformblocks[i].members[member] = next_sect(state, §_size); 8637ec681f3Smrg 8647ec681f3Smrg clean_ascii(state->uniformblocks[i].members[member]->name, 8657ec681f3Smrg sect_size - 56); 8667ec681f3Smrg if (full_dump) { 8677ec681f3Smrg printf("######## UNIFORM BLOCK MEMBER: (size %d)\n", sect_size); 8687ec681f3Smrg dump_uniformblockmember(state->uniformblocks[i].members[member]); 8697ec681f3Smrg dump_hex((char *)state->uniformblocks[i].members[member], 8707ec681f3Smrg sect_size); 8717ec681f3Smrg } 8727ec681f3Smrg } 8737ec681f3Smrg /* 8747ec681f3Smrg * Qualcomm saves the UBO members twice for each UBO 8757ec681f3Smrg * Don't ask me why 8767ec681f3Smrg */ 8777ec681f3Smrg for (member = 0; (member < state->uniformblocks[i].header->num_members) && 8787ec681f3Smrg (state->sz > 0); 8797ec681f3Smrg member++) { 8807ec681f3Smrg state->uniformblocks[i].members[member] = next_sect(state, §_size); 8817ec681f3Smrg 8827ec681f3Smrg clean_ascii(state->uniformblocks[i].members[member]->name, 8837ec681f3Smrg sect_size - 56); 8847ec681f3Smrg if (full_dump) { 8857ec681f3Smrg printf("######## UNIFORM BLOCK MEMBER2: (size %d)\n", sect_size); 8867ec681f3Smrg dump_uniformblockmember(state->uniformblocks[i].members[member]); 8877ec681f3Smrg dump_hex((char *)state->uniformblocks[i].members[member], 8887ec681f3Smrg sect_size); 8897ec681f3Smrg } 8907ec681f3Smrg } 8917ec681f3Smrg } 8927ec681f3Smrg 8937ec681f3Smrg if (gpu_id >= 300) { 8947ec681f3Smrg dump_shaders_a3xx(state); 8957ec681f3Smrg } else { 8967ec681f3Smrg dump_shaders_a2xx(state); 8977ec681f3Smrg } 8987ec681f3Smrg 8997ec681f3Smrg if (!full_dump) 9007ec681f3Smrg return; 9017ec681f3Smrg 9027ec681f3Smrg /* dump ascii version of shader program: */ 9037ec681f3Smrg ptr = next_sect(state, §_size); 9047ec681f3Smrg printf("\n#######################################################\n"); 9057ec681f3Smrg printf("######## SHADER SRC: (size=%d)\n", sect_size); 9067ec681f3Smrg dump_ascii(ptr, sect_size); 9077ec681f3Smrg free(ptr); 9087ec681f3Smrg 9097ec681f3Smrg /* dump remaining sections (there shouldn't be any): */ 9107ec681f3Smrg while (state->sz > 0) { 9117ec681f3Smrg ptr = next_sect(state, §_size); 9127ec681f3Smrg printf("######## section (size=%d)\n", sect_size); 9137ec681f3Smrg printf("as hex:\n"); 9147ec681f3Smrg dump_hex(ptr, sect_size); 9157ec681f3Smrg printf("as float:\n"); 9167ec681f3Smrg dump_float(ptr, sect_size); 9177ec681f3Smrg printf("as ascii:\n"); 9187ec681f3Smrg dump_ascii(ptr, sect_size); 9197ec681f3Smrg free(ptr); 9207ec681f3Smrg } 9217ec681f3Smrg /* cleanup the uniform buffer members we allocated */ 9227ec681f3Smrg if (state->hdr->num_uniformblocks > 0) 9237ec681f3Smrg free(state->uniformblocks[i].members); 9247ec681f3Smrg} 9257ec681f3Smrg 9267ec681f3Smrgint 9277ec681f3Smrgmain(int argc, char **argv) 9287ec681f3Smrg{ 9297ec681f3Smrg enum rd_sect_type type = RD_NONE; 9307ec681f3Smrg enum debug_t debug = PRINT_RAW | PRINT_STATS; 9317ec681f3Smrg void *buf = NULL; 9327ec681f3Smrg int sz; 9337ec681f3Smrg struct io *io; 9347ec681f3Smrg int raw_program = 0; 9357ec681f3Smrg 9367ec681f3Smrg /* lame argument parsing: */ 9377ec681f3Smrg 9387ec681f3Smrg while (1) { 9397ec681f3Smrg if ((argc > 1) && !strcmp(argv[1], "--verbose")) { 9407ec681f3Smrg debug |= PRINT_RAW | PRINT_VERBOSE; 9417ec681f3Smrg argv++; 9427ec681f3Smrg argc--; 9437ec681f3Smrg continue; 9447ec681f3Smrg } 9457ec681f3Smrg if ((argc > 1) && !strcmp(argv[1], "--expand")) { 9467ec681f3Smrg debug |= EXPAND_REPEAT; 9477ec681f3Smrg argv++; 9487ec681f3Smrg argc--; 9497ec681f3Smrg continue; 9507ec681f3Smrg } 9517ec681f3Smrg if ((argc > 1) && !strcmp(argv[1], "--short")) { 9527ec681f3Smrg /* only short dump, original shader, symbol table, and disassembly */ 9537ec681f3Smrg full_dump = 0; 9547ec681f3Smrg argv++; 9557ec681f3Smrg argc--; 9567ec681f3Smrg continue; 9577ec681f3Smrg } 9587ec681f3Smrg if ((argc > 1) && !strcmp(argv[1], "--dump-shaders")) { 9597ec681f3Smrg dump_shaders = 1; 9607ec681f3Smrg argv++; 9617ec681f3Smrg argc--; 9627ec681f3Smrg continue; 9637ec681f3Smrg } 9647ec681f3Smrg if ((argc > 1) && !strcmp(argv[1], "--raw")) { 9657ec681f3Smrg raw_program = 1; 9667ec681f3Smrg argv++; 9677ec681f3Smrg argc--; 9687ec681f3Smrg continue; 9697ec681f3Smrg } 9707ec681f3Smrg if ((argc > 1) && !strcmp(argv[1], "--gpu300")) { 9717ec681f3Smrg gpu_id = 320; 9727ec681f3Smrg argv++; 9737ec681f3Smrg argc--; 9747ec681f3Smrg continue; 9757ec681f3Smrg } 9767ec681f3Smrg break; 9777ec681f3Smrg } 9787ec681f3Smrg 9797ec681f3Smrg if (argc != 2) { 9807ec681f3Smrg fprintf( 9817ec681f3Smrg stderr, 9827ec681f3Smrg "usage: pgmdump [--verbose] [--short] [--dump-shaders] testlog.rd\n"); 9837ec681f3Smrg return -1; 9847ec681f3Smrg } 9857ec681f3Smrg 9867ec681f3Smrg disasm_a2xx_set_debug(debug); 9877ec681f3Smrg disasm_a3xx_set_debug(debug); 9887ec681f3Smrg 9897ec681f3Smrg infile = argv[1]; 9907ec681f3Smrg 9917ec681f3Smrg io = io_open(infile); 9927ec681f3Smrg if (!io) { 9937ec681f3Smrg fprintf(stderr, "could not open: %s\n", infile); 9947ec681f3Smrg return -1; 9957ec681f3Smrg } 9967ec681f3Smrg 9977ec681f3Smrg if (raw_program) { 9987ec681f3Smrg io_readn(io, &sz, 4); 9997ec681f3Smrg free(buf); 10007ec681f3Smrg 10017ec681f3Smrg /* note: allow hex dumps to go a bit past the end of the buffer.. 10027ec681f3Smrg * might see some garbage, but better than missing the last few bytes.. 10037ec681f3Smrg */ 10047ec681f3Smrg buf = calloc(1, sz + 3); 10057ec681f3Smrg io_readn(io, buf + 4, sz); 10067ec681f3Smrg (*(int *)buf) = sz; 10077ec681f3Smrg 10087ec681f3Smrg struct state state = { 10097ec681f3Smrg .buf = buf, 10107ec681f3Smrg .sz = sz, 10117ec681f3Smrg }; 10127ec681f3Smrg printf("############################################################\n"); 10137ec681f3Smrg printf("program:\n"); 10147ec681f3Smrg dump_program(&state); 10157ec681f3Smrg printf("############################################################\n"); 10167ec681f3Smrg return 0; 10177ec681f3Smrg } 10187ec681f3Smrg 10197ec681f3Smrg /* figure out what sort of input we are dealing with: */ 10207ec681f3Smrg if (!(check_extension(infile, ".rd") || check_extension(infile, ".rd.gz"))) { 10217ec681f3Smrg gl_shader_stage shader = ~0; 10227ec681f3Smrg int ret; 10237ec681f3Smrg if (check_extension(infile, ".vo")) { 10247ec681f3Smrg shader = MESA_SHADER_VERTEX; 10257ec681f3Smrg } else if (check_extension(infile, ".fo")) { 10267ec681f3Smrg shader = MESA_SHADER_FRAGMENT; 10277ec681f3Smrg } else if (check_extension(infile, ".vo3")) { 10287ec681f3Smrg } else if (check_extension(infile, ".fo3")) { 10297ec681f3Smrg } else if (check_extension(infile, ".co3")) { 10307ec681f3Smrg } else { 10317ec681f3Smrg fprintf(stderr, "invalid input file: %s\n", infile); 10327ec681f3Smrg return -1; 10337ec681f3Smrg } 10347ec681f3Smrg buf = calloc(1, 100 * 1024); 10357ec681f3Smrg ret = io_readn(io, buf, 100 * 1024); 10367ec681f3Smrg if (ret < 0) { 10377ec681f3Smrg fprintf(stderr, "error: %m"); 10387ec681f3Smrg return -1; 10397ec681f3Smrg } 10407ec681f3Smrg if (shader != ~0) { 10417ec681f3Smrg return disasm_a2xx(buf, ret / 4, 0, shader); 10427ec681f3Smrg } else { 10437ec681f3Smrg /* disassembly does not depend on shader stage on a3xx+: */ 10447ec681f3Smrg return disasm_a3xx(buf, ret / 4, 0, stdout, gpu_id); 10457ec681f3Smrg } 10467ec681f3Smrg } 10477ec681f3Smrg 10487ec681f3Smrg while ((io_readn(io, &type, sizeof(type)) > 0) && 10497ec681f3Smrg (io_readn(io, &sz, 4) > 0)) { 10507ec681f3Smrg free(buf); 10517ec681f3Smrg 10527ec681f3Smrg /* note: allow hex dumps to go a bit past the end of the buffer.. 10537ec681f3Smrg * might see some garbage, but better than missing the last few bytes.. 10547ec681f3Smrg */ 10557ec681f3Smrg buf = calloc(1, sz + 3); 10567ec681f3Smrg io_readn(io, buf, sz); 10577ec681f3Smrg 10587ec681f3Smrg switch (type) { 10597ec681f3Smrg case RD_TEST: 10607ec681f3Smrg if (full_dump) 10617ec681f3Smrg printf("test: %s\n", (char *)buf); 10627ec681f3Smrg break; 10637ec681f3Smrg case RD_VERT_SHADER: 10647ec681f3Smrg printf("vertex shader:\n%s\n", (char *)buf); 10657ec681f3Smrg break; 10667ec681f3Smrg case RD_FRAG_SHADER: 10677ec681f3Smrg printf("fragment shader:\n%s\n", (char *)buf); 10687ec681f3Smrg break; 10697ec681f3Smrg case RD_PROGRAM: { 10707ec681f3Smrg struct state state = { 10717ec681f3Smrg .buf = buf, 10727ec681f3Smrg .sz = sz, 10737ec681f3Smrg }; 10747ec681f3Smrg printf( 10757ec681f3Smrg "############################################################\n"); 10767ec681f3Smrg printf("program:\n"); 10777ec681f3Smrg dump_program(&state); 10787ec681f3Smrg printf( 10797ec681f3Smrg "############################################################\n"); 10807ec681f3Smrg break; 10817ec681f3Smrg } 10827ec681f3Smrg case RD_GPU_ID: 10837ec681f3Smrg gpu_id = *((unsigned int *)buf); 10847ec681f3Smrg printf("gpu_id: %d\n", gpu_id); 10857ec681f3Smrg break; 10867ec681f3Smrg default: 10877ec681f3Smrg break; 10887ec681f3Smrg } 10897ec681f3Smrg } 10907ec681f3Smrg 10917ec681f3Smrg io_close(io); 10927ec681f3Smrg 10937ec681f3Smrg return 0; 10947ec681f3Smrg} 1095