1/*
2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
4 *
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:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
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.
23 *
24 * Authors:
25 *    Christian Gmeiner <christian.gmeiner@gmail.com>
26 */
27
28#include "etnaviv_context.h"
29#include "etnaviv_perfmon.h"
30#include "etnaviv_screen.h"
31
32static const char *group_names[] = {
33   [ETNA_QUERY_HI_GROUP_ID] = "HI",
34   [ETNA_QUERY_PE_GROUP_ID] = "PE",
35   [ETNA_QUERY_SH_GROUP_ID] = "SH",
36   [ETNA_QUERY_PA_GROUP_ID] = "PA",
37   [ETNA_QUERY_SE_GROUP_ID] = "SE",
38   [ETNA_QUERY_RA_GROUP_ID] = "RA",
39   [ETNA_QUERY_TX_GROUP_ID] = "TX",
40   [ETNA_QUERY_MC_GROUP_ID] = "MC",
41};
42
43static const struct etna_perfmon_config query_config[] = {
44   {
45      .name = "hi-total-cycles",
46      .type = ETNA_QUERY_HI_TOTAL_CYCLES,
47      .group_id = ETNA_QUERY_HI_GROUP_ID,
48      .source = (const struct etna_perfmon_source[]) {
49         { "HI", "TOTAL_CYCLES" }
50      }
51   },
52   {
53      .name = "hi-idle-cycles",
54      .type = ETNA_QUERY_HI_IDLE_CYCLES,
55      .group_id = ETNA_QUERY_HI_GROUP_ID,
56      .source = (const struct etna_perfmon_source[]) {
57         { "HI", "IDLE_CYCLES" }
58      }
59   },
60   {
61      .name = "hi-axi-cycles-read-request-stalled",
62      .type = ETNA_QUERY_HI_AXI_CYCLES_READ_REQUEST_STALLED,
63      .group_id = ETNA_QUERY_HI_GROUP_ID,
64      .source = (const struct etna_perfmon_source[]) {
65         { "HI", "AXI_CYCLES_READ_REQUEST_STALLED" }
66      }
67   },
68   {
69      .name = "hi-axi-cycles-write-request-stalled",
70      .type = ETNA_QUERY_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
71      .group_id = ETNA_QUERY_HI_GROUP_ID,
72      .source = (const struct etna_perfmon_source[]) {
73         { "HI", "AXI_CYCLES_WRITE_REQUEST_STALLED" }
74      }
75   },
76   {
77      .name = "hi-axi-cycles-write-data-stalled",
78      .type = ETNA_QUERY_HI_AXI_CYCLES_WRITE_DATA_STALLED,
79      .group_id = ETNA_QUERY_HI_GROUP_ID,
80      .source = (const struct etna_perfmon_source[]) {
81         { "HI", "AXI_CYCLES_WRITE_DATA_STALLED" }
82      }
83   },
84   {
85      .name = "pe-pixel-count-killed-by-color-pipe",
86      .type = ETNA_QUERY_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
87      .group_id = ETNA_QUERY_PE_GROUP_ID,
88      .source = (const struct etna_perfmon_source[]) {
89         { "PE", "PIXEL_COUNT_KILLED_BY_COLOR_PIPE" }
90      }
91   },
92   {
93      .name = "pe-pixel-count-killed-by-depth-pipe",
94      .type = ETNA_QUERY_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
95      .group_id = ETNA_QUERY_PE_GROUP_ID,
96      .source = (const struct etna_perfmon_source[]) {
97         { "PE", "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE" }
98      }
99   },
100   {
101      .name = "pe-pixel-count-drawn-by-color-pipe",
102      .type = ETNA_QUERY_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
103      .group_id = ETNA_QUERY_PE_GROUP_ID,
104      .source = (const struct etna_perfmon_source[]) {
105         { "PE", "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE" }
106      }
107   },
108   {
109      .name = "pe-pixel-count-drawn-by-depth-pipe",
110      .type = ETNA_QUERY_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
111      .group_id = ETNA_QUERY_PE_GROUP_ID,
112      .source = (const struct etna_perfmon_source[]) {
113         { "PE", "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE" }
114      }
115   },
116   {
117      .name = "sh-shader-cycles",
118      .type = ETNA_QUERY_SH_SHADER_CYCLES,
119      .group_id = ETNA_QUERY_SH_GROUP_ID,
120      .source = (const struct etna_perfmon_source[]) {
121         { "SH", "SHADER_CYCLES" }
122      }
123   },
124   {
125      .name = "sh-ps-inst-counter",
126      .type = ETNA_QUERY_SH_PS_INST_COUNTER,
127      .group_id = ETNA_QUERY_SH_GROUP_ID,
128      .source = (const struct etna_perfmon_source[]) {
129         { "SH", "PS_INST_COUNTER" }
130      }
131   },
132   {
133      .name = "sh-rendered-pixel-counter",
134      .type = ETNA_QUERY_SH_RENDERED_PIXEL_COUNTER,
135      .group_id = ETNA_QUERY_SH_GROUP_ID,
136      .source = (const struct etna_perfmon_source[]) {
137         { "SH", "RENDERED_PIXEL_COUNTER" }
138      }
139   },
140   {
141      .name = "sh-vs-inst-counter",
142      .type = ETNA_QUERY_SH_VS_INST_COUNTER,
143      .group_id = ETNA_QUERY_SH_GROUP_ID,
144      .source = (const struct etna_perfmon_source[]) {
145         { "SH", "VS_INST_COUNTER" }
146      }
147   },
148   {
149      .name = "sh-rendered-vertice-counter",
150      .type = ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER,
151      .group_id = ETNA_QUERY_SH_GROUP_ID,
152      .source = (const struct etna_perfmon_source[]) {
153         { "SH", "RENDERED_VERTICE_COUNTER" }
154      }
155   },
156   {
157      .name = "sh-vtx-branch-inst-counter",
158      .type = ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER,
159      .group_id = ETNA_QUERY_SH_GROUP_ID,
160      .source = (const struct etna_perfmon_source[]) {
161         { "SH", "VTX_BRANCH_INST_COUNTER" }
162      }
163   },
164   {
165      .name = "sh-vtx-texld-inst-counter",
166      .type = ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER,
167      .group_id = ETNA_QUERY_SH_GROUP_ID,
168      .source = (const struct etna_perfmon_source[]) {
169         { "SH", "VTX_TEXLD_INST_COUNTER" }
170      }
171   },
172   {
173      .name = "sh-plx-branch-inst-counter",
174      .type = ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER,
175      .group_id = ETNA_QUERY_SH_GROUP_ID,
176      .source = (const struct etna_perfmon_source[]) {
177         { "SH", "PXL_BRANCH_INST_COUNTER" }
178      }
179   },
180   {
181      .name = "sh-plx-texld-inst-counter",
182      .type = ETNA_QUERY_SH_RENDERED_VERTICE_COUNTER,
183      .group_id = ETNA_QUERY_SH_GROUP_ID,
184      .source = (const struct etna_perfmon_source[]) {
185         { "SH", "PXL_TEXLD_INST_COUNTER" }
186      }
187   },
188   {
189      .name = "pa-input-vtx-counter",
190      .type = ETNA_QUERY_PA_INPUT_VTX_COUNTER,
191      .group_id = ETNA_QUERY_PA_GROUP_ID,
192      .source = (const struct etna_perfmon_source[]) {
193         { "PA", "INPUT_VTX_COUNTER" }
194      }
195   },
196   {
197      .name = "pa-input-prim-counter",
198      .type = ETNA_QUERY_PA_INPUT_PRIM_COUNTER,
199      .group_id = ETNA_QUERY_PA_GROUP_ID,
200      .source = (const struct etna_perfmon_source[]) {
201         { "PA", "INPUT_PRIM_COUNTER" }
202      }
203   },
204   {
205      .name = "pa-output-prim-counter",
206      .type = ETNA_QUERY_PA_OUTPUT_PRIM_COUNTER,
207      .group_id = ETNA_QUERY_PA_GROUP_ID,
208      .source = (const struct etna_perfmon_source[]) {
209         { "PA", "OUTPUT_PRIM_COUNTER" }
210      }
211   },
212   {
213      .name = "pa-depth-clipped-counter",
214      .type = ETNA_QUERY_PA_DEPTH_CLIPPED_COUNTER,
215      .group_id = ETNA_QUERY_PA_GROUP_ID,
216      .source = (const struct etna_perfmon_source[]) {
217         { "PA", "DEPTH_CLIPPED_COUNTER" }
218      }
219   },
220   {
221      .name = "pa-trivial-rejected-counter",
222      .type = ETNA_QUERY_PA_TRIVIAL_REJECTED_COUNTER,
223      .group_id = ETNA_QUERY_PA_GROUP_ID,
224      .source = (const struct etna_perfmon_source[]) {
225         { "PA", "TRIVIAL_REJECTED_COUNTER" }
226      }
227   },
228   {
229      .name = "pa-culled-counter",
230      .type = ETNA_QUERY_PA_CULLED_COUNTER,
231      .group_id = ETNA_QUERY_PA_GROUP_ID,
232      .source = (const struct etna_perfmon_source[]) {
233         { "PA", "CULLED_COUNTER" }
234      }
235   },
236   {
237      .name = "se-culled-triangle-count",
238      .type = ETNA_QUERY_SE_CULLED_TRIANGLE_COUNT,
239      .group_id = ETNA_QUERY_SE_GROUP_ID,
240      .source = (const struct etna_perfmon_source[]) {
241         { "SE", "CULLED_TRIANGLE_COUNT" }
242      }
243   },
244   {
245      .name = "se-culled-lines-count",
246      .type = ETNA_QUERY_SE_CULLED_LINES_COUNT,
247      .group_id = ETNA_QUERY_SE_GROUP_ID,
248      .source = (const struct etna_perfmon_source[]) {
249         { "SE", "CULLED_LINES_COUNT" }
250      }
251   },
252   {
253      .name = "ra-valid-pixel-count",
254      .type = ETNA_QUERY_RA_VALID_PIXEL_COUNT,
255      .group_id = ETNA_QUERY_RA_GROUP_ID,
256      .source = (const struct etna_perfmon_source[]) {
257         { "RA", "VALID_PIXEL_COUNT" }
258      }
259   },
260   {
261      .name = "ra-total-quad-count",
262      .type = ETNA_QUERY_RA_TOTAL_QUAD_COUNT,
263      .group_id = ETNA_QUERY_RA_GROUP_ID,
264      .source = (const struct etna_perfmon_source[]) {
265         { "RA", "TOTAL_QUAD_COUNT" }
266      }
267   },
268   {
269      .name = "ra-valid-quad-count-after-early-z",
270      .type = ETNA_QUERY_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
271      .group_id = ETNA_QUERY_RA_GROUP_ID,
272      .source = (const struct etna_perfmon_source[]) {
273         { "RA", "VALID_QUAD_COUNT_AFTER_EARLY_Z" }
274      }
275   },
276   {
277      .name = "ra-total-primitive-count",
278      .type = ETNA_QUERY_RA_TOTAL_PRIMITIVE_COUNT,
279      .group_id = ETNA_QUERY_RA_GROUP_ID,
280      .source = (const struct etna_perfmon_source[]) {
281         { "RA", "TOTAL_PRIMITIVE_COUNT" }
282      }
283   },
284   {
285      .name = "ra-pipe-cache-miss-counter",
286      .type = ETNA_QUERY_RA_PIPE_CACHE_MISS_COUNTER,
287      .group_id = ETNA_QUERY_RA_GROUP_ID,
288      .source = (const struct etna_perfmon_source[]) {
289         { "RA", "PIPE_CACHE_MISS_COUNTER" }
290      }
291   },
292   {
293      .name = "ra-prefetch-cache-miss-counter",
294      .type = ETNA_QUERY_RA_PREFETCH_CACHE_MISS_COUNTER,
295      .group_id = ETNA_QUERY_RA_GROUP_ID,
296      .source = (const struct etna_perfmon_source[]) {
297         { "RA", "PREFETCH_CACHE_MISS_COUNTER" }
298      }
299   },
300   {
301      .name = "ra-pculled-quad-count",
302      .type = ETNA_QUERY_RA_CULLED_QUAD_COUNT,
303      .group_id = ETNA_QUERY_RA_GROUP_ID,
304      .source = (const struct etna_perfmon_source[]) {
305         { "RA", "CULLED_QUAD_COUNT" }
306      }
307   },
308   {
309      .name = "tx-total-bilinear-requests",
310      .type = ETNA_QUERY_TX_TOTAL_BILINEAR_REQUESTS,
311      .group_id = ETNA_QUERY_TX_GROUP_ID,
312      .source = (const struct etna_perfmon_source[]) {
313         { "TX", "TOTAL_BILINEAR_REQUESTS" }
314      }
315   },
316   {
317      .name = "tx-total-trilinear-requests",
318      .type = ETNA_QUERY_TX_TOTAL_TRILINEAR_REQUESTS,
319      .group_id = ETNA_QUERY_TX_GROUP_ID,
320      .source = (const struct etna_perfmon_source[]) {
321         { "TX", "TOTAL_TRILINEAR_REQUESTS" }
322      }
323   },
324   {
325      .name = "tx-total-discarded-texture-requests",
326      .type = ETNA_QUERY_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
327      .group_id = ETNA_QUERY_TX_GROUP_ID,
328      .source = (const struct etna_perfmon_source[]) {
329         { "TX", "TOTAL_DISCARDED_TEXTURE_REQUESTS" }
330      }
331   },
332   {
333      .name = "tx-total-texture-requests",
334      .type = ETNA_QUERY_TX_TOTAL_TEXTURE_REQUESTS,
335      .group_id = ETNA_QUERY_TX_GROUP_ID,
336      .source = (const struct etna_perfmon_source[]) {
337         { "TX", "TOTAL_TEXTURE_REQUESTS" }
338      }
339   },
340   {
341      .name = "tx-mem-read-count",
342      .type = ETNA_QUERY_TX_MEM_READ_COUNT,
343      .group_id = ETNA_QUERY_TX_GROUP_ID,
344      .source = (const struct etna_perfmon_source[]) {
345         { "TX", "MEM_READ_COUNT" }
346      }
347   },
348   {
349      .name = "tx-mem-read-in-8b-count",
350      .type = ETNA_QUERY_TX_MEM_READ_IN_8B_COUNT,
351      .group_id = ETNA_QUERY_TX_GROUP_ID,
352      .source = (const struct etna_perfmon_source[]) {
353         { "TX", "MEM_READ_IN_8B_COUNT" }
354      }
355   },
356   {
357      .name = "tx-cache-miss-count",
358      .type = ETNA_QUERY_TX_CACHE_MISS_COUNT,
359      .group_id = ETNA_QUERY_TX_GROUP_ID,
360      .source = (const struct etna_perfmon_source[]) {
361         { "TX", "CACHE_MISS_COUNT" }
362      }
363   },
364   {
365      .name = "tx-cache-hit-texel-count",
366      .type = ETNA_QUERY_TX_CACHE_HIT_TEXEL_COUNT,
367      .group_id = ETNA_QUERY_TX_GROUP_ID,
368      .source = (const struct etna_perfmon_source[]) {
369         { "TX", "CACHE_HIT_TEXEL_COUNT" }
370      }
371   },
372   {
373      .name = "tx-cache-miss-texel-count",
374      .type = ETNA_QUERY_TX_CACHE_MISS_TEXEL_COUNT,
375      .group_id = ETNA_QUERY_TX_GROUP_ID,
376      .source = (const struct etna_perfmon_source[]) {
377         { "TX", "CACHE_MISS_TEXEL_COUNT" }
378      }
379   },
380   {
381      .name = "mc-total-read-req-8b-from-pipeline",
382      .type = ETNA_QUERY_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
383      .group_id = ETNA_QUERY_MC_GROUP_ID,
384      .source = (const struct etna_perfmon_source[]) {
385         { "MC", "TOTAL_READ_REQ_8B_FROM_PIPELINE" }
386      }
387   },
388   {
389      .name = "mc-total-read-req-8b-from-ip",
390      .type = ETNA_QUERY_MC_TOTAL_READ_REQ_8B_FROM_IP,
391      .group_id = ETNA_QUERY_MC_GROUP_ID,
392      .source = (const struct etna_perfmon_source[]) {
393         { "MC", "TOTAL_READ_REQ_8B_FROM_IP" }
394      }
395   },
396   {
397      .name = "mc-total-write-req-8b-from-pipeline",
398      .type = ETNA_QUERY_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
399      .group_id = ETNA_QUERY_MC_GROUP_ID,
400      .source = (const struct etna_perfmon_source[]) {
401         { "MC", "TOTAL_WRITE_REQ_8B_FROM_PIPELINE" }
402      }
403   }
404};
405
406struct etna_perfmon_signal *
407etna_pm_query_signal(struct etna_perfmon *perfmon,
408                     const struct etna_perfmon_source *source)
409{
410   struct etna_perfmon_domain *domain;
411
412   domain = etna_perfmon_get_dom_by_name(perfmon, source->domain);
413   if (!domain)
414      return NULL;
415
416   return etna_perfmon_get_sig_by_name(domain, source->signal);
417}
418
419void
420etna_pm_query_setup(struct etna_screen *screen)
421{
422   screen->perfmon = etna_perfmon_create(screen->pipe);
423
424   if (!screen->perfmon)
425      return;
426
427   for (unsigned i = 0; i < ARRAY_SIZE(query_config); i++) {
428      const struct etna_perfmon_config *cfg = &query_config[i];
429
430      if (!etna_pm_cfg_supported(screen->perfmon, cfg))
431         continue;
432
433      util_dynarray_append(&screen->supported_pm_queries, unsigned, i);
434   }
435}
436
437const struct etna_perfmon_config *
438etna_pm_query_config(unsigned type)
439{
440   for (unsigned i = 0; i < ARRAY_SIZE(query_config); i++)
441      if (query_config[i].type == type)
442         return &query_config[i];
443
444   return NULL;
445}
446
447int
448etna_pm_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
449                              struct pipe_driver_query_info *info)
450{
451   const struct etna_screen *screen = etna_screen(pscreen);
452   const unsigned num = screen->supported_pm_queries.size / sizeof(unsigned);
453   unsigned i;
454
455   if (!info)
456      return num;
457
458   if (index >= num)
459      return 0;
460
461   i = *util_dynarray_element(&screen->supported_pm_queries, unsigned, index);
462   assert(i < ARRAY_SIZE(query_config));
463
464   info->name = query_config[i].name;
465   info->query_type = query_config[i].type;
466   info->group_id = query_config[i].group_id;
467
468   return 1;
469}
470
471static
472unsigned query_count(unsigned group)
473{
474   unsigned count = 0;
475
476   for (unsigned i = 0; i < ARRAY_SIZE(query_config); i++)
477      if (query_config[i].group_id == group)
478         count++;
479
480   assert(count);
481
482   return count;
483}
484
485int
486etna_pm_get_driver_query_group_info(struct pipe_screen *pscreen,
487                                    unsigned index,
488                                    struct pipe_driver_query_group_info *info)
489{
490   if (!info)
491      return ARRAY_SIZE(group_names);
492
493   if (index >= ARRAY_SIZE(group_names))
494      return 0;
495
496   unsigned count = query_count(index);
497
498   info->name = group_names[index];
499   info->max_active_queries = count;
500   info->num_queries = count;
501
502   return 1;
503}
504