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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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, &sect_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