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