blob: a356aad5b32792701fcf8b7ea84ea474dcaceeb9 [file] [log] [blame]
Jerome Glisse1235bec2010-09-29 15:05:19 -04001/*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
Marek Olšák4e5c70e2014-01-21 18:01:01 +01003 * Copyright 2014 Marek Olšák <marek.olsak@amd.com>
Jerome Glisse1235bec2010-09-29 15:05:19 -04004 *
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * 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 AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
Marek Olšák4e5c70e2014-01-21 18:01:01 +010024
25#include "r600_cs.h"
Marek Olšákdf00dc32012-02-22 00:25:55 +010026#include "util/u_memory.h"
Marek Olšák83667ac2012-02-23 22:38:41 +010027
Marek Olšák4e5c70e2014-01-21 18:01:01 +010028
29struct r600_query_buffer {
30 /* The buffer where query results are stored. */
31 struct r600_resource *buf;
32 /* Offset of the next free result after current query data */
33 unsigned results_end;
34 /* If a query buffer is full, a new buffer is created and the old one
35 * is put in here. When we calculate the result, we sum up the samples
36 * from all buffers. */
37 struct r600_query_buffer *previous;
38};
39
40struct r600_query {
41 /* The query buffer and how many results are in it. */
42 struct r600_query_buffer buffer;
43 /* The type of query */
44 unsigned type;
45 /* Size of the result in memory for both begin_query and end_query,
46 * this can be one or two numbers, or it could even be a size of a structure. */
47 unsigned result_size;
48 /* The number of dwords for begin_query or end_query. */
49 unsigned num_cs_dw;
50 /* linked list of queries */
51 struct list_head list;
52 /* for custom non-GPU queries */
53 uint64_t begin_result;
54 uint64_t end_result;
55};
56
57
Marek Olšák09ec30f2012-02-23 23:22:35 +010058static bool r600_is_timer_query(unsigned type)
59{
60 return type == PIPE_QUERY_TIME_ELAPSED ||
61 type == PIPE_QUERY_TIMESTAMP ||
62 type == PIPE_QUERY_TIMESTAMP_DISJOINT;
63}
64
Marek Olšák0018db12012-02-23 23:32:01 +010065static bool r600_query_needs_begin(unsigned type)
66{
67 return type != PIPE_QUERY_GPU_FINISHED &&
68 type != PIPE_QUERY_TIMESTAMP;
69}
70
Marek Olšák4e5c70e2014-01-21 18:01:01 +010071static struct r600_resource *r600_new_query_buffer(struct r600_common_context *ctx, unsigned type)
Marek Olšák83667ac2012-02-23 22:38:41 +010072{
73 unsigned j, i, num_results, buf_size = 4096;
74 uint32_t *results;
Marek Olšák25043802013-03-21 19:44:18 +010075
76 /* Non-GPU queries. */
77 switch (type) {
78 case R600_QUERY_DRAW_CALLS:
Marek Olšák8ddae682013-03-22 02:39:42 +010079 case R600_QUERY_REQUESTED_VRAM:
80 case R600_QUERY_REQUESTED_GTT:
Marek Olšák05fa3592013-04-05 02:43:26 +020081 case R600_QUERY_BUFFER_WAIT_TIME:
Marek Olšákfb5cf342014-02-12 15:13:30 +010082 case R600_QUERY_NUM_CS_FLUSHES:
83 case R600_QUERY_NUM_BYTES_MOVED:
84 case R600_QUERY_VRAM_USAGE:
85 case R600_QUERY_GTT_USAGE:
Marek Olšák25043802013-03-21 19:44:18 +010086 return NULL;
87 }
88
Marek Olšák83667ac2012-02-23 22:38:41 +010089 /* Queries are normally read by the CPU after
90 * being written by the gpu, hence staging is probably a good
91 * usage pattern.
92 */
93 struct r600_resource *buf = (struct r600_resource*)
Marek Olšák4e5c70e2014-01-21 18:01:01 +010094 pipe_buffer_create(ctx->b.screen, PIPE_BIND_CUSTOM,
Marek Olšák83667ac2012-02-23 22:38:41 +010095 PIPE_USAGE_STAGING, buf_size);
96
97 switch (type) {
98 case PIPE_QUERY_OCCLUSION_COUNTER:
99 case PIPE_QUERY_OCCLUSION_PREDICATE:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100100 results = r600_buffer_map_sync_with_rings(ctx, buf, PIPE_TRANSFER_WRITE);
Marek Olšák83667ac2012-02-23 22:38:41 +0100101 memset(results, 0, buf_size);
102
103 /* Set top bits for unused backends. */
104 num_results = buf_size / (16 * ctx->max_db);
105 for (j = 0; j < num_results; j++) {
106 for (i = 0; i < ctx->max_db; i++) {
107 if (!(ctx->backend_mask & (1<<i))) {
108 results[(i * 4)+1] = 0x80000000;
109 results[(i * 4)+3] = 0x80000000;
110 }
111 }
112 results += 4 * ctx->max_db;
113 }
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100114 ctx->ws->buffer_unmap(buf->cs_buf);
Marek Olšák83667ac2012-02-23 22:38:41 +0100115 break;
Christoph Bumiller04de3232014-05-17 01:20:13 +0200116 case PIPE_QUERY_GPU_FINISHED:
Marek Olšák83667ac2012-02-23 22:38:41 +0100117 case PIPE_QUERY_TIME_ELAPSED:
Marek Olšák44f14eb2012-07-05 20:06:41 +0200118 case PIPE_QUERY_TIMESTAMP:
Marek Olšák83667ac2012-02-23 22:38:41 +0100119 break;
120 case PIPE_QUERY_PRIMITIVES_EMITTED:
121 case PIPE_QUERY_PRIMITIVES_GENERATED:
122 case PIPE_QUERY_SO_STATISTICS:
123 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
Marek Olšákdfe53672013-04-10 20:45:01 +0200124 case PIPE_QUERY_PIPELINE_STATISTICS:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100125 results = r600_buffer_map_sync_with_rings(ctx, buf, PIPE_TRANSFER_WRITE);
Marek Olšák83667ac2012-02-23 22:38:41 +0100126 memset(results, 0, buf_size);
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100127 ctx->ws->buffer_unmap(buf->cs_buf);
Marek Olšák83667ac2012-02-23 22:38:41 +0100128 break;
129 default:
130 assert(0);
131 }
132 return buf;
133}
134
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100135static void r600_update_occlusion_query_state(struct r600_common_context *rctx,
Marek Olšák6fa22b82012-09-29 03:33:29 +0200136 unsigned type, int diff)
137{
138 if (type == PIPE_QUERY_OCCLUSION_COUNTER ||
139 type == PIPE_QUERY_OCCLUSION_PREDICATE) {
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100140 bool old_enable = rctx->num_occlusion_queries != 0;
Marek Olšák6fa22b82012-09-29 03:33:29 +0200141 bool enable;
142
143 rctx->num_occlusion_queries += diff;
144 assert(rctx->num_occlusion_queries >= 0);
145
146 enable = rctx->num_occlusion_queries != 0;
147
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100148 if (enable != old_enable) {
149 rctx->set_occlusion_query_state(&rctx->b, enable);
Marek Olšák6fa22b82012-09-29 03:33:29 +0200150 }
151 }
152}
153
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100154static void r600_emit_query_begin(struct r600_common_context *ctx, struct r600_query *query)
Marek Olšák83667ac2012-02-23 22:38:41 +0100155{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100156 struct radeon_winsys_cs *cs = ctx->rings.gfx.cs;
Marek Olšák83667ac2012-02-23 22:38:41 +0100157 uint64_t va;
158
Marek Olšák6fa22b82012-09-29 03:33:29 +0200159 r600_update_occlusion_query_state(ctx, query->type, 1);
Marek Olšákf5491292014-03-09 22:12:26 +0100160 r600_update_prims_generated_query_state(ctx, query->type, 1);
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100161 ctx->need_gfx_cs_space(&ctx->b, query->num_cs_dw * 2, TRUE);
Marek Olšák83667ac2012-02-23 22:38:41 +0100162
163 /* Get a new query buffer if needed. */
Marek Olšáka52b3332012-04-10 21:29:06 +0200164 if (query->buffer.results_end + query->result_size > query->buffer.buf->b.b.width0) {
Marek Olšák83667ac2012-02-23 22:38:41 +0100165 struct r600_query_buffer *qbuf = MALLOC_STRUCT(r600_query_buffer);
166 *qbuf = query->buffer;
167 query->buffer.buf = r600_new_query_buffer(ctx, query->type);
168 query->buffer.results_end = 0;
169 query->buffer.previous = qbuf;
170 }
171
172 /* emit begin query */
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100173 va = r600_resource_va(ctx->b.screen, (void*)query->buffer.buf);
Marek Olšák83667ac2012-02-23 22:38:41 +0100174 va += query->buffer.results_end;
175
176 switch (query->type) {
177 case PIPE_QUERY_OCCLUSION_COUNTER:
178 case PIPE_QUERY_OCCLUSION_PREDICATE:
Marek Olšákaa90f172014-01-21 23:44:39 +0100179 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
180 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
181 radeon_emit(cs, va);
182 radeon_emit(cs, (va >> 32UL) & 0xFF);
Marek Olšák83667ac2012-02-23 22:38:41 +0100183 break;
184 case PIPE_QUERY_PRIMITIVES_EMITTED:
185 case PIPE_QUERY_PRIMITIVES_GENERATED:
186 case PIPE_QUERY_SO_STATISTICS:
187 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
Marek Olšákaa90f172014-01-21 23:44:39 +0100188 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
189 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SAMPLE_STREAMOUTSTATS) | EVENT_INDEX(3));
190 radeon_emit(cs, va);
191 radeon_emit(cs, (va >> 32UL) & 0xFF);
Marek Olšák83667ac2012-02-23 22:38:41 +0100192 break;
193 case PIPE_QUERY_TIME_ELAPSED:
Marek Olšákaa90f172014-01-21 23:44:39 +0100194 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOP, 4, 0));
195 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5));
196 radeon_emit(cs, va);
197 radeon_emit(cs, (3 << 29) | ((va >> 32UL) & 0xFF));
198 radeon_emit(cs, 0);
199 radeon_emit(cs, 0);
Marek Olšák83667ac2012-02-23 22:38:41 +0100200 break;
Marek Olšákdfe53672013-04-10 20:45:01 +0200201 case PIPE_QUERY_PIPELINE_STATISTICS:
202 if (!ctx->num_pipelinestat_queries) {
Marek Olšákaa90f172014-01-21 23:44:39 +0100203 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0));
204 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_PIPELINESTAT_START) | EVENT_INDEX(0));
Marek Olšákdfe53672013-04-10 20:45:01 +0200205 }
206 ctx->num_pipelinestat_queries++;
Marek Olšákaa90f172014-01-21 23:44:39 +0100207 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
208 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SAMPLE_PIPELINESTAT) | EVENT_INDEX(2));
209 radeon_emit(cs, va);
210 radeon_emit(cs, (va >> 32UL) & 0xFF);
Marek Olšákdfe53672013-04-10 20:45:01 +0200211 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100212 default:
213 assert(0);
214 }
Marek Olšákbee2b962014-02-20 15:39:35 +0100215 r600_emit_reloc(ctx, &ctx->rings.gfx, query->buffer.buf, RADEON_USAGE_WRITE,
216 RADEON_PRIO_MIN);
Marek Olšák83667ac2012-02-23 22:38:41 +0100217
Marek Olšákfb45a812012-12-21 16:29:19 +0100218 if (!r600_is_timer_query(query->type)) {
Marek Olšák09ec30f2012-02-23 23:22:35 +0100219 ctx->num_cs_dw_nontimer_queries_suspend += query->num_cs_dw;
220 }
Marek Olšák83667ac2012-02-23 22:38:41 +0100221}
222
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100223static void r600_emit_query_end(struct r600_common_context *ctx, struct r600_query *query)
Marek Olšák83667ac2012-02-23 22:38:41 +0100224{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100225 struct radeon_winsys_cs *cs = ctx->rings.gfx.cs;
Marek Olšák83667ac2012-02-23 22:38:41 +0100226 uint64_t va;
227
Marek Olšák0018db12012-02-23 23:32:01 +0100228 /* The queries which need begin already called this in begin_query. */
229 if (!r600_query_needs_begin(query->type)) {
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100230 ctx->need_gfx_cs_space(&ctx->b, query->num_cs_dw, FALSE);
Marek Olšák0018db12012-02-23 23:32:01 +0100231 }
232
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100233 va = r600_resource_va(ctx->b.screen, (void*)query->buffer.buf);
Marek Olšák83667ac2012-02-23 22:38:41 +0100234 /* emit end query */
235 switch (query->type) {
236 case PIPE_QUERY_OCCLUSION_COUNTER:
237 case PIPE_QUERY_OCCLUSION_PREDICATE:
238 va += query->buffer.results_end + 8;
Marek Olšákaa90f172014-01-21 23:44:39 +0100239 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
240 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
241 radeon_emit(cs, va);
242 radeon_emit(cs, (va >> 32UL) & 0xFF);
Marek Olšák83667ac2012-02-23 22:38:41 +0100243 break;
244 case PIPE_QUERY_PRIMITIVES_EMITTED:
245 case PIPE_QUERY_PRIMITIVES_GENERATED:
246 case PIPE_QUERY_SO_STATISTICS:
247 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
Martin Andersson92855bc2013-03-25 23:11:34 +0100248 va += query->buffer.results_end + query->result_size/2;
Marek Olšákaa90f172014-01-21 23:44:39 +0100249 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
250 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SAMPLE_STREAMOUTSTATS) | EVENT_INDEX(3));
251 radeon_emit(cs, va);
252 radeon_emit(cs, (va >> 32UL) & 0xFF);
Marek Olšák83667ac2012-02-23 22:38:41 +0100253 break;
254 case PIPE_QUERY_TIME_ELAPSED:
255 va += query->buffer.results_end + query->result_size/2;
Marek Olšák44f14eb2012-07-05 20:06:41 +0200256 /* fall through */
257 case PIPE_QUERY_TIMESTAMP:
Marek Olšákaa90f172014-01-21 23:44:39 +0100258 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE_EOP, 4, 0));
259 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5));
260 radeon_emit(cs, va);
261 radeon_emit(cs, (3 << 29) | ((va >> 32UL) & 0xFF));
262 radeon_emit(cs, 0);
263 radeon_emit(cs, 0);
Marek Olšák83667ac2012-02-23 22:38:41 +0100264 break;
Marek Olšákdfe53672013-04-10 20:45:01 +0200265 case PIPE_QUERY_PIPELINE_STATISTICS:
266 assert(ctx->num_pipelinestat_queries > 0);
267 ctx->num_pipelinestat_queries--;
268 if (!ctx->num_pipelinestat_queries) {
Marek Olšákaa90f172014-01-21 23:44:39 +0100269 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 0, 0));
270 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_PIPELINESTAT_STOP) | EVENT_INDEX(0));
Marek Olšákdfe53672013-04-10 20:45:01 +0200271 }
272 va += query->buffer.results_end + query->result_size/2;
Marek Olšákaa90f172014-01-21 23:44:39 +0100273 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
274 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_SAMPLE_PIPELINESTAT) | EVENT_INDEX(2));
275 radeon_emit(cs, va);
276 radeon_emit(cs, (va >> 32UL) & 0xFF);
Marek Olšákdfe53672013-04-10 20:45:01 +0200277 break;
Christoph Bumiller04de3232014-05-17 01:20:13 +0200278 case PIPE_QUERY_GPU_FINISHED:
279 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100280 default:
281 assert(0);
282 }
Marek Olšákbee2b962014-02-20 15:39:35 +0100283 r600_emit_reloc(ctx, &ctx->rings.gfx, query->buffer.buf, RADEON_USAGE_WRITE,
284 RADEON_PRIO_MIN);
Marek Olšák83667ac2012-02-23 22:38:41 +0100285
286 query->buffer.results_end += query->result_size;
Marek Olšák09ec30f2012-02-23 23:22:35 +0100287
Marek Olšák0018db12012-02-23 23:32:01 +0100288 if (r600_query_needs_begin(query->type)) {
Marek Olšákfb45a812012-12-21 16:29:19 +0100289 if (!r600_is_timer_query(query->type)) {
Marek Olšák0018db12012-02-23 23:32:01 +0100290 ctx->num_cs_dw_nontimer_queries_suspend -= query->num_cs_dw;
291 }
Marek Olšák09ec30f2012-02-23 23:22:35 +0100292 }
Marek Olšák6fa22b82012-09-29 03:33:29 +0200293
294 r600_update_occlusion_query_state(ctx, query->type, -1);
Marek Olšákf5491292014-03-09 22:12:26 +0100295 r600_update_prims_generated_query_state(ctx, query->type, -1);
Marek Olšák83667ac2012-02-23 22:38:41 +0100296}
297
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100298static void r600_emit_query_predication(struct r600_common_context *ctx, struct r600_query *query,
Marek Olšák83667ac2012-02-23 22:38:41 +0100299 int operation, bool flag_wait)
300{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100301 struct radeon_winsys_cs *cs = ctx->rings.gfx.cs;
Marek Olšák83667ac2012-02-23 22:38:41 +0100302
303 if (operation == PREDICATION_OP_CLEAR) {
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100304 ctx->need_gfx_cs_space(&ctx->b, 3, FALSE);
Marek Olšák83667ac2012-02-23 22:38:41 +0100305
Marek Olšákaa90f172014-01-21 23:44:39 +0100306 radeon_emit(cs, PKT3(PKT3_SET_PREDICATION, 1, 0));
307 radeon_emit(cs, 0);
308 radeon_emit(cs, PRED_OP(PREDICATION_OP_CLEAR));
Marek Olšák83667ac2012-02-23 22:38:41 +0100309 } else {
310 struct r600_query_buffer *qbuf;
311 unsigned count;
312 uint32_t op;
313
314 /* Find how many results there are. */
315 count = 0;
316 for (qbuf = &query->buffer; qbuf; qbuf = qbuf->previous) {
317 count += qbuf->results_end / query->result_size;
318 }
319
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100320 ctx->need_gfx_cs_space(&ctx->b, 5 * count, TRUE);
Marek Olšák83667ac2012-02-23 22:38:41 +0100321
322 op = PRED_OP(operation) | PREDICATION_DRAW_VISIBLE |
323 (flag_wait ? PREDICATION_HINT_WAIT : PREDICATION_HINT_NOWAIT_DRAW);
324
325 /* emit predicate packets for all data blocks */
326 for (qbuf = &query->buffer; qbuf; qbuf = qbuf->previous) {
327 unsigned results_base = 0;
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100328 uint64_t va = r600_resource_va(ctx->b.screen, &qbuf->buf->b.b);
Marek Olšák83667ac2012-02-23 22:38:41 +0100329
330 while (results_base < qbuf->results_end) {
Marek Olšákaa90f172014-01-21 23:44:39 +0100331 radeon_emit(cs, PKT3(PKT3_SET_PREDICATION, 1, 0));
332 radeon_emit(cs, (va + results_base) & 0xFFFFFFFFUL);
333 radeon_emit(cs, op | (((va + results_base) >> 32UL) & 0xFF));
Marek Olšákbee2b962014-02-20 15:39:35 +0100334 r600_emit_reloc(ctx, &ctx->rings.gfx, qbuf->buf, RADEON_USAGE_READ,
335 RADEON_PRIO_MIN);
Marek Olšák83667ac2012-02-23 22:38:41 +0100336 results_base += query->result_size;
337
338 /* set CONTINUE bit for all packets except the first */
339 op |= PREDICATION_CONTINUE;
340 }
Marek Olšákc53b8de2014-01-21 23:46:44 +0100341 }
Marek Olšák83667ac2012-02-23 22:38:41 +0100342 }
343}
Jerome Glisse1235bec2010-09-29 15:05:19 -0400344
345static struct pipe_query *r600_create_query(struct pipe_context *ctx, unsigned query_type)
346{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100347 struct r600_common_context *rctx = (struct r600_common_context *)ctx;
Marek Olšák83667ac2012-02-23 22:38:41 +0100348 struct r600_query *query;
Marek Olšák25043802013-03-21 19:44:18 +0100349 bool skip_allocation = false;
Marek Olšák83667ac2012-02-23 22:38:41 +0100350
351 query = CALLOC_STRUCT(r600_query);
352 if (query == NULL)
353 return NULL;
354
355 query->type = query_type;
356
357 switch (query_type) {
358 case PIPE_QUERY_OCCLUSION_COUNTER:
359 case PIPE_QUERY_OCCLUSION_PREDICATE:
360 query->result_size = 16 * rctx->max_db;
361 query->num_cs_dw = 6;
362 break;
Christoph Bumiller04de3232014-05-17 01:20:13 +0200363 case PIPE_QUERY_GPU_FINISHED:
364 query->num_cs_dw = 2;
365 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100366 case PIPE_QUERY_TIME_ELAPSED:
367 query->result_size = 16;
368 query->num_cs_dw = 8;
369 break;
Marek Olšák44f14eb2012-07-05 20:06:41 +0200370 case PIPE_QUERY_TIMESTAMP:
371 query->result_size = 8;
372 query->num_cs_dw = 8;
373 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100374 case PIPE_QUERY_PRIMITIVES_EMITTED:
375 case PIPE_QUERY_PRIMITIVES_GENERATED:
376 case PIPE_QUERY_SO_STATISTICS:
377 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
378 /* NumPrimitivesWritten, PrimitiveStorageNeeded. */
379 query->result_size = 32;
380 query->num_cs_dw = 6;
381 break;
Marek Olšákdfe53672013-04-10 20:45:01 +0200382 case PIPE_QUERY_PIPELINE_STATISTICS:
383 /* 11 values on EG, 8 on R600. */
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100384 query->result_size = (rctx->chip_class >= EVERGREEN ? 11 : 8) * 16;
Marek Olšákdfe53672013-04-10 20:45:01 +0200385 query->num_cs_dw = 8;
386 break;
Marek Olšák25043802013-03-21 19:44:18 +0100387 /* Non-GPU queries. */
388 case R600_QUERY_DRAW_CALLS:
Marek Olšák8ddae682013-03-22 02:39:42 +0100389 case R600_QUERY_REQUESTED_VRAM:
390 case R600_QUERY_REQUESTED_GTT:
Marek Olšák05fa3592013-04-05 02:43:26 +0200391 case R600_QUERY_BUFFER_WAIT_TIME:
Marek Olšákfb5cf342014-02-12 15:13:30 +0100392 case R600_QUERY_NUM_CS_FLUSHES:
393 case R600_QUERY_NUM_BYTES_MOVED:
394 case R600_QUERY_VRAM_USAGE:
395 case R600_QUERY_GTT_USAGE:
Marek Olšák25043802013-03-21 19:44:18 +0100396 skip_allocation = true;
397 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100398 default:
399 assert(0);
400 FREE(query);
401 return NULL;
402 }
403
Marek Olšák25043802013-03-21 19:44:18 +0100404 if (!skip_allocation) {
405 query->buffer.buf = r600_new_query_buffer(rctx, query_type);
406 if (!query->buffer.buf) {
407 FREE(query);
408 return NULL;
409 }
Marek Olšák83667ac2012-02-23 22:38:41 +0100410 }
411 return (struct pipe_query*)query;
Jerome Glisse1235bec2010-09-29 15:05:19 -0400412}
413
414static void r600_destroy_query(struct pipe_context *ctx, struct pipe_query *query)
415{
Marek Olšák83667ac2012-02-23 22:38:41 +0100416 struct r600_query *rquery = (struct r600_query*)query;
Marek Olšákeabcecc2012-02-23 22:45:45 +0100417 struct r600_query_buffer *prev = rquery->buffer.previous;
418
419 /* Release all query buffers. */
420 while (prev) {
421 struct r600_query_buffer *qbuf = prev;
422 prev = prev->previous;
423 pipe_resource_reference((struct pipe_resource**)&qbuf->buf, NULL);
424 FREE(qbuf);
425 }
Jerome Glisse1235bec2010-09-29 15:05:19 -0400426
Marek Olšák83667ac2012-02-23 22:38:41 +0100427 pipe_resource_reference((struct pipe_resource**)&rquery->buffer.buf, NULL);
428 FREE(query);
Jerome Glisse1235bec2010-09-29 15:05:19 -0400429}
430
Marek Olšák83667ac2012-02-23 22:38:41 +0100431static void r600_begin_query(struct pipe_context *ctx, struct pipe_query *query)
Marek Olšákdf00dc32012-02-22 00:25:55 +0100432{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100433 struct r600_common_context *rctx = (struct r600_common_context *)ctx;
Marek Olšák83667ac2012-02-23 22:38:41 +0100434 struct r600_query *rquery = (struct r600_query *)query;
Marek Olšák83667ac2012-02-23 22:38:41 +0100435 struct r600_query_buffer *prev = rquery->buffer.previous;
Marek Olšákdf00dc32012-02-22 00:25:55 +0100436
Marek Olšák0018db12012-02-23 23:32:01 +0100437 if (!r600_query_needs_begin(rquery->type)) {
438 assert(0);
439 return;
440 }
441
Marek Olšák25043802013-03-21 19:44:18 +0100442 /* Non-GPU queries. */
443 switch (rquery->type) {
444 case R600_QUERY_DRAW_CALLS:
445 rquery->begin_result = rctx->num_draw_calls;
446 return;
Marek Olšák8ddae682013-03-22 02:39:42 +0100447 case R600_QUERY_REQUESTED_VRAM:
448 case R600_QUERY_REQUESTED_GTT:
Marek Olšákfb5cf342014-02-12 15:13:30 +0100449 case R600_QUERY_VRAM_USAGE:
450 case R600_QUERY_GTT_USAGE:
Marek Olšák8ddae682013-03-22 02:39:42 +0100451 rquery->begin_result = 0;
452 return;
Marek Olšák05fa3592013-04-05 02:43:26 +0200453 case R600_QUERY_BUFFER_WAIT_TIME:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100454 rquery->begin_result = rctx->ws->query_value(rctx->ws, RADEON_BUFFER_WAIT_TIME_NS);
Marek Olšák05fa3592013-04-05 02:43:26 +0200455 return;
Marek Olšákfb5cf342014-02-12 15:13:30 +0100456 case R600_QUERY_NUM_CS_FLUSHES:
457 rquery->begin_result = rctx->ws->query_value(rctx->ws, RADEON_NUM_CS_FLUSHES);
458 return;
459 case R600_QUERY_NUM_BYTES_MOVED:
460 rquery->begin_result = rctx->ws->query_value(rctx->ws, RADEON_NUM_BYTES_MOVED);
461 return;
Marek Olšák25043802013-03-21 19:44:18 +0100462 }
463
Marek Olšák0018db12012-02-23 23:32:01 +0100464 /* Discard the old query buffers. */
Marek Olšákdf00dc32012-02-22 00:25:55 +0100465 while (prev) {
466 struct r600_query_buffer *qbuf = prev;
467 prev = prev->previous;
468 pipe_resource_reference((struct pipe_resource**)&qbuf->buf, NULL);
469 FREE(qbuf);
470 }
471
472 /* Obtain a new buffer if the current one can't be mapped without a stall. */
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100473 if (r600_rings_is_buffer_referenced(rctx, rquery->buffer.buf->cs_buf, RADEON_USAGE_READWRITE) ||
474 rctx->ws->buffer_is_busy(rquery->buffer.buf->buf, RADEON_USAGE_READWRITE)) {
Marek Olšák83667ac2012-02-23 22:38:41 +0100475 pipe_resource_reference((struct pipe_resource**)&rquery->buffer.buf, NULL);
476 rquery->buffer.buf = r600_new_query_buffer(rctx, rquery->type);
Marek Olšákdf00dc32012-02-22 00:25:55 +0100477 }
478
Marek Olšák83667ac2012-02-23 22:38:41 +0100479 rquery->buffer.results_end = 0;
480 rquery->buffer.previous = NULL;
Jerome Glisse1235bec2010-09-29 15:05:19 -0400481
Marek Olšák83667ac2012-02-23 22:38:41 +0100482 r600_emit_query_begin(rctx, rquery);
Marek Olšák09ec30f2012-02-23 23:22:35 +0100483
Marek Olšákfb45a812012-12-21 16:29:19 +0100484 if (!r600_is_timer_query(rquery->type)) {
Marek Olšák09ec30f2012-02-23 23:22:35 +0100485 LIST_ADDTAIL(&rquery->list, &rctx->active_nontimer_queries);
486 }
Jerome Glisse1235bec2010-09-29 15:05:19 -0400487}
488
489static void r600_end_query(struct pipe_context *ctx, struct pipe_query *query)
490{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100491 struct r600_common_context *rctx = (struct r600_common_context *)ctx;
Marek Olšáke9b6f212011-10-28 18:27:00 +0200492 struct r600_query *rquery = (struct r600_query *)query;
Jerome Glisse1235bec2010-09-29 15:05:19 -0400493
Marek Olšák25043802013-03-21 19:44:18 +0100494 /* Non-GPU queries. */
495 switch (rquery->type) {
496 case R600_QUERY_DRAW_CALLS:
497 rquery->end_result = rctx->num_draw_calls;
498 return;
Marek Olšák8ddae682013-03-22 02:39:42 +0100499 case R600_QUERY_REQUESTED_VRAM:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100500 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_REQUESTED_VRAM_MEMORY);
Marek Olšák8ddae682013-03-22 02:39:42 +0100501 return;
502 case R600_QUERY_REQUESTED_GTT:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100503 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_REQUESTED_GTT_MEMORY);
Marek Olšák8ddae682013-03-22 02:39:42 +0100504 return;
Marek Olšák05fa3592013-04-05 02:43:26 +0200505 case R600_QUERY_BUFFER_WAIT_TIME:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100506 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_BUFFER_WAIT_TIME_NS);
Marek Olšák05fa3592013-04-05 02:43:26 +0200507 return;
Marek Olšákfb5cf342014-02-12 15:13:30 +0100508 case R600_QUERY_NUM_CS_FLUSHES:
509 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_NUM_CS_FLUSHES);
510 return;
511 case R600_QUERY_NUM_BYTES_MOVED:
512 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_NUM_BYTES_MOVED);
513 return;
514 case R600_QUERY_VRAM_USAGE:
515 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_VRAM_USAGE);
516 return;
517 case R600_QUERY_GTT_USAGE:
518 rquery->end_result = rctx->ws->query_value(rctx->ws, RADEON_GTT_USAGE);
519 return;
Marek Olšák25043802013-03-21 19:44:18 +0100520 }
521
Marek Olšák83667ac2012-02-23 22:38:41 +0100522 r600_emit_query_end(rctx, rquery);
Marek Olšák0018db12012-02-23 23:32:01 +0100523
Marek Olšákfb45a812012-12-21 16:29:19 +0100524 if (r600_query_needs_begin(rquery->type) && !r600_is_timer_query(rquery->type)) {
Marek Olšák0018db12012-02-23 23:32:01 +0100525 LIST_DELINIT(&rquery->list);
526 }
Jerome Glisse1235bec2010-09-29 15:05:19 -0400527}
528
Marek Olšák83667ac2012-02-23 22:38:41 +0100529static unsigned r600_query_read_result(char *map, unsigned start_index, unsigned end_index,
530 bool test_status_bit)
531{
532 uint32_t *current_result = (uint32_t*)map;
533 uint64_t start, end;
534
535 start = (uint64_t)current_result[start_index] |
536 (uint64_t)current_result[start_index+1] << 32;
537 end = (uint64_t)current_result[end_index] |
538 (uint64_t)current_result[end_index+1] << 32;
539
540 if (!test_status_bit ||
541 ((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL))) {
542 return end - start;
543 }
544 return 0;
545}
546
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100547static boolean r600_get_query_buffer_result(struct r600_common_context *ctx,
Marek Olšák83667ac2012-02-23 22:38:41 +0100548 struct r600_query *query,
549 struct r600_query_buffer *qbuf,
550 boolean wait,
Marek Olšákead0a892012-03-29 16:45:44 +0200551 union pipe_query_result *result)
Marek Olšák83667ac2012-02-23 22:38:41 +0100552{
553 unsigned results_base = 0;
554 char *map;
555
Marek Olšák25043802013-03-21 19:44:18 +0100556 /* Non-GPU queries. */
557 switch (query->type) {
558 case R600_QUERY_DRAW_CALLS:
Marek Olšák8ddae682013-03-22 02:39:42 +0100559 case R600_QUERY_REQUESTED_VRAM:
560 case R600_QUERY_REQUESTED_GTT:
Marek Olšák05fa3592013-04-05 02:43:26 +0200561 case R600_QUERY_BUFFER_WAIT_TIME:
Marek Olšákfb5cf342014-02-12 15:13:30 +0100562 case R600_QUERY_NUM_CS_FLUSHES:
563 case R600_QUERY_NUM_BYTES_MOVED:
564 case R600_QUERY_VRAM_USAGE:
565 case R600_QUERY_GTT_USAGE:
Marek Olšák25043802013-03-21 19:44:18 +0100566 result->u64 = query->end_result - query->begin_result;
567 return TRUE;
568 }
569
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100570 map = r600_buffer_map_sync_with_rings(ctx, qbuf->buf,
Jerome Glissebff07632013-01-07 14:25:11 -0500571 PIPE_TRANSFER_READ |
572 (wait ? 0 : PIPE_TRANSFER_DONTBLOCK));
Marek Olšák83667ac2012-02-23 22:38:41 +0100573 if (!map)
574 return FALSE;
575
576 /* count all results across all data blocks */
577 switch (query->type) {
578 case PIPE_QUERY_OCCLUSION_COUNTER:
579 while (results_base != qbuf->results_end) {
580 result->u64 +=
581 r600_query_read_result(map + results_base, 0, 2, true);
582 results_base += 16;
583 }
584 break;
585 case PIPE_QUERY_OCCLUSION_PREDICATE:
586 while (results_base != qbuf->results_end) {
587 result->b = result->b ||
588 r600_query_read_result(map + results_base, 0, 2, true) != 0;
589 results_base += 16;
590 }
591 break;
Christoph Bumiller04de3232014-05-17 01:20:13 +0200592 case PIPE_QUERY_GPU_FINISHED:
593 result->b = TRUE;
594 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100595 case PIPE_QUERY_TIME_ELAPSED:
596 while (results_base != qbuf->results_end) {
597 result->u64 +=
598 r600_query_read_result(map + results_base, 0, 2, false);
599 results_base += query->result_size;
600 }
601 break;
Marek Olšák44f14eb2012-07-05 20:06:41 +0200602 case PIPE_QUERY_TIMESTAMP:
603 {
604 uint32_t *current_result = (uint32_t*)map;
605 result->u64 = (uint64_t)current_result[0] |
606 (uint64_t)current_result[1] << 32;
607 break;
608 }
Marek Olšák83667ac2012-02-23 22:38:41 +0100609 case PIPE_QUERY_PRIMITIVES_EMITTED:
610 /* SAMPLE_STREAMOUTSTATS stores this structure:
611 * {
612 * u64 NumPrimitivesWritten;
613 * u64 PrimitiveStorageNeeded;
614 * }
615 * We only need NumPrimitivesWritten here. */
616 while (results_base != qbuf->results_end) {
617 result->u64 +=
618 r600_query_read_result(map + results_base, 2, 6, true);
619 results_base += query->result_size;
620 }
621 break;
622 case PIPE_QUERY_PRIMITIVES_GENERATED:
623 /* Here we read PrimitiveStorageNeeded. */
624 while (results_base != qbuf->results_end) {
625 result->u64 +=
626 r600_query_read_result(map + results_base, 0, 4, true);
627 results_base += query->result_size;
628 }
629 break;
630 case PIPE_QUERY_SO_STATISTICS:
631 while (results_base != qbuf->results_end) {
Marek Olšákead0a892012-03-29 16:45:44 +0200632 result->so_statistics.num_primitives_written +=
Marek Olšák83667ac2012-02-23 22:38:41 +0100633 r600_query_read_result(map + results_base, 2, 6, true);
Marek Olšákead0a892012-03-29 16:45:44 +0200634 result->so_statistics.primitives_storage_needed +=
Marek Olšák83667ac2012-02-23 22:38:41 +0100635 r600_query_read_result(map + results_base, 0, 4, true);
636 results_base += query->result_size;
637 }
638 break;
639 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
640 while (results_base != qbuf->results_end) {
641 result->b = result->b ||
642 r600_query_read_result(map + results_base, 2, 6, true) !=
643 r600_query_read_result(map + results_base, 0, 4, true);
644 results_base += query->result_size;
645 }
646 break;
Marek Olšákdfe53672013-04-10 20:45:01 +0200647 case PIPE_QUERY_PIPELINE_STATISTICS:
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100648 if (ctx->chip_class >= EVERGREEN) {
Marek Olšákdfe53672013-04-10 20:45:01 +0200649 while (results_base != qbuf->results_end) {
650 result->pipeline_statistics.ps_invocations +=
651 r600_query_read_result(map + results_base, 0, 22, false);
652 result->pipeline_statistics.c_primitives +=
653 r600_query_read_result(map + results_base, 2, 24, false);
654 result->pipeline_statistics.c_invocations +=
655 r600_query_read_result(map + results_base, 4, 26, false);
656 result->pipeline_statistics.vs_invocations +=
657 r600_query_read_result(map + results_base, 6, 28, false);
658 result->pipeline_statistics.gs_invocations +=
659 r600_query_read_result(map + results_base, 8, 30, false);
660 result->pipeline_statistics.gs_primitives +=
661 r600_query_read_result(map + results_base, 10, 32, false);
662 result->pipeline_statistics.ia_primitives +=
663 r600_query_read_result(map + results_base, 12, 34, false);
664 result->pipeline_statistics.ia_vertices +=
665 r600_query_read_result(map + results_base, 14, 36, false);
666 result->pipeline_statistics.hs_invocations +=
667 r600_query_read_result(map + results_base, 16, 38, false);
668 result->pipeline_statistics.ds_invocations +=
669 r600_query_read_result(map + results_base, 18, 40, false);
670 result->pipeline_statistics.cs_invocations +=
671 r600_query_read_result(map + results_base, 20, 42, false);
672 results_base += query->result_size;
673 }
674 } else {
675 while (results_base != qbuf->results_end) {
676 result->pipeline_statistics.ps_invocations +=
677 r600_query_read_result(map + results_base, 0, 16, false);
678 result->pipeline_statistics.c_primitives +=
679 r600_query_read_result(map + results_base, 2, 18, false);
680 result->pipeline_statistics.c_invocations +=
681 r600_query_read_result(map + results_base, 4, 20, false);
682 result->pipeline_statistics.vs_invocations +=
683 r600_query_read_result(map + results_base, 6, 22, false);
684 result->pipeline_statistics.gs_invocations +=
685 r600_query_read_result(map + results_base, 8, 24, false);
686 result->pipeline_statistics.gs_primitives +=
687 r600_query_read_result(map + results_base, 10, 26, false);
688 result->pipeline_statistics.ia_primitives +=
689 r600_query_read_result(map + results_base, 12, 28, false);
690 result->pipeline_statistics.ia_vertices +=
691 r600_query_read_result(map + results_base, 14, 30, false);
692 results_base += query->result_size;
693 }
694 }
695#if 0 /* for testing */
696 printf("Pipeline stats: IA verts=%llu, IA prims=%llu, VS=%llu, HS=%llu, "
697 "DS=%llu, GS=%llu, GS prims=%llu, Clipper=%llu, "
698 "Clipper prims=%llu, PS=%llu, CS=%llu\n",
699 result->pipeline_statistics.ia_vertices,
700 result->pipeline_statistics.ia_primitives,
701 result->pipeline_statistics.vs_invocations,
702 result->pipeline_statistics.hs_invocations,
703 result->pipeline_statistics.ds_invocations,
704 result->pipeline_statistics.gs_invocations,
705 result->pipeline_statistics.gs_primitives,
706 result->pipeline_statistics.c_invocations,
707 result->pipeline_statistics.c_primitives,
708 result->pipeline_statistics.ps_invocations,
709 result->pipeline_statistics.cs_invocations);
710#endif
711 break;
Marek Olšák83667ac2012-02-23 22:38:41 +0100712 default:
713 assert(0);
714 }
715
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100716 ctx->ws->buffer_unmap(qbuf->buf->cs_buf);
Marek Olšák83667ac2012-02-23 22:38:41 +0100717 return TRUE;
718}
719
Jerome Glisse1235bec2010-09-29 15:05:19 -0400720static boolean r600_get_query_result(struct pipe_context *ctx,
721 struct pipe_query *query,
Marek Olšákead0a892012-03-29 16:45:44 +0200722 boolean wait, union pipe_query_result *result)
Jerome Glisse1235bec2010-09-29 15:05:19 -0400723{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100724 struct r600_common_context *rctx = (struct r600_common_context *)ctx;
Jerome Glisse1235bec2010-09-29 15:05:19 -0400725 struct r600_query *rquery = (struct r600_query *)query;
Marek Olšák83667ac2012-02-23 22:38:41 +0100726 struct r600_query_buffer *qbuf;
Jerome Glisse1235bec2010-09-29 15:05:19 -0400727
Marek Olšákead0a892012-03-29 16:45:44 +0200728 util_query_clear_result(result, rquery->type);
Marek Olšák83667ac2012-02-23 22:38:41 +0100729
730 for (qbuf = &rquery->buffer; qbuf; qbuf = qbuf->previous) {
Marek Olšákead0a892012-03-29 16:45:44 +0200731 if (!r600_get_query_buffer_result(rctx, rquery, qbuf, wait, result)) {
Marek Olšák83667ac2012-02-23 22:38:41 +0100732 return FALSE;
733 }
734 }
735
Marek Olšákead0a892012-03-29 16:45:44 +0200736 /* Convert the time to expected units. */
Marek Olšák44f14eb2012-07-05 20:06:41 +0200737 if (rquery->type == PIPE_QUERY_TIME_ELAPSED ||
738 rquery->type == PIPE_QUERY_TIMESTAMP) {
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100739 result->u64 = (1000000 * result->u64) / rctx->screen->info.r600_clock_crystal_freq;
Marek Olšák83667ac2012-02-23 22:38:41 +0100740 }
741 return TRUE;
Jerome Glisse1235bec2010-09-29 15:05:19 -0400742}
743
Dave Airliea44b6532011-02-28 16:19:58 +1000744static void r600_render_condition(struct pipe_context *ctx,
745 struct pipe_query *query,
Roland Scheidegger793e8e32013-06-14 19:48:57 +0200746 boolean condition,
Dave Airliea44b6532011-02-28 16:19:58 +1000747 uint mode)
748{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100749 struct r600_common_context *rctx = (struct r600_common_context *)ctx;
Dave Airliea44b6532011-02-28 16:19:58 +1000750 struct r600_query *rquery = (struct r600_query *)query;
Marek Olšák83667ac2012-02-23 22:38:41 +0100751 bool wait_flag = false;
Dave Airliea44b6532011-02-28 16:19:58 +1000752
Marek Olšák6f243ec2011-06-15 14:26:41 +0200753 rctx->current_render_cond = query;
Roland Scheidegger793e8e32013-06-14 19:48:57 +0200754 rctx->current_render_cond_cond = condition;
Marek Olšák6f243ec2011-06-15 14:26:41 +0200755 rctx->current_render_cond_mode = mode;
756
Vadim Girlinef29bfe2011-07-15 07:22:20 +0400757 if (query == NULL) {
Marek Olšáke4340c12012-01-29 23:25:42 +0100758 if (rctx->predicate_drawing) {
759 rctx->predicate_drawing = false;
Marek Olšák83667ac2012-02-23 22:38:41 +0100760 r600_emit_query_predication(rctx, NULL, PREDICATION_OP_CLEAR, false);
Vadim Girlinef29bfe2011-07-15 07:22:20 +0400761 }
Dave Airliea44b6532011-02-28 16:19:58 +1000762 return;
763 }
764
765 if (mode == PIPE_RENDER_COND_WAIT ||
766 mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
Marek Olšák83667ac2012-02-23 22:38:41 +0100767 wait_flag = true;
Dave Airliea44b6532011-02-28 16:19:58 +1000768 }
769
Marek Olšáke4340c12012-01-29 23:25:42 +0100770 rctx->predicate_drawing = true;
Marek Olšák543b2332011-11-08 21:58:27 +0100771
772 switch (rquery->type) {
773 case PIPE_QUERY_OCCLUSION_COUNTER:
774 case PIPE_QUERY_OCCLUSION_PREDICATE:
Marek Olšák83667ac2012-02-23 22:38:41 +0100775 r600_emit_query_predication(rctx, rquery, PREDICATION_OP_ZPASS, wait_flag);
Marek Olšák543b2332011-11-08 21:58:27 +0100776 break;
777 case PIPE_QUERY_PRIMITIVES_EMITTED:
778 case PIPE_QUERY_PRIMITIVES_GENERATED:
779 case PIPE_QUERY_SO_STATISTICS:
780 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
Marek Olšák83667ac2012-02-23 22:38:41 +0100781 r600_emit_query_predication(rctx, rquery, PREDICATION_OP_PRIMCOUNT, wait_flag);
Marek Olšák543b2332011-11-08 21:58:27 +0100782 break;
783 default:
784 assert(0);
785 }
Dave Airliea44b6532011-02-28 16:19:58 +1000786}
787
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100788void r600_suspend_nontimer_queries(struct r600_common_context *ctx)
Marek Olšák83667ac2012-02-23 22:38:41 +0100789{
790 struct r600_query *query;
791
Marek Olšák09ec30f2012-02-23 23:22:35 +0100792 LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_queries, list) {
Marek Olšák83667ac2012-02-23 22:38:41 +0100793 r600_emit_query_end(ctx, query);
794 }
Marek Olšák09ec30f2012-02-23 23:22:35 +0100795 assert(ctx->num_cs_dw_nontimer_queries_suspend == 0);
Marek Olšák83667ac2012-02-23 22:38:41 +0100796}
797
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100798void r600_resume_nontimer_queries(struct r600_common_context *ctx)
Marek Olšák83667ac2012-02-23 22:38:41 +0100799{
800 struct r600_query *query;
801
Marek Olšák09ec30f2012-02-23 23:22:35 +0100802 assert(ctx->num_cs_dw_nontimer_queries_suspend == 0);
Marek Olšák83667ac2012-02-23 22:38:41 +0100803
Marek Olšák09ec30f2012-02-23 23:22:35 +0100804 LIST_FOR_EACH_ENTRY(query, &ctx->active_nontimer_queries, list) {
805 r600_emit_query_begin(ctx, query);
806 }
807}
808
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100809/* Get backends mask */
810void r600_query_init_backend_mask(struct r600_common_context *ctx)
Jerome Glisse1235bec2010-09-29 15:05:19 -0400811{
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100812 struct radeon_winsys_cs *cs = ctx->rings.gfx.cs;
813 struct r600_resource *buffer;
814 uint32_t *results;
815 unsigned num_backends = ctx->screen->info.r600_num_backends;
816 unsigned i, mask = 0;
817 uint64_t va;
Dave Airliea44b6532011-02-28 16:19:58 +1000818
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100819 /* if backend_map query is supported by the kernel */
820 if (ctx->screen->info.r600_backend_map_valid) {
821 unsigned num_tile_pipes = ctx->screen->info.r600_num_tile_pipes;
822 unsigned backend_map = ctx->screen->info.r600_backend_map;
823 unsigned item_width, item_mask;
824
825 if (ctx->chip_class >= EVERGREEN) {
826 item_width = 4;
827 item_mask = 0x7;
828 } else {
829 item_width = 2;
830 item_mask = 0x3;
831 }
832
833 while(num_tile_pipes--) {
834 i = backend_map & item_mask;
835 mask |= (1<<i);
836 backend_map >>= item_width;
837 }
838 if (mask != 0) {
839 ctx->backend_mask = mask;
840 return;
841 }
842 }
843
844 /* otherwise backup path for older kernels */
845
846 /* create buffer for event data */
847 buffer = (struct r600_resource*)
848 pipe_buffer_create(ctx->b.screen, PIPE_BIND_CUSTOM,
849 PIPE_USAGE_STAGING, ctx->max_db*16);
850 if (!buffer)
851 goto err;
852 va = r600_resource_va(ctx->b.screen, (void*)buffer);
853
854 /* initialize buffer with zeroes */
855 results = r600_buffer_map_sync_with_rings(ctx, buffer, PIPE_TRANSFER_WRITE);
856 if (results) {
857 memset(results, 0, ctx->max_db * 4 * 4);
858 ctx->ws->buffer_unmap(buffer->cs_buf);
859
860 /* emit EVENT_WRITE for ZPASS_DONE */
Marek Olšákaa90f172014-01-21 23:44:39 +0100861 radeon_emit(cs, PKT3(PKT3_EVENT_WRITE, 2, 0));
862 radeon_emit(cs, EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1));
863 radeon_emit(cs, va);
864 radeon_emit(cs, va >> 32);
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100865
Marek Olšákbee2b962014-02-20 15:39:35 +0100866 r600_emit_reloc(ctx, &ctx->rings.gfx, buffer, RADEON_USAGE_WRITE, RADEON_PRIO_MIN);
Marek Olšák4e5c70e2014-01-21 18:01:01 +0100867
868 /* analyze results */
869 results = r600_buffer_map_sync_with_rings(ctx, buffer, PIPE_TRANSFER_READ);
870 if (results) {
871 for(i = 0; i < ctx->max_db; i++) {
872 /* at least highest bit will be set if backend is used */
873 if (results[i*4 + 1])
874 mask |= (1<<i);
875 }
876 ctx->ws->buffer_unmap(buffer->cs_buf);
877 }
878 }
879
880 pipe_resource_reference((struct pipe_resource**)&buffer, NULL);
881
882 if (mask != 0) {
883 ctx->backend_mask = mask;
884 return;
885 }
886
887err:
888 /* fallback to old method - set num_backends lower bits to 1 */
889 ctx->backend_mask = (~((uint32_t)0))>>(32-num_backends);
890 return;
891}
892
893void r600_query_init(struct r600_common_context *rctx)
894{
895 rctx->b.create_query = r600_create_query;
896 rctx->b.destroy_query = r600_destroy_query;
897 rctx->b.begin_query = r600_begin_query;
898 rctx->b.end_query = r600_end_query;
899 rctx->b.get_query_result = r600_get_query_result;
900
901 if (((struct r600_common_screen*)rctx->b.screen)->info.r600_num_backends > 0)
902 rctx->b.render_condition = r600_render_condition;
903
904 LIST_INITHEAD(&rctx->active_nontimer_queries);
Jerome Glisse1235bec2010-09-29 15:05:19 -0400905}