1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * Copyright 2010 VMware, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 /* Authors:
30 * Keith Whitwell, Qicheng Christopher Li, Brian Paul
31 */
32
33 #include "draw/draw_context.h"
34 #include "pipe/p_defines.h"
35 #include "util/u_memory.h"
36 #include "util/os_time.h"
37 #include "lp_context.h"
38 #include "lp_flush.h"
39 #include "lp_fence.h"
40 #include "lp_query.h"
41 #include "lp_screen.h"
42 #include "lp_state.h"
43 #include "lp_rast.h"
44
45
llvmpipe_query( struct pipe_query *p )46 static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
47 {
48 return (struct llvmpipe_query *)p;
49 }
50
51 static struct pipe_query *
llvmpipe_create_query(struct pipe_context *pipe, unsigned type, unsigned index)52 llvmpipe_create_query(struct pipe_context *pipe,
53 unsigned type,
54 unsigned index)
55 {
56 struct llvmpipe_query *pq;
57
58 assert(type < PIPE_QUERY_TYPES);
59
60 pq = CALLOC_STRUCT( llvmpipe_query );
61
62 if (pq) {
63 pq->type = type;
64 pq->index = index;
65 }
66
67 return (struct pipe_query *) pq;
68 }
69
70
71 static void
llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)72 llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
73 {
74 struct llvmpipe_query *pq = llvmpipe_query(q);
75
76 /* Ideally we would refcount queries & not get destroyed until the
77 * last scene had finished with us.
78 */
79 if (pq->fence) {
80 if (!lp_fence_issued(pq->fence))
81 llvmpipe_flush(pipe, NULL, __FUNCTION__);
82
83 if (!lp_fence_signalled(pq->fence))
84 lp_fence_wait(pq->fence);
85
86 lp_fence_reference(&pq->fence, NULL);
87 }
88
89 FREE(pq);
90 }
91
92
93 static bool
llvmpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, bool wait, union pipe_query_result *vresult)94 llvmpipe_get_query_result(struct pipe_context *pipe,
95 struct pipe_query *q,
96 bool wait,
97 union pipe_query_result *vresult)
98 {
99 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
100 unsigned num_threads = MAX2(1, screen->num_threads);
101 struct llvmpipe_query *pq = llvmpipe_query(q);
102 uint64_t *result = (uint64_t *)vresult;
103 int i;
104
105 if (pq->fence) {
106 /* only have a fence if there was a scene */
107 if (!lp_fence_signalled(pq->fence)) {
108 if (!lp_fence_issued(pq->fence))
109 llvmpipe_flush(pipe, NULL, __FUNCTION__);
110
111 if (!wait)
112 return false;
113
114 lp_fence_wait(pq->fence);
115 }
116 }
117
118 /* Sum the results from each of the threads:
119 */
120 *result = 0;
121
122 switch (pq->type) {
123 case PIPE_QUERY_OCCLUSION_COUNTER:
124 for (i = 0; i < num_threads; i++) {
125 *result += pq->end[i];
126 }
127 break;
128 case PIPE_QUERY_OCCLUSION_PREDICATE:
129 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
130 for (i = 0; i < num_threads; i++) {
131 /* safer (still not guaranteed) when there's an overflow */
132 vresult->b = vresult->b || pq->end[i];
133 }
134 break;
135 case PIPE_QUERY_TIMESTAMP:
136 for (i = 0; i < num_threads; i++) {
137 if (pq->end[i] > *result) {
138 *result = pq->end[i];
139 }
140 }
141 break;
142 case PIPE_QUERY_TIME_ELAPSED: {
143 uint64_t start = (uint64_t)-1, end = 0;
144 for (i = 0; i < num_threads; i++) {
145 if (pq->start[i] && pq->start[i] < start)
146 start = pq->start[i];
147 if (pq->end[i] && pq->end[i] > end)
148 end = pq->end[i];
149 }
150 *result = end - start;
151 break;
152 }
153 case PIPE_QUERY_TIMESTAMP_DISJOINT: {
154 struct pipe_query_data_timestamp_disjoint *td =
155 (struct pipe_query_data_timestamp_disjoint *)vresult;
156 /* os_get_time_nano return nanoseconds */
157 td->frequency = UINT64_C(1000000000);
158 td->disjoint = false;
159 }
160 break;
161 case PIPE_QUERY_GPU_FINISHED:
162 vresult->b = true;
163 break;
164 case PIPE_QUERY_PRIMITIVES_GENERATED:
165 *result = pq->num_primitives_generated[0];
166 break;
167 case PIPE_QUERY_PRIMITIVES_EMITTED:
168 *result = pq->num_primitives_written[0];
169 break;
170 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
171 vresult->b = false;
172 for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++)
173 vresult->b |= pq->num_primitives_generated[s] > pq->num_primitives_written[s];
174 break;
175 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
176 vresult->b = pq->num_primitives_generated[0] > pq->num_primitives_written[0];
177 break;
178 case PIPE_QUERY_SO_STATISTICS: {
179 struct pipe_query_data_so_statistics *stats =
180 (struct pipe_query_data_so_statistics *)vresult;
181 stats->num_primitives_written = pq->num_primitives_written[0];
182 stats->primitives_storage_needed = pq->num_primitives_generated[0];
183 }
184 break;
185 case PIPE_QUERY_PIPELINE_STATISTICS: {
186 struct pipe_query_data_pipeline_statistics *stats =
187 (struct pipe_query_data_pipeline_statistics *)vresult;
188 /* only ps_invocations come from binned query */
189 for (i = 0; i < num_threads; i++) {
190 pq->stats.ps_invocations += pq->end[i];
191 }
192 pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
193 *stats = pq->stats;
194 }
195 break;
196 default:
197 assert(0);
198 break;
199 }
200
201 return true;
202 }
203
204 static void
llvmpipe_get_query_result_resource(struct pipe_context *pipe, struct pipe_query *q, enum pipe_query_flags flags, enum pipe_query_value_type result_type, int index, struct pipe_resource *resource, unsigned offset)205 llvmpipe_get_query_result_resource(struct pipe_context *pipe,
206 struct pipe_query *q,
207 enum pipe_query_flags flags,
208 enum pipe_query_value_type result_type,
209 int index,
210 struct pipe_resource *resource,
211 unsigned offset)
212 {
213 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
214 unsigned num_threads = MAX2(1, screen->num_threads);
215 struct llvmpipe_query *pq = llvmpipe_query(q);
216 struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
217 bool unsignalled = false;
218 if (pq->fence) {
219 /* only have a fence if there was a scene */
220 if (!lp_fence_signalled(pq->fence)) {
221 if (!lp_fence_issued(pq->fence))
222 llvmpipe_flush(pipe, NULL, __FUNCTION__);
223
224 if (flags & PIPE_QUERY_WAIT)
225 lp_fence_wait(pq->fence);
226 }
227 unsignalled = !lp_fence_signalled(pq->fence);
228 }
229
230
231 uint64_t value = 0, value2 = 0;
232 unsigned num_values = 1;
233 if (index == -1)
234 if (unsignalled)
235 value = 0;
236 else
237 value = 1;
238 else {
239 unsigned i;
240
241 /* don't write a value if fence hasn't signalled,
242 and partial isn't set . */
243 if (unsignalled && !(flags & PIPE_QUERY_PARTIAL))
244 return;
245 switch (pq->type) {
246 case PIPE_QUERY_OCCLUSION_COUNTER:
247 for (i = 0; i < num_threads; i++) {
248 value += pq->end[i];
249 }
250 break;
251 case PIPE_QUERY_OCCLUSION_PREDICATE:
252 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
253 for (i = 0; i < num_threads; i++) {
254 /* safer (still not guaranteed) when there's an overflow */
255 value = value || pq->end[i];
256 }
257 break;
258 case PIPE_QUERY_PRIMITIVES_GENERATED:
259 value = pq->num_primitives_generated[0];
260 break;
261 case PIPE_QUERY_PRIMITIVES_EMITTED:
262 value = pq->num_primitives_written[0];
263 break;
264 case PIPE_QUERY_TIMESTAMP:
265 for (i = 0; i < num_threads; i++) {
266 if (pq->end[i] > value) {
267 value = pq->end[i];
268 }
269 }
270 break;
271 case PIPE_QUERY_TIME_ELAPSED: {
272 uint64_t start = (uint64_t)-1, end = 0;
273 for (i = 0; i < num_threads; i++) {
274 if (pq->start[i] && pq->start[i] < start)
275 start = pq->start[i];
276 if (pq->end[i] && pq->end[i] > end)
277 end = pq->end[i];
278 }
279 value = end - start;
280 break;
281 }
282 case PIPE_QUERY_SO_STATISTICS:
283 value = pq->num_primitives_written[0];
284 value2 = pq->num_primitives_generated[0];
285 num_values = 2;
286 break;
287 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
288 value = 0;
289 for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++)
290 value |= !!(pq->num_primitives_generated[s] > pq->num_primitives_written[s]);
291 break;
292 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
293 value = !!(pq->num_primitives_generated[0] > pq->num_primitives_written[0]);
294 break;
295 case PIPE_QUERY_PIPELINE_STATISTICS:
296 switch ((enum pipe_statistics_query_index)index) {
297 case PIPE_STAT_QUERY_IA_VERTICES:
298 value = pq->stats.ia_vertices;
299 break;
300 case PIPE_STAT_QUERY_IA_PRIMITIVES:
301 value = pq->stats.ia_primitives;
302 break;
303 case PIPE_STAT_QUERY_VS_INVOCATIONS:
304 value = pq->stats.vs_invocations;
305 break;
306 case PIPE_STAT_QUERY_GS_INVOCATIONS:
307 value = pq->stats.gs_invocations;
308 break;
309 case PIPE_STAT_QUERY_GS_PRIMITIVES:
310 value = pq->stats.gs_primitives;
311 break;
312 case PIPE_STAT_QUERY_C_INVOCATIONS:
313 value = pq->stats.c_invocations;
314 break;
315 case PIPE_STAT_QUERY_C_PRIMITIVES:
316 value = pq->stats.c_primitives;
317 break;
318 case PIPE_STAT_QUERY_PS_INVOCATIONS:
319 value = 0;
320 for (i = 0; i < num_threads; i++) {
321 value += pq->end[i];
322 }
323 value *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
324 break;
325 case PIPE_STAT_QUERY_HS_INVOCATIONS:
326 value = pq->stats.hs_invocations;
327 break;
328 case PIPE_STAT_QUERY_DS_INVOCATIONS:
329 value = pq->stats.ds_invocations;
330 break;
331 case PIPE_STAT_QUERY_CS_INVOCATIONS:
332 value = pq->stats.cs_invocations;
333 break;
334 }
335 break;
336 default:
337 fprintf(stderr, "Unknown query type %d\n", pq->type);
338 break;
339 }
340 }
341
342 void *dst = (uint8_t *)lpr->data + offset;
343
344 for (unsigned i = 0; i < num_values; i++) {
345
346 if (i == 1) {
347 value = value2;
348 dst = (char *)dst + ((result_type == PIPE_QUERY_TYPE_I64 ||
349 result_type == PIPE_QUERY_TYPE_U64) ? 8 : 4);
350 }
351 switch (result_type) {
352 case PIPE_QUERY_TYPE_I32: {
353 int32_t *iptr = (int32_t *)dst;
354 if (value > 0x7fffffff)
355 *iptr = 0x7fffffff;
356 else
357 *iptr = (int32_t)value;
358 break;
359 }
360 case PIPE_QUERY_TYPE_U32: {
361 uint32_t *uptr = (uint32_t *)dst;
362 if (value > 0xffffffff)
363 *uptr = 0xffffffff;
364 else
365 *uptr = (uint32_t)value;
366 break;
367 }
368 case PIPE_QUERY_TYPE_I64: {
369 int64_t *iptr = (int64_t *)dst;
370 *iptr = (int64_t)value;
371 break;
372 }
373 case PIPE_QUERY_TYPE_U64: {
374 uint64_t *uptr = (uint64_t *)dst;
375 *uptr = (uint64_t)value;
376 break;
377 }
378 }
379 }
380 }
381
382 static bool
llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)383 llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
384 {
385 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
386 struct llvmpipe_query *pq = llvmpipe_query(q);
387
388 /* Check if the query is already in the scene. If so, we need to
389 * flush the scene now. Real apps shouldn't re-use a query in a
390 * frame of rendering.
391 */
392 if (pq->fence && !lp_fence_issued(pq->fence)) {
393 llvmpipe_finish(pipe, __FUNCTION__);
394 }
395
396
397 memset(pq->start, 0, sizeof(pq->start));
398 memset(pq->end, 0, sizeof(pq->end));
399 lp_setup_begin_query(llvmpipe->setup, pq);
400
401 switch (pq->type) {
402 case PIPE_QUERY_PRIMITIVES_EMITTED:
403 pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
404 break;
405 case PIPE_QUERY_PRIMITIVES_GENERATED:
406 pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
407 llvmpipe->active_primgen_queries++;
408 break;
409 case PIPE_QUERY_SO_STATISTICS:
410 pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
411 pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
412 break;
413 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
414 for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) {
415 pq->num_primitives_written[s] = llvmpipe->so_stats[s].num_primitives_written;
416 pq->num_primitives_generated[s] = llvmpipe->so_stats[s].primitives_storage_needed;
417 }
418 break;
419 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
420 pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
421 pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
422 break;
423 case PIPE_QUERY_PIPELINE_STATISTICS:
424 /* reset our cache */
425 if (llvmpipe->active_statistics_queries == 0) {
426 memset(&llvmpipe->pipeline_statistics, 0,
427 sizeof(llvmpipe->pipeline_statistics));
428 }
429 memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats));
430 llvmpipe->active_statistics_queries++;
431 break;
432 case PIPE_QUERY_OCCLUSION_COUNTER:
433 case PIPE_QUERY_OCCLUSION_PREDICATE:
434 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
435 llvmpipe->active_occlusion_queries++;
436 llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
437 break;
438 default:
439 break;
440 }
441 return true;
442 }
443
444
445 static bool
llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)446 llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
447 {
448 struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
449 struct llvmpipe_query *pq = llvmpipe_query(q);
450
451 lp_setup_end_query(llvmpipe->setup, pq);
452
453 switch (pq->type) {
454
455 case PIPE_QUERY_PRIMITIVES_EMITTED:
456 pq->num_primitives_written[0] =
457 llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
458 break;
459 case PIPE_QUERY_PRIMITIVES_GENERATED:
460 assert(llvmpipe->active_primgen_queries);
461 llvmpipe->active_primgen_queries--;
462 pq->num_primitives_generated[0] =
463 llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
464 break;
465 case PIPE_QUERY_SO_STATISTICS:
466 pq->num_primitives_written[0] =
467 llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
468 pq->num_primitives_generated[0] =
469 llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
470 break;
471 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
472 for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) {
473 pq->num_primitives_written[s] =
474 llvmpipe->so_stats[s].num_primitives_written - pq->num_primitives_written[s];
475 pq->num_primitives_generated[s] =
476 llvmpipe->so_stats[s].primitives_storage_needed - pq->num_primitives_generated[s];
477 }
478 break;
479 case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
480 pq->num_primitives_written[0] =
481 llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
482 pq->num_primitives_generated[0] =
483 llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
484 break;
485 case PIPE_QUERY_PIPELINE_STATISTICS:
486 pq->stats.ia_vertices =
487 llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices;
488 pq->stats.ia_primitives =
489 llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives;
490 pq->stats.vs_invocations =
491 llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations;
492 pq->stats.gs_invocations =
493 llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations;
494 pq->stats.gs_primitives =
495 llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives;
496 pq->stats.c_invocations =
497 llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations;
498 pq->stats.c_primitives =
499 llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives;
500 pq->stats.ps_invocations =
501 llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations;
502 pq->stats.cs_invocations =
503 llvmpipe->pipeline_statistics.cs_invocations - pq->stats.cs_invocations;
504 pq->stats.hs_invocations =
505 llvmpipe->pipeline_statistics.hs_invocations - pq->stats.hs_invocations;
506 pq->stats.ds_invocations =
507 llvmpipe->pipeline_statistics.ds_invocations - pq->stats.ds_invocations;
508 llvmpipe->active_statistics_queries--;
509 break;
510 case PIPE_QUERY_OCCLUSION_COUNTER:
511 case PIPE_QUERY_OCCLUSION_PREDICATE:
512 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
513 assert(llvmpipe->active_occlusion_queries);
514 llvmpipe->active_occlusion_queries--;
515 llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
516 break;
517 default:
518 break;
519 }
520
521 return true;
522 }
523
524 boolean
llvmpipe_check_render_cond(struct llvmpipe_context *lp)525 llvmpipe_check_render_cond(struct llvmpipe_context *lp)
526 {
527 struct pipe_context *pipe = &lp->pipe;
528 boolean b, wait;
529 uint64_t result;
530
531 if (lp->render_cond_buffer) {
532 uint32_t data = *(uint32_t *)((char *)lp->render_cond_buffer->data + lp->render_cond_offset);
533 return (!data) == lp->render_cond_cond;
534 }
535 if (!lp->render_cond_query)
536 return TRUE; /* no query predicate, draw normally */
537
538 wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
539 lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
540
541 b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result);
542 if (b)
543 return ((!result) == lp->render_cond_cond);
544 else
545 return TRUE;
546 }
547
548 static void
llvmpipe_set_active_query_state(struct pipe_context *pipe, bool enable)549 llvmpipe_set_active_query_state(struct pipe_context *pipe, bool enable)
550 {
551 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
552
553 llvmpipe->queries_disabled = !enable;
554 /* for OQs we need to regenerate the fragment shader */
555 llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
556 }
557
llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )558 void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
559 {
560 llvmpipe->pipe.create_query = llvmpipe_create_query;
561 llvmpipe->pipe.destroy_query = llvmpipe_destroy_query;
562 llvmpipe->pipe.begin_query = llvmpipe_begin_query;
563 llvmpipe->pipe.end_query = llvmpipe_end_query;
564 llvmpipe->pipe.get_query_result = llvmpipe_get_query_result;
565 llvmpipe->pipe.get_query_result_resource = llvmpipe_get_query_result_resource;
566 llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state;
567 }
568
569
570