2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Christian Gmeiner <christian.gmeiner@gmail.com>
28 #include "util/u_inlines.h"
29 #include "util/u_memory.h"
31 #include "etnaviv_context.h"
32 #include "etnaviv_query_pm.h"
33 #include "etnaviv_screen.h"
35 struct etna_perfmon_source
41 struct etna_perfmon_config
45 const struct etna_perfmon_source
*source
;
48 static const struct etna_perfmon_config query_config
[] = {
50 .name
= "hi-total-cyles",
51 .type
= ETNA_QUERY_HI_TOTAL_CYCLES
,
52 .source
= (const struct etna_perfmon_source
[]) {
53 { "HI", "TOTAL_CYCLES" }
57 .name
= "hi-idle-cyles",
58 .type
= ETNA_QUERY_HI_IDLE_CYCLES
,
59 .source
= (const struct etna_perfmon_source
[]) {
60 { "HI", "IDLE_CYCLES" }
64 .name
= "hi-axi-cycles-read-request-stalled",
65 .type
= ETNA_QUERY_HI_AXI_CYCLES_READ_REQUEST_STALLED
,
66 .source
= (const struct etna_perfmon_source
[]) {
67 { "HI", "AXI_CYCLES_READ_REQUEST_STALLED" }
71 .name
= "hi-axi-cycles-write-request-stalled",
72 .type
= ETNA_QUERY_HI_AXI_CYCLES_WRITE_REQUEST_STALLED
,
73 .source
= (const struct etna_perfmon_source
[]) {
74 { "HI", "AXI_CYCLES_WRITE_REQUEST_STALLED" }
78 .name
= "hi-axi-cycles-write-data-stalled",
79 .type
= ETNA_QUERY_HI_AXI_CYCLES_WRITE_DATA_STALLED
,
80 .source
= (const struct etna_perfmon_source
[]) {
81 { "HI", "AXI_CYCLES_WRITE_DATA_STALLED" }
85 .name
= "pe-pixel-count-killed-by-color-pipe",
86 .type
= ETNA_QUERY_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE
,
87 .source
= (const struct etna_perfmon_source
[]) {
88 { "PE", "PIXEL_COUNT_KILLED_BY_COLOR_PIPE" }
92 .name
= "pe-pixel-count-killed-by-depth-pipe",
93 .type
= ETNA_QUERY_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE
,
94 .source
= (const struct etna_perfmon_source
[]) {
95 { "PE", "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE" }
99 .name
= "pe-pixel-count-drawn-by-color-pipe",
100 .type
= ETNA_QUERY_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE
,
101 .source
= (const struct etna_perfmon_source
[]) {
102 { "PE", "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE" }
106 .name
= "pe-pixel-count-drawn-by-depth-pipe",
107 .type
= ETNA_QUERY_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE
,
108 .source
= (const struct etna_perfmon_source
[]) {
109 { "PE", "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE" }
113 .name
= "sh-shader-cycles",
114 .type
= ETNA_QUERY_SH_SHADER_CYCLES
,
115 .source
= (const struct etna_perfmon_source
[]) {
116 { "SH", "SHADER_CYCLES" }
120 .name
= "sh-ps-inst-counter",
121 .type
= ETNA_QUERY_SH_PS_INST_COUNTER
,
122 .source
= (const struct etna_perfmon_source
[]) {
123 { "SH", "PS_INST_COUNTER" }
127 .name
= "sh-rendered-pixel-counter",
128 .type
= ETNA_QUERY_SH_RENDERED_PIXEL_COUNTER
,
129 .source
= (const struct etna_perfmon_source
[]) {
130 { "SH", "RENDERED_PIXEL_COUNTER" }
134 .name
= "sh-vs-inst-counter",
135 .type
= ETNA_QUERY_SH_VS_INST_COUNTER
,
136 .source
= (const struct etna_perfmon_source
[]) {
137 { "SH", "VS_INST_COUNTER" }
141 .name
= "sh-rendered-vertice-counter",
142 .type
= ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER
,
143 .source
= (const struct etna_perfmon_source
[]) {
144 { "SH", "RENDERED_VERTICE_COUNTER" }
148 .name
= "sh-vtx-branch-inst-counter",
149 .type
= ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER
,
150 .source
= (const struct etna_perfmon_source
[]) {
151 { "SH", "VTX_BRANCH_INST_COUNTER" }
155 .name
= "sh-vtx-texld-inst-counter",
156 .type
= ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER
,
157 .source
= (const struct etna_perfmon_source
[]) {
158 { "SH", "VTX_TEXLD_INST_COUNTER" }
162 .name
= "sh-plx-branch-inst-counter",
163 .type
= ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER
,
164 .source
= (const struct etna_perfmon_source
[]) {
165 { "SH", "PXL_BRANCH_INST_COUNTER" }
169 .name
= "sh-plx-texld-inst-counter",
170 .type
= ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER
,
171 .source
= (const struct etna_perfmon_source
[]) {
172 { "SH", "PXL_TEXLD_INST_COUNTER" }
176 .name
= "pa-input-vtx-counter",
177 .type
= ETNA_QUERY_PA_INPUT_VTX_COUNTER
,
178 .source
= (const struct etna_perfmon_source
[]) {
179 { "PA", "INPUT_VTX_COUNTER" }
183 .name
= "pa-input-prim-counter",
184 .type
= ETNA_QUERY_PA_INPUT_PRIM_COUNTER
,
185 .source
= (const struct etna_perfmon_source
[]) {
186 { "PA", "INPUT_PRIM_COUNTER" }
190 .name
= "pa-output-prim-counter",
191 .type
= ETNA_QUERY_PA_OUTPUT_PRIM_COUNTER
,
192 .source
= (const struct etna_perfmon_source
[]) {
193 { "PA", "OUTPUT_PRIM_COUNTER" }
197 .name
= "pa-depth-clipped-counter",
198 .type
= ETNA_QUERY_PA_DEPTH_CLIPPED_COUNTER
,
199 .source
= (const struct etna_perfmon_source
[]) {
200 { "PA", "DEPTH_CLIPPED_COUNTER" }
204 .name
= "pa-trivial-rejected-counter",
205 .type
= ETNA_QUERY_PA_TRIVIAL_REJECTED_COUNTER
,
206 .source
= (const struct etna_perfmon_source
[]) {
207 { "PA", "TRIVIAL_REJECTED_COUNTER" }
211 .name
= "pa-culled-counter",
212 .type
= ETNA_QUERY_PA_CULLED_COUNTER
,
213 .source
= (const struct etna_perfmon_source
[]) {
214 { "PA", "CULLED_COUNTER" }
218 .name
= "se-culled-triangle-count",
219 .type
= ETNA_QUERY_SE_CULLED_TRIANGLE_COUNT
,
220 .source
= (const struct etna_perfmon_source
[]) {
221 { "SE", "CULLED_TRIANGLE_COUNT" }
225 .name
= "se-culled-lines-count",
226 .type
= ETNA_QUERY_SE_CULLED_LINES_COUNT
,
227 .source
= (const struct etna_perfmon_source
[]) {
228 { "SE", "CULLED_LINES_COUNT" }
232 .name
= "ra-valid-pixel-count",
233 .type
= ETNA_QUERY_RA_VALID_PIXEL_COUNT
,
234 .source
= (const struct etna_perfmon_source
[]) {
235 { "RA", "VALID_PIXEL_COUNT" }
239 .name
= "ra-total-quad-count",
240 .type
= ETNA_QUERY_RA_TOTAL_QUAD_COUNT
,
241 .source
= (const struct etna_perfmon_source
[]) {
242 { "RA", "TOTAL_QUAD_COUNT" }
246 .name
= "ra-valid-quad-count-after-early-z",
247 .type
= ETNA_QUERY_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z
,
248 .source
= (const struct etna_perfmon_source
[]) {
249 { "RA", "VALID_QUAD_COUNT_AFTER_EARLY_Z" }
253 .name
= "ra-total-primitive-count",
254 .type
= ETNA_QUERY_RA_TOTAL_PRIMITIVE_COUNT
,
255 .source
= (const struct etna_perfmon_source
[]) {
256 { "RA", "TOTAL_PRIMITIVE_COUNT" }
260 .name
= "ra-pipe-cache-miss-counter",
261 .type
= ETNA_QUERY_RA_PIPE_CACHE_MISS_COUNTER
,
262 .source
= (const struct etna_perfmon_source
[]) {
263 { "RA", "PIPE_CACHE_MISS_COUNTER" }
267 .name
= "ra-prefetch-cache-miss-counter",
268 .type
= ETNA_QUERY_RA_PREFETCH_CACHE_MISS_COUNTER
,
269 .source
= (const struct etna_perfmon_source
[]) {
270 { "RA", "PREFETCH_CACHE_MISS_COUNTER" }
274 .name
= "ra-pculled-quad-count",
275 .type
= ETNA_QUERY_RA_CULLED_QUAD_COUNT
,
276 .source
= (const struct etna_perfmon_source
[]) {
277 { "RA", "CULLED_QUAD_COUNT" }
281 .name
= "tx-total-bilinear-requests",
282 .type
= ETNA_QUERY_TX_TOTAL_BILINEAR_REQUESTS
,
283 .source
= (const struct etna_perfmon_source
[]) {
284 { "TX", "TOTAL_BILINEAR_REQUESTS" }
288 .name
= "tx-total-trilinear-requests",
289 .type
= ETNA_QUERY_TX_TOTAL_TRILINEAR_REQUESTS
,
290 .source
= (const struct etna_perfmon_source
[]) {
291 { "TX", "TOTAL_TRILINEAR_REQUESTS" }
295 .name
= "tx-total-discarded-texture-requests",
296 .type
= ETNA_QUERY_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS
,
297 .source
= (const struct etna_perfmon_source
[]) {
298 { "TX", "TOTAL_DISCARDED_TEXTURE_REQUESTS" }
302 .name
= "tx-total-texture-requests",
303 .type
= ETNA_QUERY_TX_TOTAL_TEXTURE_REQUESTS
,
304 .source
= (const struct etna_perfmon_source
[]) {
305 { "TX", "TOTAL_TEXTURE_REQUESTS" }
309 .name
= "tx-mem-read-count",
310 .type
= ETNA_QUERY_TX_MEM_READ_COUNT
,
311 .source
= (const struct etna_perfmon_source
[]) {
312 { "TX", "MEM_READ_COUNT" }
316 .name
= "tx-mem-read-in-8b-count",
317 .type
= ETNA_QUERY_TX_MEM_READ_IN_8B_COUNT
,
318 .source
= (const struct etna_perfmon_source
[]) {
319 { "TX", "MEM_READ_IN_8B_COUNT" }
323 .name
= "tx-cache-miss-count",
324 .type
= ETNA_QUERY_TX_CACHE_MISS_COUNT
,
325 .source
= (const struct etna_perfmon_source
[]) {
326 { "TX", "CACHE_MISS_COUNT" }
330 .name
= "tx-cache-hit-texel-count",
331 .type
= ETNA_QUERY_TX_CACHE_HIT_TEXEL_COUNT
,
332 .source
= (const struct etna_perfmon_source
[]) {
333 { "TX", "CACHE_HIT_TEXEL_COUNT" }
337 .name
= "tx-cache-miss-texel-count",
338 .type
= ETNA_QUERY_TX_CACHE_MISS_TEXEL_COUNT
,
339 .source
= (const struct etna_perfmon_source
[]) {
340 { "TX", "CACHE_MISS_TEXEL_COUNT" }
344 .name
= "mc-total-read-req-8b-from-pipeline",
345 .type
= ETNA_QUERY_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE
,
346 .source
= (const struct etna_perfmon_source
[]) {
347 { "MC", "TOTAL_READ_REQ_8B_FROM_PIPELINE" }
351 .name
= "mc-total-read-req-8b-from-ip",
352 .type
= ETNA_QUERY_MC_TOTAL_READ_REQ_8B_FROM_IP
,
353 .source
= (const struct etna_perfmon_source
[]) {
354 { "MC", "TOTAL_READ_REQ_8B_FROM_IP" }
358 .name
= "mc-total-write-req-8b-from-pipeline",
359 .type
= ETNA_QUERY_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE
,
360 .source
= (const struct etna_perfmon_source
[]) {
361 { "MC", "TOTAL_WRITE_REQ_8B_FROM_PIPELINE" }
366 static const struct etna_perfmon_config
*
367 etna_pm_query_config(unsigned type
)
369 for (unsigned i
= 0; i
< ARRAY_SIZE(query_config
); i
++)
370 if (query_config
[i
].type
== type
)
371 return &query_config
[i
];
376 static struct etna_perfmon_signal
*
377 etna_pm_query_signal(struct etna_perfmon
*perfmon
,
378 const struct etna_perfmon_source
*source
)
380 struct etna_perfmon_domain
*domain
;
382 domain
= etna_perfmon_get_dom_by_name(perfmon
, source
->domain
);
386 return etna_perfmon_get_sig_by_name(domain
, source
->signal
);
390 etna_pm_cfg_supported(struct etna_perfmon
*perfmon
,
391 const struct etna_perfmon_config
*cfg
)
393 struct etna_perfmon_signal
*signal
= etna_pm_query_signal(perfmon
, cfg
->source
);
399 etna_pm_add_signal(struct etna_pm_query
*pq
, struct etna_perfmon
*perfmon
,
400 const struct etna_perfmon_config
*cfg
)
402 struct etna_perfmon_signal
*signal
= etna_pm_query_signal(perfmon
, cfg
->source
);
408 realloc_query_bo(struct etna_context
*ctx
, struct etna_pm_query
*pq
)
413 pq
->bo
= etna_bo_new(ctx
->screen
->dev
, 64, DRM_ETNA_GEM_CACHE_WC
);
414 if (unlikely(!pq
->bo
))
417 pq
->data
= etna_bo_map(pq
->bo
);
423 etna_pm_query_get(struct etna_cmd_stream
*stream
, struct etna_query
*q
,
426 struct etna_pm_query
*pq
= etna_pm_query(q
);
430 if (flags
== ETNA_PM_PROCESS_PRE
)
435 struct etna_perf p
= {
437 .sequence
= pq
->sequence
,
439 .signal
= pq
->signal
,
443 etna_cmd_stream_perf(stream
, &p
);
447 etna_pm_query_update(struct etna_query
*q
)
449 struct etna_pm_query
*pq
= etna_pm_query(q
);
451 if (pq
->data
[0] == pq
->sequence
)
456 etna_pm_destroy_query(struct etna_context
*ctx
, struct etna_query
*q
)
458 struct etna_pm_query
*pq
= etna_pm_query(q
);
465 etna_pm_begin_query(struct etna_context
*ctx
, struct etna_query
*q
)
467 struct etna_pm_query
*pq
= etna_pm_query(q
);
472 etna_pm_query_get(ctx
->stream
, q
, ETNA_PM_PROCESS_PRE
);
478 etna_pm_end_query(struct etna_context
*ctx
, struct etna_query
*q
)
480 etna_pm_query_get(ctx
->stream
, q
, ETNA_PM_PROCESS_POST
);
484 etna_pm_get_query_result(struct etna_context
*ctx
, struct etna_query
*q
,
485 boolean wait
, union pipe_query_result
*result
)
487 struct etna_pm_query
*pq
= etna_pm_query(q
);
489 etna_pm_query_update(q
);
495 if (!etna_bo_cpu_prep(pq
->bo
, DRM_ETNA_PREP_READ
))
499 etna_bo_cpu_fini(pq
->bo
);
502 result
->u32
= pq
->data
[2] - pq
->data
[1];
507 static const struct etna_query_funcs hw_query_funcs
= {
508 .destroy_query
= etna_pm_destroy_query
,
509 .begin_query
= etna_pm_begin_query
,
510 .end_query
= etna_pm_end_query
,
511 .get_query_result
= etna_pm_get_query_result
,
515 etna_pm_create_query(struct etna_context
*ctx
, unsigned query_type
)
517 struct etna_perfmon
*perfmon
= ctx
->screen
->perfmon
;
518 const struct etna_perfmon_config
*cfg
;
519 struct etna_pm_query
*pq
;
520 struct etna_query
*q
;
522 cfg
= etna_pm_query_config(query_type
);
526 if (!etna_pm_cfg_supported(perfmon
, cfg
))
529 pq
= CALLOC_STRUCT(etna_pm_query
);
533 if (!realloc_query_bo(ctx
, pq
)) {
539 q
->funcs
= &hw_query_funcs
;
540 q
->type
= query_type
;
542 etna_pm_add_signal(pq
, perfmon
, cfg
);
548 etna_pm_query_setup(struct etna_screen
*screen
)
550 screen
->perfmon
= etna_perfmon_create(screen
->pipe
);
552 if (!screen
->perfmon
)
555 for (unsigned i
= 0; i
< ARRAY_SIZE(query_config
); i
++) {
556 const struct etna_perfmon_config
*cfg
= &query_config
[i
];
558 if (!etna_pm_cfg_supported(screen
->perfmon
, cfg
))
561 util_dynarray_append(&screen
->supported_pm_queries
, unsigned, i
);
566 etna_pm_get_driver_query_info(struct pipe_screen
*pscreen
, unsigned index
,
567 struct pipe_driver_query_info
*info
)
569 const struct etna_screen
*screen
= etna_screen(pscreen
);
570 const unsigned num
= screen
->supported_pm_queries
.size
/ sizeof(unsigned);
579 i
= *util_dynarray_element(&screen
->supported_pm_queries
, unsigned, index
);
580 assert(i
< ARRAY_SIZE(query_config
));
582 info
->name
= query_config
[i
].name
;
583 info
->query_type
= query_config
[i
].type
;