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
;
61 static const char *exename
;
63 static int handle_file(const char *filename
, int start
, int end
, int draw
);
65 static void print_usage(const char *name
)
67 fprintf(stderr
, "Usage:\n\n"
68 "\t%s [OPTSIONS]... FILE...\n\n"
70 "\t-v, --verbose - more verbose disassembly\n"
71 "\t--dump-shaders - dump each shader to a raw file\n"
72 "\t--no-color - disable colorized output (default for non-console\n"
74 "\t--color - enable colorized output (default for tty output)\n"
75 "\t--no-pager - disable pager (default for non-console output)\n"
76 "\t--pager - enable pager (default for tty output)\n"
77 "\t-s, --summary - don't show individual register writes, but just\n"
78 "\t register values on draws\n"
79 "\t-a, --allregs - show all registers (including ones not written\n"
80 "\t since previous draw) on each draw\n"
81 "\t-S, --start=N - start decoding from frame N\n"
82 "\t-E, --end=N - stop decoding after frame N\n"
83 "\t-F, --frame=N - decode only frame N\n"
84 "\t-D, --draw=N - decode only draw N\n"
85 "\t-e, --exe=NAME - only decode cmdstream from named process\n"
86 "\t--textures - dump texture contents (if possible)\n"
87 "\t-L, --script=LUA - run specified lua script to analyze state\n"
88 "\t-q, --query=REG - query mode, dump only specified query registers on\n"
89 "\t each draw; multiple --query/-q args can be given to\n"
90 "\t dump multiple registers; register can be specified\n"
91 "\t either by name or numeric offset\n"
92 "\t--query-all - in query mode, show all queried regs on each draw\n"
93 "\t (default query mode)\n"
94 "\t--query-written - in query mode, show queried regs on draws if any of\n"
95 "\t them have been written since previous draw\n"
96 "\t--query-delta - in query mode, show queried regs on draws if any of\n"
97 "\t them have changed since previous draw\n"
98 "\t--query-compare - dump registers for BINNING vs GMEM/BYPASS per draw;\n"
99 "\t only applicable for regs set via SDS group (a6xx+),\n"
100 "\t implies --once, can be combined with --query-all,\n"
101 "\t --query-written, or --query-delta\n"
102 "\t--once - decode cmdstream only once (per draw mode); if same\n"
103 "\t cmdstream is executed for each tile, this will decode\n"
104 "\t it only for the first tile and skip the remainder,\n"
105 "\t which can be useful when looking at state that does\n"
106 "\t not change per tile\n"
107 "\t--not-once - decode cmdstream for each IB (default)\n"
108 "\t-h, --help - show this message\n"
113 static const struct option opts
[] = {
114 /* Long opts that simply set a flag (no corresponding short alias: */
115 { "dump-shaders", no_argument
, &options
.dump_shaders
, 1 },
116 { "no-color", no_argument
, &options
.color
, 0 },
117 { "color", no_argument
, &options
.color
, 1 },
118 { "no-pager", no_argument
, &interactive
, 0 },
119 { "pager", no_argument
, &interactive
, 1 },
120 { "textures", no_argument
, &options
.dump_textures
, 1 },
121 { "show-compositor", no_argument
, &show_comp
, 1 },
122 { "query-all", no_argument
, &options
.query_mode
, QUERY_ALL
},
123 { "query-written", no_argument
, &options
.query_mode
, QUERY_WRITTEN
},
124 { "query-delta", no_argument
, &options
.query_mode
, QUERY_DELTA
},
125 { "query-compare", no_argument
, &options
.query_compare
, 1 },
126 { "once", no_argument
, &options
.once
, 1 },
127 { "not-once", no_argument
, &options
.once
, 0 },
129 /* Long opts with short alias: */
130 { "verbose", no_argument
, 0, 'v' },
131 { "summary", no_argument
, 0, 's' },
132 { "allregs", no_argument
, 0, 'a' },
133 { "start", required_argument
, 0, 'S' },
134 { "end", required_argument
, 0, 'E' },
135 { "frame", required_argument
, 0, 'F' },
136 { "draw", required_argument
, 0, 'D' },
137 { "exe", required_argument
, 0, 'e' },
138 { "script", required_argument
, 0, 'L' },
139 { "query", required_argument
, 0, 'q' },
140 { "help", no_argument
, 0, 'h' },
143 int main(int argc
, char **argv
)
145 enum debug_t debug
= PRINT_RAW
| PRINT_STATS
;
147 int start
= 0, end
= 0x7ffffff, draw
= -1;
150 interactive
= isatty(STDOUT_FILENO
);
152 options
.color
= interactive
;
154 while ((c
= getopt_long(argc
, argv
, "vsaS:E:F:D:e:L:q:h", opts
, NULL
)) != -1) {
157 /* option that set a flag, nothing to do */
160 debug
|= (PRINT_RAW
| EXPAND_REPEAT
| PRINT_VERBOSE
);
163 options
.summary
= true;
166 options
.allregs
= true;
169 start
= atoi(optarg
);
175 start
= end
= atoi(optarg
);
184 options
.script
= optarg
;
185 if (script_load(options
.script
)) {
186 errx(-1, "error loading %s\n", options
.script
);
190 options
.querystrs
= realloc(options
.querystrs
,
191 (options
.nquery
+ 1) * sizeof(*options
.querystrs
));
192 options
.querystrs
[options
.nquery
] = optarg
;
198 print_usage(argv
[0]);
202 disasm_a2xx_set_debug(debug
);
203 disasm_a3xx_set_debug(debug
);
209 while (optind
< argc
) {
210 ret
= handle_file(argv
[optind
], start
, end
, draw
);
212 fprintf(stderr
, "error reading: %s\n", argv
[optind
]);
213 fprintf(stderr
, "continuing..\n");
219 print_usage(argv
[0]);
221 if ((options
.query_mode
|| options
.query_compare
) && !options
.nquery
) {
222 fprintf(stderr
, "query options only valid in query mode!\n");
223 print_usage(argv
[0]);
235 static void parse_addr(uint32_t *buf
, int sz
, unsigned int *len
, uint64_t *gpuaddr
)
240 *gpuaddr
|= ((uint64_t)(buf
[2])) << 32;
243 static int handle_file(const char *filename
, int start
, int end
, int draw
)
245 enum rd_sect_type type
= RD_NONE
;
248 int submit
= 0, got_gpu_id
= 0;
250 bool needs_reset
= false;
253 options
.draw_filter
= draw
;
255 cffdec_init(&options
);
257 printf("Reading %s...\n", filename
);
259 script_start_cmdstream(filename
);
261 if (!strcmp(filename
, "-"))
264 io
= io_open(filename
);
267 fprintf(stderr
, "could not open: %s\n", filename
);
279 ret
= io_readn(io
, arr
, 8);
283 while ((arr
[0] == 0xffffffff) && (arr
[1] == 0xffffffff)) {
284 ret
= io_readn(io
, arr
, 8);
301 buf
= malloc(sz
+ 1);
302 ((char *)buf
)[sz
] = '\0';
303 ret
= io_readn(io
, buf
, sz
);
309 printl(1, "test: %s\n", (char *)buf
);
313 printl(2, "cmd: %s\n", (char *)buf
);
316 skip
|= (strstr(buf
, exename
) != buf
);
317 } else if (!show_comp
) {
318 skip
|= (strstr(buf
, "fdperf") == buf
);
319 skip
|= (strstr(buf
, "chrome") == buf
);
320 skip
|= (strstr(buf
, "surfaceflinger") == buf
);
321 skip
|= ((char *)buf
)[0] == 'X';
325 printl(2, "vertex shader:\n%s\n", (char *)buf
);
328 printl(2, "fragment shader:\n%s\n", (char *)buf
);
335 parse_addr(buf
, sz
, &gpuaddr
.len
, &gpuaddr
.gpuaddr
);
337 case RD_BUFFER_CONTENTS
:
338 add_buffer(gpuaddr
.gpuaddr
, gpuaddr
.len
, buf
);
341 case RD_CMDSTREAM_ADDR
:
342 if ((start
<= submit
) && (submit
<= end
)) {
343 unsigned int sizedwords
;
345 parse_addr(buf
, sz
, &sizedwords
, &gpuaddr
);
346 printl(2, "############################################################\n");
347 printl(2, "cmdstream: %d dwords\n", sizedwords
);
349 script_start_submit();
350 dump_commands(hostptr(gpuaddr
), sizedwords
, 0);
353 printl(2, "############################################################\n");
354 printl(2, "vertices: %d\n", vertices
);
361 options
.gpu_id
= *((unsigned int *)buf
);
362 printl(2, "gpu_id: %d\n", options
.gpu_id
);
363 cffdec_init(&options
);
373 script_end_cmdstream();
379 printf("corrupt file\n");