2 * Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <sys/types.h>
52 static struct cffdec_options options
= {
56 static bool needs_wfi
= false;
57 static bool is_blob
= false;
58 static int show_comp
= false;
59 static int interactive
;
62 static int handle_file(const char *filename
, int start
, int end
, int draw
);
64 static void print_usage(const char *name
)
66 fprintf(stderr
, "Usage:\n\n"
67 "\t%s [OPTSIONS]... FILE...\n\n"
69 "\t-v, --verbose - more verbose disassembly\n"
70 "\t--dump-shaders - dump each shader to a raw file\n"
71 "\t--no-color - disable colorized output (default for non-console\n"
73 "\t--color - enable colorized output (default for tty output)\n"
74 "\t--no-pager - disable pager (default for non-console output)\n"
75 "\t--pager - enable pager (default for tty output)\n"
76 "\t-s, --summary - don't show individual register writes, but just\n"
77 "\t register values on draws\n"
78 "\t-a, --allregs - show all registers (including ones not written\n"
79 "\t since previous draw) on each draw\n"
80 "\t-S, --start=N - start decoding from frame N\n"
81 "\t-E, --end=N - stop decoding after frame N\n"
82 "\t-F, --frame=N - decode only frame N\n"
83 "\t-D, --draw=N - decode only draw N\n"
84 "\t--textures - dump texture contents (if possible)\n"
85 "\t-L, --script=LUA - run specified lua script to analyze state\n"
86 "\t-q, --query=REG - query mode, dump only specified query registers on\n"
87 "\t each draw; multiple --query/-q args can be given to\n"
88 "\t dump multiple registers; register can be specified\n"
89 "\t either by name or numeric offset\n"
90 "\t--query-all - in query mode, show all queried regs on each draw\n"
91 "\t (default query mode)\n"
92 "\t--query-written - in query mode, show queried regs on draws if any of\n"
93 "\t them have been written since previous draw\n"
94 "\t--query-delta - in query mode, show queried regs on draws if any of\n"
95 "\t them have changed since previous draw\n"
96 "\t--query-compare - dump registers for BINNING vs GMEM/BYPASS per draw;\n"
97 "\t only applicable for regs set via SDS group (a6xx+),\n"
98 "\t implies --once, can be combined with --query-all,\n"
99 "\t --query-written, or --query-delta\n"
100 "\t--once - decode cmdstream only once (per draw mode); if same\n"
101 "\t cmdstream is executed for each tile, this will decode\n"
102 "\t it only for the first tile and skip the remainder,\n"
103 "\t which can be useful when looking at state that does\n"
104 "\t not change per tile\n"
105 "\t--not-once - decode cmdstream for each IB (default)\n"
106 "\t-h, --help - show this message\n"
111 static const struct option opts
[] = {
112 /* Long opts that simply set a flag (no corresponding short alias: */
113 { "dump-shaders", no_argument
, &options
.dump_shaders
, 1 },
114 { "no-color", no_argument
, &options
.color
, 0 },
115 { "color", no_argument
, &options
.color
, 1 },
116 { "no-pager", no_argument
, &interactive
, 0 },
117 { "pager", no_argument
, &interactive
, 1 },
118 { "textures", no_argument
, &options
.dump_textures
, 1 },
119 { "show-compositor", no_argument
, &show_comp
, 1 },
120 { "query-all", no_argument
, &options
.query_mode
, QUERY_ALL
},
121 { "query-written", no_argument
, &options
.query_mode
, QUERY_WRITTEN
},
122 { "query-delta", no_argument
, &options
.query_mode
, QUERY_DELTA
},
123 { "query-compare", no_argument
, &options
.query_compare
, 1 },
124 { "once", no_argument
, &options
.once
, 1 },
125 { "not-once", no_argument
, &options
.once
, 0 },
127 /* Long opts with short alias: */
128 { "verbose", no_argument
, 0, 'v' },
129 { "summary", no_argument
, 0, 's' },
130 { "allregs", no_argument
, 0, 'a' },
131 { "start", required_argument
, 0, 'S' },
132 { "end", required_argument
, 0, 'E' },
133 { "frame", required_argument
, 0, 'F' },
134 { "draw", required_argument
, 0, 'D' },
135 { "script", required_argument
, 0, 'L' },
136 { "query", required_argument
, 0, 'q' },
137 { "help", no_argument
, 0, 'h' },
140 int main(int argc
, char **argv
)
142 enum debug_t debug
= PRINT_RAW
| PRINT_STATS
;
144 int start
= 0, end
= 0x7ffffff, draw
= -1;
147 interactive
= isatty(STDOUT_FILENO
);
149 options
.color
= interactive
;
151 while ((c
= getopt_long(argc
, argv
, "vsaS:E:F:D:L:q:h", opts
, NULL
)) != -1) {
154 /* option that set a flag, nothing to do */
157 debug
|= (PRINT_RAW
| EXPAND_REPEAT
| PRINT_VERBOSE
);
160 options
.summary
= true;
163 options
.allregs
= true;
166 start
= atoi(optarg
);
172 start
= end
= atoi(optarg
);
178 options
.script
= optarg
;
179 if (script_load(options
.script
)) {
180 errx(-1, "error loading %s\n", options
.script
);
184 options
.querystrs
= realloc(options
.querystrs
,
185 (options
.nquery
+ 1) * sizeof(*options
.querystrs
));
186 options
.querystrs
[options
.nquery
] = optarg
;
192 print_usage(argv
[0]);
196 disasm_a2xx_set_debug(debug
);
197 disasm_a3xx_set_debug(debug
);
203 while (optind
< argc
) {
204 ret
= handle_file(argv
[optind
], start
, end
, draw
);
206 fprintf(stderr
, "error reading: %s\n", argv
[optind
]);
207 fprintf(stderr
, "continuing..\n");
213 print_usage(argv
[0]);
215 if ((options
.query_mode
|| options
.query_compare
) && !options
.nquery
) {
216 fprintf(stderr
, "query options only valid in query mode!\n");
217 print_usage(argv
[0]);
229 static void parse_addr(uint32_t *buf
, int sz
, unsigned int *len
, uint64_t *gpuaddr
)
234 *gpuaddr
|= ((uint64_t)(buf
[2])) << 32;
237 static int handle_file(const char *filename
, int start
, int end
, int draw
)
239 enum rd_sect_type type
= RD_NONE
;
242 int submit
= 0, got_gpu_id
= 0;
244 bool needs_reset
= false;
247 options
.draw_filter
= draw
;
249 cffdec_init(&options
);
251 printf("Reading %s...\n", filename
);
253 script_start_cmdstream(filename
);
255 if (!strcmp(filename
, "-"))
258 io
= io_open(filename
);
261 fprintf(stderr
, "could not open: %s\n", filename
);
273 ret
= io_readn(io
, arr
, 8);
277 while ((arr
[0] == 0xffffffff) && (arr
[1] == 0xffffffff)) {
278 ret
= io_readn(io
, arr
, 8);
295 buf
= malloc(sz
+ 1);
296 ((char *)buf
)[sz
] = '\0';
297 ret
= io_readn(io
, buf
, sz
);
303 printl(1, "test: %s\n", (char *)buf
);
307 printl(2, "cmd: %s\n", (char *)buf
);
310 skip
|= (strstr(buf
, "fdperf") == buf
);
311 skip
|= (strstr(buf
, "chrome") == buf
);
312 skip
|= (strstr(buf
, "surfaceflinger") == buf
);
313 skip
|= ((char *)buf
)[0] == 'X';
317 printl(2, "vertex shader:\n%s\n", (char *)buf
);
320 printl(2, "fragment shader:\n%s\n", (char *)buf
);
327 parse_addr(buf
, sz
, &gpuaddr
.len
, &gpuaddr
.gpuaddr
);
329 case RD_BUFFER_CONTENTS
:
330 add_buffer(gpuaddr
.gpuaddr
, gpuaddr
.len
, buf
);
333 case RD_CMDSTREAM_ADDR
:
334 if ((start
<= submit
) && (submit
<= end
)) {
335 unsigned int sizedwords
;
337 parse_addr(buf
, sz
, &sizedwords
, &gpuaddr
);
338 printl(2, "############################################################\n");
339 printl(2, "cmdstream: %d dwords\n", sizedwords
);
341 script_start_submit();
342 dump_commands(hostptr(gpuaddr
), sizedwords
, 0);
345 printl(2, "############################################################\n");
346 printl(2, "vertices: %d\n", vertices
);
353 options
.gpu_id
= *((unsigned int *)buf
);
354 printl(2, "gpu_id: %d\n", options
.gpu_id
);
355 cffdec_init(&options
);
365 script_end_cmdstream();
371 printf("corrupt file\n");