• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
3  *
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:
10  *
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
13  * Software.
14  *
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
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include "pipe/p_state.h"
28 #include "util/u_memory.h"
29 
30 #include "freedreno_context.h"
31 #include "freedreno_query.h"
32 #include "freedreno_query_hw.h"
33 #include "freedreno_query_sw.h"
34 #include "freedreno_util.h"
35 
36 /*
37  * Pipe Query interface:
38  */
39 
40 static struct pipe_query *
fd_create_query(struct pipe_context * pctx,unsigned query_type,unsigned index)41 fd_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index)
42 {
43    struct fd_context *ctx = fd_context(pctx);
44    struct fd_query *q = NULL;
45 
46    if (ctx->create_query)
47       q = ctx->create_query(ctx, query_type, index);
48    if (!q)
49       q = fd_sw_create_query(ctx, query_type, index);
50 
51    return (struct pipe_query *)q;
52 }
53 
54 static void
fd_destroy_query(struct pipe_context * pctx,struct pipe_query * pq)55 fd_destroy_query(struct pipe_context *pctx, struct pipe_query *pq) in_dt
56 {
57    struct fd_query *q = fd_query(pq);
58    q->funcs->destroy_query(fd_context(pctx), q);
59 }
60 
61 static bool
fd_begin_query(struct pipe_context * pctx,struct pipe_query * pq)62 fd_begin_query(struct pipe_context *pctx, struct pipe_query *pq) in_dt
63 {
64    struct fd_query *q = fd_query(pq);
65 
66    q->funcs->begin_query(fd_context(pctx), q);
67 
68    return true;
69 }
70 
71 static bool
fd_end_query(struct pipe_context * pctx,struct pipe_query * pq)72 fd_end_query(struct pipe_context *pctx, struct pipe_query *pq) in_dt
73 {
74    struct fd_query *q = fd_query(pq);
75 
76    /* there are a couple special cases, which don't have
77     * a matching ->begin_query():
78     */
79    if (skip_begin_query(q->type))
80       fd_begin_query(pctx, pq);
81 
82    q->funcs->end_query(fd_context(pctx), q);
83 
84    return true;
85 }
86 
87 static bool
fd_get_query_result(struct pipe_context * pctx,struct pipe_query * pq,bool wait,union pipe_query_result * result)88 fd_get_query_result(struct pipe_context *pctx, struct pipe_query *pq, bool wait,
89                     union pipe_query_result *result)
90 {
91    struct fd_query *q = fd_query(pq);
92 
93    util_query_clear_result(result, q->type);
94 
95    return q->funcs->get_query_result(fd_context(pctx), q, wait, result);
96 }
97 
98 static void
fd_render_condition(struct pipe_context * pctx,struct pipe_query * pq,bool condition,enum pipe_render_cond_flag mode)99 fd_render_condition(struct pipe_context *pctx, struct pipe_query *pq,
100                     bool condition, enum pipe_render_cond_flag mode) in_dt
101 {
102    struct fd_context *ctx = fd_context(pctx);
103    ctx->cond_query = pq;
104    ctx->cond_cond = condition;
105    ctx->cond_mode = mode;
106 }
107 
108 #define _Q(_name, _query_type, _type, _result_type) {                          \
109       .name = _name, .query_type = _query_type,                                \
110       .type = PIPE_DRIVER_QUERY_TYPE_##_type,                                  \
111       .result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_##_result_type,             \
112       .group_id = ~(unsigned)0,                                                \
113    }
114 
115 #define FQ(_name, _query_type, _type, _result_type)                            \
116    _Q(_name, FD_QUERY_##_query_type, _type, _result_type)
117 
118 #define PQ(_name, _query_type, _type, _result_type)                            \
119    _Q(_name, PIPE_QUERY_##_query_type, _type, _result_type)
120 
121 static const struct pipe_driver_query_info sw_query_list[] = {
122    FQ("draw-calls", DRAW_CALLS, UINT64, AVERAGE),
123    FQ("batches", BATCH_TOTAL, UINT64, AVERAGE),
124    FQ("batches-sysmem", BATCH_SYSMEM, UINT64, AVERAGE),
125    FQ("batches-gmem", BATCH_GMEM, UINT64, AVERAGE),
126    FQ("batches-nondraw", BATCH_NONDRAW, UINT64, AVERAGE),
127    FQ("restores", BATCH_RESTORE, UINT64, AVERAGE),
128    PQ("prims-emitted", PRIMITIVES_EMITTED, UINT64, AVERAGE),
129    FQ("staging", STAGING_UPLOADS, UINT64, AVERAGE),
130    FQ("shadow", SHADOW_UPLOADS, UINT64, AVERAGE),
131    FQ("vsregs", VS_REGS, FLOAT, AVERAGE),
132    FQ("fsregs", FS_REGS, FLOAT, AVERAGE),
133 };
134 
135 static int
fd_get_driver_query_info(struct pipe_screen * pscreen,unsigned index,struct pipe_driver_query_info * info)136 fd_get_driver_query_info(struct pipe_screen *pscreen, unsigned index,
137                          struct pipe_driver_query_info *info)
138 {
139    struct fd_screen *screen = fd_screen(pscreen);
140 
141    if (!info)
142       return ARRAY_SIZE(sw_query_list) + screen->num_perfcntr_queries;
143 
144    if (index >= ARRAY_SIZE(sw_query_list)) {
145       index -= ARRAY_SIZE(sw_query_list);
146       if (index >= screen->num_perfcntr_queries)
147          return 0;
148       *info = screen->perfcntr_queries[index];
149       return 1;
150    }
151 
152    *info = sw_query_list[index];
153    return 1;
154 }
155 
156 static int
fd_get_driver_query_group_info(struct pipe_screen * pscreen,unsigned index,struct pipe_driver_query_group_info * info)157 fd_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index,
158                                struct pipe_driver_query_group_info *info)
159 {
160    struct fd_screen *screen = fd_screen(pscreen);
161 
162    if (!info)
163       return screen->num_perfcntr_groups;
164 
165    if (index >= screen->num_perfcntr_groups)
166       return 0;
167 
168    const struct fd_perfcntr_group *g = &screen->perfcntr_groups[index];
169 
170    info->name = g->name;
171    info->max_active_queries = g->num_counters;
172    info->num_queries = g->num_countables;
173 
174    return 1;
175 }
176 
177 static void
fd_set_active_query_state(struct pipe_context * pctx,bool enable)178 fd_set_active_query_state(struct pipe_context *pctx, bool enable) assert_dt
179 {
180    struct fd_context *ctx = fd_context(pctx);
181    ctx->active_queries = enable;
182    ctx->update_active_queries = true;
183 }
184 
185 static enum pipe_driver_query_type
query_type(enum fd_perfcntr_type type)186 query_type(enum fd_perfcntr_type type)
187 {
188 #define ENUM(t)                                                                \
189    case FD_PERFCNTR_##t:                                                       \
190       return PIPE_DRIVER_QUERY_##t
191    switch (type) {
192       ENUM(TYPE_UINT64);
193       ENUM(TYPE_UINT);
194       ENUM(TYPE_FLOAT);
195       ENUM(TYPE_PERCENTAGE);
196       ENUM(TYPE_BYTES);
197       ENUM(TYPE_MICROSECONDS);
198       ENUM(TYPE_HZ);
199       ENUM(TYPE_DBM);
200       ENUM(TYPE_TEMPERATURE);
201       ENUM(TYPE_VOLTS);
202       ENUM(TYPE_AMPS);
203       ENUM(TYPE_WATTS);
204    default:
205       unreachable("bad type");
206       return 0;
207    }
208 }
209 
210 static enum pipe_driver_query_result_type
query_result_type(enum fd_perfcntr_result_type type)211 query_result_type(enum fd_perfcntr_result_type type)
212 {
213    switch (type) {
214       ENUM(RESULT_TYPE_AVERAGE);
215       ENUM(RESULT_TYPE_CUMULATIVE);
216    default:
217       unreachable("bad type");
218       return 0;
219    }
220 }
221 
222 static void
setup_perfcntr_query_info(struct fd_screen * screen)223 setup_perfcntr_query_info(struct fd_screen *screen)
224 {
225    unsigned num_queries = 0;
226 
227    for (unsigned i = 0; i < screen->num_perfcntr_groups; i++)
228       num_queries += screen->perfcntr_groups[i].num_countables;
229 
230    screen->perfcntr_queries =
231       calloc(num_queries, sizeof(screen->perfcntr_queries[0]));
232    screen->num_perfcntr_queries = num_queries;
233 
234    unsigned idx = 0;
235    for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) {
236       const struct fd_perfcntr_group *g = &screen->perfcntr_groups[i];
237       for (unsigned j = 0; j < g->num_countables; j++) {
238          struct pipe_driver_query_info *info = &screen->perfcntr_queries[idx];
239          const struct fd_perfcntr_countable *c = &g->countables[j];
240 
241          info->name = c->name;
242          info->query_type = FD_QUERY_FIRST_PERFCNTR + idx;
243          info->type = query_type(c->query_type);
244          info->result_type = query_result_type(c->result_type);
245          info->group_id = i;
246          info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH;
247 
248          idx++;
249       }
250    }
251 }
252 
253 void
fd_query_screen_init(struct pipe_screen * pscreen)254 fd_query_screen_init(struct pipe_screen *pscreen)
255 {
256    pscreen->get_driver_query_info = fd_get_driver_query_info;
257    pscreen->get_driver_query_group_info = fd_get_driver_query_group_info;
258    setup_perfcntr_query_info(fd_screen(pscreen));
259 }
260 
261 void
fd_query_context_init(struct pipe_context * pctx)262 fd_query_context_init(struct pipe_context *pctx)
263 {
264    pctx->create_query = fd_create_query;
265    pctx->destroy_query = fd_destroy_query;
266    pctx->begin_query = fd_begin_query;
267    pctx->end_query = fd_end_query;
268    pctx->get_query_result = fd_get_query_result;
269    pctx->set_active_query_state = fd_set_active_query_state;
270    pctx->render_condition = fd_render_condition;
271 }
272