1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "pipe/p_state.h"
28bf215546Sopenharmony_ci#include "util/u_memory.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "freedreno_context.h"
31bf215546Sopenharmony_ci#include "freedreno_query.h"
32bf215546Sopenharmony_ci#include "freedreno_query_hw.h"
33bf215546Sopenharmony_ci#include "freedreno_query_sw.h"
34bf215546Sopenharmony_ci#include "freedreno_util.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci/*
37bf215546Sopenharmony_ci * Pipe Query interface:
38bf215546Sopenharmony_ci */
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_cistatic struct pipe_query *
41bf215546Sopenharmony_cifd_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index)
42bf215546Sopenharmony_ci{
43bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
44bf215546Sopenharmony_ci   struct fd_query *q = NULL;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   if (ctx->create_query)
47bf215546Sopenharmony_ci      q = ctx->create_query(ctx, query_type, index);
48bf215546Sopenharmony_ci   if (!q)
49bf215546Sopenharmony_ci      q = fd_sw_create_query(ctx, query_type, index);
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   return (struct pipe_query *)q;
52bf215546Sopenharmony_ci}
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_cistatic void
55bf215546Sopenharmony_cifd_destroy_query(struct pipe_context *pctx, struct pipe_query *pq) in_dt
56bf215546Sopenharmony_ci{
57bf215546Sopenharmony_ci   struct fd_query *q = fd_query(pq);
58bf215546Sopenharmony_ci   q->funcs->destroy_query(fd_context(pctx), q);
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cistatic bool
62bf215546Sopenharmony_cifd_begin_query(struct pipe_context *pctx, struct pipe_query *pq) in_dt
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci   struct fd_query *q = fd_query(pq);
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   q->funcs->begin_query(fd_context(pctx), q);
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   return true;
69bf215546Sopenharmony_ci}
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_cistatic bool
72bf215546Sopenharmony_cifd_end_query(struct pipe_context *pctx, struct pipe_query *pq) in_dt
73bf215546Sopenharmony_ci{
74bf215546Sopenharmony_ci   struct fd_query *q = fd_query(pq);
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   /* there are a couple special cases, which don't have
77bf215546Sopenharmony_ci    * a matching ->begin_query():
78bf215546Sopenharmony_ci    */
79bf215546Sopenharmony_ci   if (skip_begin_query(q->type))
80bf215546Sopenharmony_ci      fd_begin_query(pctx, pq);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   q->funcs->end_query(fd_context(pctx), q);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   return true;
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_cistatic bool
88bf215546Sopenharmony_cifd_get_query_result(struct pipe_context *pctx, struct pipe_query *pq, bool wait,
89bf215546Sopenharmony_ci                    union pipe_query_result *result)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   struct fd_query *q = fd_query(pq);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   util_query_clear_result(result, q->type);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   return q->funcs->get_query_result(fd_context(pctx), q, wait, result);
96bf215546Sopenharmony_ci}
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_cistatic void
99bf215546Sopenharmony_cifd_render_condition(struct pipe_context *pctx, struct pipe_query *pq,
100bf215546Sopenharmony_ci                    bool condition, enum pipe_render_cond_flag mode) in_dt
101bf215546Sopenharmony_ci{
102bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
103bf215546Sopenharmony_ci   ctx->cond_query = pq;
104bf215546Sopenharmony_ci   ctx->cond_cond = condition;
105bf215546Sopenharmony_ci   ctx->cond_mode = mode;
106bf215546Sopenharmony_ci}
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci#define _Q(_name, _query_type, _type, _result_type) {                          \
109bf215546Sopenharmony_ci      .name = _name, .query_type = _query_type,                                \
110bf215546Sopenharmony_ci      .type = PIPE_DRIVER_QUERY_TYPE_##_type,                                  \
111bf215546Sopenharmony_ci      .result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_##_result_type,             \
112bf215546Sopenharmony_ci      .group_id = ~(unsigned)0,                                                \
113bf215546Sopenharmony_ci   }
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci#define FQ(_name, _query_type, _type, _result_type)                            \
116bf215546Sopenharmony_ci   _Q(_name, FD_QUERY_##_query_type, _type, _result_type)
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci#define PQ(_name, _query_type, _type, _result_type)                            \
119bf215546Sopenharmony_ci   _Q(_name, PIPE_QUERY_##_query_type, _type, _result_type)
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic const struct pipe_driver_query_info sw_query_list[] = {
122bf215546Sopenharmony_ci   FQ("draw-calls", DRAW_CALLS, UINT64, AVERAGE),
123bf215546Sopenharmony_ci   FQ("batches", BATCH_TOTAL, UINT64, AVERAGE),
124bf215546Sopenharmony_ci   FQ("batches-sysmem", BATCH_SYSMEM, UINT64, AVERAGE),
125bf215546Sopenharmony_ci   FQ("batches-gmem", BATCH_GMEM, UINT64, AVERAGE),
126bf215546Sopenharmony_ci   FQ("batches-nondraw", BATCH_NONDRAW, UINT64, AVERAGE),
127bf215546Sopenharmony_ci   FQ("restores", BATCH_RESTORE, UINT64, AVERAGE),
128bf215546Sopenharmony_ci   PQ("prims-emitted", PRIMITIVES_EMITTED, UINT64, AVERAGE),
129bf215546Sopenharmony_ci   FQ("staging", STAGING_UPLOADS, UINT64, AVERAGE),
130bf215546Sopenharmony_ci   FQ("shadow", SHADOW_UPLOADS, UINT64, AVERAGE),
131bf215546Sopenharmony_ci   FQ("vsregs", VS_REGS, FLOAT, AVERAGE),
132bf215546Sopenharmony_ci   FQ("fsregs", FS_REGS, FLOAT, AVERAGE),
133bf215546Sopenharmony_ci};
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_cistatic int
136bf215546Sopenharmony_cifd_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
137bf215546Sopenharmony_ci                         struct pipe_driver_query_info *info)
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci   struct fd_screen *screen = fd_screen(pscreen);
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   if (!info)
142bf215546Sopenharmony_ci      return ARRAY_SIZE(sw_query_list) + screen->num_perfcntr_queries;
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   if (index >= ARRAY_SIZE(sw_query_list)) {
145bf215546Sopenharmony_ci      index -= ARRAY_SIZE(sw_query_list);
146bf215546Sopenharmony_ci      if (index >= screen->num_perfcntr_queries)
147bf215546Sopenharmony_ci         return 0;
148bf215546Sopenharmony_ci      *info = screen->perfcntr_queries[index];
149bf215546Sopenharmony_ci      return 1;
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   *info = sw_query_list[index];
153bf215546Sopenharmony_ci   return 1;
154bf215546Sopenharmony_ci}
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_cistatic int
157bf215546Sopenharmony_cifd_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index,
158bf215546Sopenharmony_ci                               struct pipe_driver_query_group_info *info)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   struct fd_screen *screen = fd_screen(pscreen);
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   if (!info)
163bf215546Sopenharmony_ci      return screen->num_perfcntr_groups;
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   if (index >= screen->num_perfcntr_groups)
166bf215546Sopenharmony_ci      return 0;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   const struct fd_perfcntr_group *g = &screen->perfcntr_groups[index];
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   info->name = g->name;
171bf215546Sopenharmony_ci   info->max_active_queries = g->num_counters;
172bf215546Sopenharmony_ci   info->num_queries = g->num_countables;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   return 1;
175bf215546Sopenharmony_ci}
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_cistatic void
178bf215546Sopenharmony_cifd_set_active_query_state(struct pipe_context *pctx, bool enable) assert_dt
179bf215546Sopenharmony_ci{
180bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
181bf215546Sopenharmony_ci   ctx->active_queries = enable;
182bf215546Sopenharmony_ci   ctx->update_active_queries = true;
183bf215546Sopenharmony_ci}
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_cistatic enum pipe_driver_query_type
186bf215546Sopenharmony_ciquery_type(enum fd_perfcntr_type type)
187bf215546Sopenharmony_ci{
188bf215546Sopenharmony_ci#define ENUM(t)                                                                \
189bf215546Sopenharmony_ci   case FD_PERFCNTR_##t:                                                       \
190bf215546Sopenharmony_ci      return PIPE_DRIVER_QUERY_##t
191bf215546Sopenharmony_ci   switch (type) {
192bf215546Sopenharmony_ci      ENUM(TYPE_UINT64);
193bf215546Sopenharmony_ci      ENUM(TYPE_UINT);
194bf215546Sopenharmony_ci      ENUM(TYPE_FLOAT);
195bf215546Sopenharmony_ci      ENUM(TYPE_PERCENTAGE);
196bf215546Sopenharmony_ci      ENUM(TYPE_BYTES);
197bf215546Sopenharmony_ci      ENUM(TYPE_MICROSECONDS);
198bf215546Sopenharmony_ci      ENUM(TYPE_HZ);
199bf215546Sopenharmony_ci      ENUM(TYPE_DBM);
200bf215546Sopenharmony_ci      ENUM(TYPE_TEMPERATURE);
201bf215546Sopenharmony_ci      ENUM(TYPE_VOLTS);
202bf215546Sopenharmony_ci      ENUM(TYPE_AMPS);
203bf215546Sopenharmony_ci      ENUM(TYPE_WATTS);
204bf215546Sopenharmony_ci   default:
205bf215546Sopenharmony_ci      unreachable("bad type");
206bf215546Sopenharmony_ci      return 0;
207bf215546Sopenharmony_ci   }
208bf215546Sopenharmony_ci}
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_cistatic enum pipe_driver_query_result_type
211bf215546Sopenharmony_ciquery_result_type(enum fd_perfcntr_result_type type)
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci   switch (type) {
214bf215546Sopenharmony_ci      ENUM(RESULT_TYPE_AVERAGE);
215bf215546Sopenharmony_ci      ENUM(RESULT_TYPE_CUMULATIVE);
216bf215546Sopenharmony_ci   default:
217bf215546Sopenharmony_ci      unreachable("bad type");
218bf215546Sopenharmony_ci      return 0;
219bf215546Sopenharmony_ci   }
220bf215546Sopenharmony_ci}
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_cistatic void
223bf215546Sopenharmony_cisetup_perfcntr_query_info(struct fd_screen *screen)
224bf215546Sopenharmony_ci{
225bf215546Sopenharmony_ci   unsigned num_queries = 0;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   for (unsigned i = 0; i < screen->num_perfcntr_groups; i++)
228bf215546Sopenharmony_ci      num_queries += screen->perfcntr_groups[i].num_countables;
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   screen->perfcntr_queries =
231bf215546Sopenharmony_ci      calloc(num_queries, sizeof(screen->perfcntr_queries[0]));
232bf215546Sopenharmony_ci   screen->num_perfcntr_queries = num_queries;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   unsigned idx = 0;
235bf215546Sopenharmony_ci   for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) {
236bf215546Sopenharmony_ci      const struct fd_perfcntr_group *g = &screen->perfcntr_groups[i];
237bf215546Sopenharmony_ci      for (unsigned j = 0; j < g->num_countables; j++) {
238bf215546Sopenharmony_ci         struct pipe_driver_query_info *info = &screen->perfcntr_queries[idx];
239bf215546Sopenharmony_ci         const struct fd_perfcntr_countable *c = &g->countables[j];
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci         info->name = c->name;
242bf215546Sopenharmony_ci         info->query_type = FD_QUERY_FIRST_PERFCNTR + idx;
243bf215546Sopenharmony_ci         info->type = query_type(c->query_type);
244bf215546Sopenharmony_ci         info->result_type = query_result_type(c->result_type);
245bf215546Sopenharmony_ci         info->group_id = i;
246bf215546Sopenharmony_ci         info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH;
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci         idx++;
249bf215546Sopenharmony_ci      }
250bf215546Sopenharmony_ci   }
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_civoid
254bf215546Sopenharmony_cifd_query_screen_init(struct pipe_screen *pscreen)
255bf215546Sopenharmony_ci{
256bf215546Sopenharmony_ci   pscreen->get_driver_query_info = fd_get_driver_query_info;
257bf215546Sopenharmony_ci   pscreen->get_driver_query_group_info = fd_get_driver_query_group_info;
258bf215546Sopenharmony_ci   setup_perfcntr_query_info(fd_screen(pscreen));
259bf215546Sopenharmony_ci}
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_civoid
262bf215546Sopenharmony_cifd_query_context_init(struct pipe_context *pctx)
263bf215546Sopenharmony_ci{
264bf215546Sopenharmony_ci   pctx->create_query = fd_create_query;
265bf215546Sopenharmony_ci   pctx->destroy_query = fd_destroy_query;
266bf215546Sopenharmony_ci   pctx->begin_query = fd_begin_query;
267bf215546Sopenharmony_ci   pctx->end_query = fd_end_query;
268bf215546Sopenharmony_ci   pctx->get_query_result = fd_get_query_result;
269bf215546Sopenharmony_ci   pctx->set_active_query_state = fd_set_active_query_state;
270bf215546Sopenharmony_ci   pctx->render_condition = fd_render_condition;
271bf215546Sopenharmony_ci}
272