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
46static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
47{
48   return (struct llvmpipe_query *)p;
49}
50
51static struct pipe_query *
52llvmpipe_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
71static void
72llvmpipe_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
93static bool
94llvmpipe_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
204static void
205llvmpipe_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
382static bool
383llvmpipe_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
445static bool
446llvmpipe_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
524boolean
525llvmpipe_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
548static void
549llvmpipe_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
558void 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