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