def6166479b11fb6e6c10eb473c71239431e2525
[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;
45
46 q = fd_sw_create_query(ctx, query_type);
47 if (!q && ctx->create_query)
48 q = ctx->create_query(ctx, query_type);
49
50 return (struct pipe_query *) q;
51 }
52
53 static void
54 fd_destroy_query(struct pipe_context *pctx, struct pipe_query *pq)
55 {
56 struct fd_query *q = fd_query(pq);
57 q->funcs->destroy_query(fd_context(pctx), q);
58 }
59
60 static bool
61 fd_begin_query(struct pipe_context *pctx, struct pipe_query *pq)
62 {
63 struct fd_query *q = fd_query(pq);
64 bool ret;
65
66 if (q->active)
67 return false;
68
69 ret = q->funcs->begin_query(fd_context(pctx), q);
70 q->active = ret;
71
72 return ret;
73 }
74
75 static bool
76 fd_end_query(struct pipe_context *pctx, struct pipe_query *pq)
77 {
78 struct fd_query *q = fd_query(pq);
79
80 /* there are a couple special cases, which don't have
81 * a matching ->begin_query():
82 */
83 if (skip_begin_query(q->type) && !q->active)
84 fd_begin_query(pctx, pq);
85
86 if (!q->active)
87 return false;
88
89 q->funcs->end_query(fd_context(pctx), q);
90 q->active = false;
91
92 return true;
93 }
94
95 static bool
96 fd_get_query_result(struct pipe_context *pctx, struct pipe_query *pq,
97 bool wait, union pipe_query_result *result)
98 {
99 struct fd_query *q = fd_query(pq);
100
101 if (q->active)
102 return false;
103
104 util_query_clear_result(result, q->type);
105
106 return q->funcs->get_query_result(fd_context(pctx), q, wait, result);
107 }
108
109 static void
110 fd_render_condition(struct pipe_context *pctx, struct pipe_query *pq,
111 bool condition, enum pipe_render_cond_flag mode)
112 {
113 struct fd_context *ctx = fd_context(pctx);
114 ctx->cond_query = pq;
115 ctx->cond_cond = condition;
116 ctx->cond_mode = mode;
117 }
118
119 #define _Q(_name, _query_type, _type, _result_type) { \
120 .name = _name, \
121 .query_type = _query_type, \
122 .type = PIPE_DRIVER_QUERY_TYPE_ ## _type, \
123 .result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_ ## _result_type, \
124 .group_id = ~(unsigned)0, \
125 }
126
127 #define FQ(_name, _query_type, _type, _result_type) \
128 _Q(_name, FD_QUERY_ ## _query_type, _type, _result_type)
129
130 #define PQ(_name, _query_type, _type, _result_type) \
131 _Q(_name, PIPE_QUERY_ ## _query_type, _type, _result_type)
132
133 static const struct pipe_driver_query_info sw_query_list[] = {
134 FQ("draw-calls", DRAW_CALLS, UINT64, AVERAGE),
135 FQ("batches", BATCH_TOTAL, UINT64, AVERAGE),
136 FQ("batches-sysmem", BATCH_SYSMEM, UINT64, AVERAGE),
137 FQ("batches-gmem", BATCH_GMEM, UINT64, AVERAGE),
138 FQ("batches-nondraw", BATCH_NONDRAW, UINT64, AVERAGE),
139 FQ("restores", BATCH_RESTORE, UINT64, AVERAGE),
140 PQ("prims-emitted", PRIMITIVES_EMITTED, UINT64, AVERAGE),
141 FQ("staging", STAGING_UPLOADS, UINT64, AVERAGE),
142 FQ("shadow", SHADOW_UPLOADS, UINT64, AVERAGE),
143 FQ("vsregs", VS_REGS, FLOAT, AVERAGE),
144 FQ("fsregs", FS_REGS, FLOAT, AVERAGE),
145 };
146
147 static int
148 fd_get_driver_query_info(struct pipe_screen *pscreen,
149 unsigned index, struct pipe_driver_query_info *info)
150 {
151 struct fd_screen *screen = fd_screen(pscreen);
152
153 if (!info)
154 return ARRAY_SIZE(sw_query_list) + screen->num_perfcntr_queries;
155
156 if (index >= ARRAY_SIZE(sw_query_list)) {
157 index -= ARRAY_SIZE(sw_query_list);
158 if (index >= screen->num_perfcntr_queries)
159 return 0;
160 *info = screen->perfcntr_queries[index];
161 return 1;
162 }
163
164 *info = sw_query_list[index];
165 return 1;
166 }
167
168 static int
169 fd_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index,
170 struct pipe_driver_query_group_info *info)
171 {
172 struct fd_screen *screen = fd_screen(pscreen);
173
174 if (!info)
175 return screen->num_perfcntr_groups;
176
177 if (index >= screen->num_perfcntr_groups)
178 return 0;
179
180 const struct fd_perfcntr_group *g = &screen->perfcntr_groups[index];
181
182 info->name = g->name;
183 info->max_active_queries = g->num_counters;
184 info->num_queries = g->num_countables;
185
186 return 1;
187 }
188
189 static void
190 fd_set_active_query_state(struct pipe_context *pipe, bool enable)
191 {
192 }
193
194 static void
195 setup_perfcntr_query_info(struct fd_screen *screen)
196 {
197 unsigned num_queries = 0;
198
199 for (unsigned i = 0; i < screen->num_perfcntr_groups; i++)
200 num_queries += screen->perfcntr_groups[i].num_countables;
201
202 screen->perfcntr_queries =
203 calloc(num_queries, sizeof(screen->perfcntr_queries[0]));
204 screen->num_perfcntr_queries = num_queries;
205
206 unsigned idx = 0;
207 for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) {
208 const struct fd_perfcntr_group *g = &screen->perfcntr_groups[i];
209 for (unsigned j = 0; j < g->num_countables; j++) {
210 struct pipe_driver_query_info *info =
211 &screen->perfcntr_queries[idx];
212 const struct fd_perfcntr_countable *c =
213 &g->countables[j];
214
215 info->name = c->name;
216 info->query_type = FD_QUERY_FIRST_PERFCNTR + idx;
217 info->type = c->query_type;
218 info->result_type = c->result_type;
219 info->group_id = i;
220 info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH;
221
222 idx++;
223 }
224 }
225 }
226
227 void
228 fd_query_screen_init(struct pipe_screen *pscreen)
229 {
230 pscreen->get_driver_query_info = fd_get_driver_query_info;
231 pscreen->get_driver_query_group_info = fd_get_driver_query_group_info;
232 setup_perfcntr_query_info(fd_screen(pscreen));
233 }
234
235 void
236 fd_query_context_init(struct pipe_context *pctx)
237 {
238 pctx->create_query = fd_create_query;
239 pctx->destroy_query = fd_destroy_query;
240 pctx->begin_query = fd_begin_query;
241 pctx->end_query = fd_end_query;
242 pctx->get_query_result = fd_get_query_result;
243 pctx->set_active_query_state = fd_set_active_query_state;
244 pctx->render_condition = fd_render_condition;
245 }