2 * Copyright © 2020 Google, Inc.
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
30 #include "util/u_math.h"
32 #include "perfcntrs/freedreno_perfcntr.h"
38 dump_float(void *buf
, int sz
)
40 uint8_t *ptr
= (uint8_t *)buf
;
41 uint8_t *end
= ptr
+ sz
- 3;
47 printf((i
% 8) ? " " : "\t");
54 printf("%8f", uif(d
));
69 dump_hex(void *buf
, int sz
)
71 uint8_t *ptr
= (uint8_t *)buf
;
72 uint8_t *end
= ptr
+ sz
;
78 printf((i
% 8) ? " " : "\t");
99 static const char *shortopts
= "df:g:hp:";
101 static const struct option longopts
[] = {
102 {"disasm", no_argument
, 0, 'd'},
103 {"file", required_argument
, 0, 'f'},
104 {"groups", required_argument
, 0, 'g'},
105 {"help", no_argument
, 0, 'h'},
106 {"perfcntr", required_argument
, 0, 'p'},
111 usage(const char *name
)
113 printf("Usage: %s [-dfgh]\n"
116 " -d, --disasm print disassembled shader\n"
117 " -f, --file=FILE read shader from file (instead of stdin)\n"
118 " -g, --groups=X,Y,Z use specified group size\n"
119 " -h, --help show this message\n"
120 " -p, --perfcntr=LIST sample specified performance counters (comma\n"
126 /* performance counter description: */
127 static unsigned num_groups
;
128 static const struct fd_perfcntr_group
*groups
;
130 /* Track enabled counters per group: */
131 static unsigned *enabled_counters
;
134 setup_counter(const char *name
, struct perfcntr
*c
)
136 for (int i
= 0; i
< num_groups
; i
++) {
137 const struct fd_perfcntr_group
*group
= &groups
[i
];
139 for (int j
= 0; j
< group
->num_countables
; j
++) {
140 const struct fd_perfcntr_countable
*countable
= &group
->countables
[j
];
142 if (strcmp(name
, countable
->name
) != 0)
146 * Allocate a counter to use to monitor the requested countable:
148 if (enabled_counters
[i
] >= group
->num_counters
) {
149 errx(-1, "Too many counters selected in group: %s", group
->name
);
152 unsigned idx
= enabled_counters
[i
]++;
153 const struct fd_perfcntr_counter
*counter
= &group
->counters
[idx
];
156 * And initialize the perfcntr struct, pulling together the info
157 * about selected counter and countable, to simplify life for the
161 c
->select_reg
= counter
->select_reg
;
162 c
->counter_reg_lo
= counter
->counter_reg_lo
;
163 c
->counter_reg_hi
= counter
->counter_reg_hi
;
164 c
->selector
= countable
->selector
;
170 errx(-1, "could not find countable: %s", name
);
173 static struct perfcntr
*
174 parse_perfcntrs(uint32_t gpu_id
, const char *perfcntrstr
, unsigned *num_perfcntrs
)
176 struct perfcntr
*counters
= NULL
;
180 groups
= fd_perfcntrs(gpu_id
, &num_groups
);
181 enabled_counters
= calloc(num_groups
, sizeof(enabled_counters
[0]));
183 cnames
= strdup(perfcntrstr
);
184 while ((s
= strstr(cnames
, ","))) {
189 counters
= realloc(counters
, ++cnt
* sizeof(counters
[0]));
190 setup_counter(name
, &counters
[cnt
-1]);
193 char * name
= cnames
;
194 counters
= realloc(counters
, ++cnt
* sizeof(counters
[0]));
195 setup_counter(name
, &counters
[cnt
-1]);
197 *num_perfcntrs
= cnt
;
203 main(int argc
, char **argv
)
206 const char *perfcntrstr
= NULL
;
207 struct perfcntr
*perfcntrs
= NULL
;
208 unsigned num_perfcntrs
= 0;
210 uint32_t grid
[3] = {0};
213 setlocale(LC_NUMERIC
, "en_US.UTF-8");
215 while ((opt
= getopt_long_only(argc
, argv
, shortopts
, longopts
, NULL
)) != -1) {
221 in
= fopen(optarg
, "r");
223 err(1, "could not open '%s'", optarg
);
226 ret
= sscanf(optarg
, "%u,%u,%u", &grid
[0], &grid
[1], &grid
[2]);
233 perfcntrstr
= optarg
;
236 printf("unrecognized arg: %c\n", opt
);
241 int fd
= drmOpen("msm", NULL
);
243 err(1, "could not open drm device");
245 struct fd_device
*dev
= fd_device_new(fd
);
246 struct fd_pipe
*pipe
= fd_pipe_new(dev
, FD_PIPE_3D
);
249 fd_pipe_get_param(pipe
, FD_GPU_ID
, &val
);
250 uint32_t gpu_id
= val
;
252 printf("got gpu_id: %u\n", gpu_id
);
254 struct backend
*backend
;
257 backend
= a6xx_init(dev
, gpu_id
);
260 err(1, "unsupported gpu: a%u", gpu_id
);
263 struct kernel
*kernel
= backend
->assemble(backend
, in
);
264 printf("localsize: %dx%dx%d\n", kernel
->local_size
[0],
265 kernel
->local_size
[1], kernel
->local_size
[2]);
266 for (int i
= 0; i
< kernel
->num_bufs
; i
++) {
267 printf("buf[%d]: size=%u\n", i
, kernel
->buf_sizes
[i
]);
268 kernel
->bufs
[i
] = fd_bo_new(dev
, kernel
->buf_sizes
[i
] * 4,
269 DRM_FREEDRENO_GEM_TYPE_KMEM
, "buf[%d]", i
);
273 backend
->disassemble(kernel
, stdout
);
278 struct fd_submit
*submit
= fd_submit_new(pipe
);
281 if (!backend
->set_perfcntrs
) {
282 err(1, "performance counters not supported");
284 perfcntrs
= parse_perfcntrs(gpu_id
, perfcntrstr
, &num_perfcntrs
);
285 backend
->set_perfcntrs(backend
, perfcntrs
, num_perfcntrs
);
288 backend
->emit_grid(kernel
, grid
, submit
);
290 fd_submit_flush(submit
, -1, NULL
, NULL
);
292 for (int i
= 0; i
< kernel
->num_bufs
; i
++) {
293 fd_bo_cpu_prep(kernel
->bufs
[i
], pipe
, DRM_FREEDRENO_PREP_READ
);
294 void *map
= fd_bo_map(kernel
->bufs
[i
]);
296 printf("buf[%d]:\n", i
);
297 dump_hex(map
, kernel
->buf_sizes
[i
] * 4);
298 dump_float(map
, kernel
->buf_sizes
[i
] * 4);
302 uint64_t results
[num_perfcntrs
];
303 backend
->read_perfcntrs(backend
, results
);
305 for (unsigned i
= 0; i
< num_perfcntrs
; i
++) {
306 printf("%s:\t%'"PRIu64
"\n", perfcntrs
[i
].name
, results
[i
]);