14a49301eSmrg/**************************************************************************
24a49301eSmrg *
3af69d88dSmrg * Copyright 2007 VMware, Inc.
43464ebd5Sriastradh * Copyright 2010 VMware, Inc.
54a49301eSmrg * All Rights Reserved.
64a49301eSmrg *
74a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
84a49301eSmrg * copy of this software and associated documentation files (the
94a49301eSmrg * "Software"), to deal in the Software without restriction, including
104a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
114a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
124a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
134a49301eSmrg * the following conditions:
144a49301eSmrg *
154a49301eSmrg * The above copyright notice and this permission notice (including the
164a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
174a49301eSmrg * of the Software.
184a49301eSmrg *
194a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
204a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
214a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
223464ebd5Sriastradh * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
234a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
244a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
254a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
264a49301eSmrg *
274a49301eSmrg **************************************************************************/
284a49301eSmrg
293464ebd5Sriastradh/* Authors:
303464ebd5Sriastradh *    Keith Whitwell, Qicheng Christopher Li, Brian Paul
314a49301eSmrg */
324a49301eSmrg
334a49301eSmrg#include "draw/draw_context.h"
344a49301eSmrg#include "pipe/p_defines.h"
354a49301eSmrg#include "util/u_memory.h"
3601e04c3fSmrg#include "util/os_time.h"
374a49301eSmrg#include "lp_context.h"
383464ebd5Sriastradh#include "lp_flush.h"
393464ebd5Sriastradh#include "lp_fence.h"
404a49301eSmrg#include "lp_query.h"
41af69d88dSmrg#include "lp_screen.h"
424a49301eSmrg#include "lp_state.h"
43af69d88dSmrg#include "lp_rast.h"
444a49301eSmrg
454a49301eSmrg
464a49301eSmrgstatic struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
474a49301eSmrg{
484a49301eSmrg   return (struct llvmpipe_query *)p;
494a49301eSmrg}
504a49301eSmrg
514a49301eSmrgstatic struct pipe_query *
524a49301eSmrgllvmpipe_create_query(struct pipe_context *pipe,
53af69d88dSmrg                      unsigned type,
54af69d88dSmrg                      unsigned index)
554a49301eSmrg{
563464ebd5Sriastradh   struct llvmpipe_query *pq;
573464ebd5Sriastradh
58af69d88dSmrg   assert(type < PIPE_QUERY_TYPES);
593464ebd5Sriastradh
603464ebd5Sriastradh   pq = CALLOC_STRUCT( llvmpipe_query );
613464ebd5Sriastradh
62af69d88dSmrg   if (pq) {
63af69d88dSmrg      pq->type = type;
647ec681f3Smrg      pq->index = index;
65af69d88dSmrg   }
66af69d88dSmrg
673464ebd5Sriastradh   return (struct pipe_query *) pq;
684a49301eSmrg}
694a49301eSmrg
704a49301eSmrg
714a49301eSmrgstatic void
724a49301eSmrgllvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
734a49301eSmrg{
743464ebd5Sriastradh   struct llvmpipe_query *pq = llvmpipe_query(q);
753464ebd5Sriastradh
763464ebd5Sriastradh   /* Ideally we would refcount queries & not get destroyed until the
773464ebd5Sriastradh    * last scene had finished with us.
783464ebd5Sriastradh    */
793464ebd5Sriastradh   if (pq->fence) {
803464ebd5Sriastradh      if (!lp_fence_issued(pq->fence))
813464ebd5Sriastradh         llvmpipe_flush(pipe, NULL, __FUNCTION__);
823464ebd5Sriastradh
833464ebd5Sriastradh      if (!lp_fence_signalled(pq->fence))
843464ebd5Sriastradh         lp_fence_wait(pq->fence);
853464ebd5Sriastradh
863464ebd5Sriastradh      lp_fence_reference(&pq->fence, NULL);
873464ebd5Sriastradh   }
883464ebd5Sriastradh
893464ebd5Sriastradh   FREE(pq);
903464ebd5Sriastradh}
913464ebd5Sriastradh
923464ebd5Sriastradh
937ec681f3Smrgstatic bool
943464ebd5Sriastradhllvmpipe_get_query_result(struct pipe_context *pipe,
953464ebd5Sriastradh                          struct pipe_query *q,
967ec681f3Smrg                          bool wait,
97af69d88dSmrg                          union pipe_query_result *vresult)
983464ebd5Sriastradh{
99af69d88dSmrg   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
100af69d88dSmrg   unsigned num_threads = MAX2(1, screen->num_threads);
1013464ebd5Sriastradh   struct llvmpipe_query *pq = llvmpipe_query(q);
1023464ebd5Sriastradh   uint64_t *result = (uint64_t *)vresult;
1033464ebd5Sriastradh   int i;
1043464ebd5Sriastradh
105af69d88dSmrg   if (pq->fence) {
106af69d88dSmrg      /* only have a fence if there was a scene */
107af69d88dSmrg      if (!lp_fence_signalled(pq->fence)) {
108af69d88dSmrg         if (!lp_fence_issued(pq->fence))
109af69d88dSmrg            llvmpipe_flush(pipe, NULL, __FUNCTION__);
1103464ebd5Sriastradh
111af69d88dSmrg         if (!wait)
1127ec681f3Smrg            return false;
1133464ebd5Sriastradh
114af69d88dSmrg         lp_fence_wait(pq->fence);
115af69d88dSmrg      }
1163464ebd5Sriastradh   }
1173464ebd5Sriastradh
1183464ebd5Sriastradh   /* Sum the results from each of the threads:
1193464ebd5Sriastradh    */
1203464ebd5Sriastradh   *result = 0;
121af69d88dSmrg
122af69d88dSmrg   switch (pq->type) {
123af69d88dSmrg   case PIPE_QUERY_OCCLUSION_COUNTER:
124af69d88dSmrg      for (i = 0; i < num_threads; i++) {
125af69d88dSmrg         *result += pq->end[i];
126af69d88dSmrg      }
127af69d88dSmrg      break;
128af69d88dSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE:
12901e04c3fSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
130af69d88dSmrg      for (i = 0; i < num_threads; i++) {
131af69d88dSmrg         /* safer (still not guaranteed) when there's an overflow */
132af69d88dSmrg         vresult->b = vresult->b || pq->end[i];
133af69d88dSmrg      }
134af69d88dSmrg      break;
135af69d88dSmrg   case PIPE_QUERY_TIMESTAMP:
136af69d88dSmrg      for (i = 0; i < num_threads; i++) {
137af69d88dSmrg         if (pq->end[i] > *result) {
138af69d88dSmrg            *result = pq->end[i];
139af69d88dSmrg         }
140af69d88dSmrg      }
141af69d88dSmrg      break;
1427ec681f3Smrg   case PIPE_QUERY_TIME_ELAPSED: {
1437ec681f3Smrg      uint64_t start = (uint64_t)-1, end = 0;
1447ec681f3Smrg      for (i = 0; i < num_threads; i++) {
1457ec681f3Smrg         if (pq->start[i] && pq->start[i] < start)
1467ec681f3Smrg            start = pq->start[i];
1477ec681f3Smrg         if (pq->end[i] && pq->end[i] > end)
1487ec681f3Smrg            end = pq->end[i];
1497ec681f3Smrg      }
1507ec681f3Smrg      *result = end - start;
1517ec681f3Smrg      break;
1527ec681f3Smrg   }
153af69d88dSmrg   case PIPE_QUERY_TIMESTAMP_DISJOINT: {
154af69d88dSmrg      struct pipe_query_data_timestamp_disjoint *td =
155af69d88dSmrg         (struct pipe_query_data_timestamp_disjoint *)vresult;
156af69d88dSmrg      /* os_get_time_nano return nanoseconds */
157af69d88dSmrg      td->frequency = UINT64_C(1000000000);
1587ec681f3Smrg      td->disjoint = false;
159af69d88dSmrg   }
160af69d88dSmrg      break;
161af69d88dSmrg   case PIPE_QUERY_GPU_FINISHED:
1627ec681f3Smrg      vresult->b = true;
163af69d88dSmrg      break;
164af69d88dSmrg   case PIPE_QUERY_PRIMITIVES_GENERATED:
1657ec681f3Smrg      *result = pq->num_primitives_generated[0];
166af69d88dSmrg      break;
167af69d88dSmrg   case PIPE_QUERY_PRIMITIVES_EMITTED:
1687ec681f3Smrg      *result = pq->num_primitives_written[0];
169af69d88dSmrg      break;
17001e04c3fSmrg   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
1717ec681f3Smrg      vresult->b = false;
1727ec681f3Smrg      for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++)
1737ec681f3Smrg         vresult->b |= pq->num_primitives_generated[s] > pq->num_primitives_written[s];
1747ec681f3Smrg      break;
1757ec681f3Smrg   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
1767ec681f3Smrg      vresult->b = pq->num_primitives_generated[0] > pq->num_primitives_written[0];
177af69d88dSmrg      break;
178af69d88dSmrg   case PIPE_QUERY_SO_STATISTICS: {
179af69d88dSmrg      struct pipe_query_data_so_statistics *stats =
180af69d88dSmrg         (struct pipe_query_data_so_statistics *)vresult;
1817ec681f3Smrg      stats->num_primitives_written = pq->num_primitives_written[0];
1827ec681f3Smrg      stats->primitives_storage_needed = pq->num_primitives_generated[0];
183af69d88dSmrg   }
184af69d88dSmrg      break;
185af69d88dSmrg   case PIPE_QUERY_PIPELINE_STATISTICS: {
186af69d88dSmrg      struct pipe_query_data_pipeline_statistics *stats =
187af69d88dSmrg         (struct pipe_query_data_pipeline_statistics *)vresult;
188af69d88dSmrg      /* only ps_invocations come from binned query */
189af69d88dSmrg      for (i = 0; i < num_threads; i++) {
190af69d88dSmrg         pq->stats.ps_invocations += pq->end[i];
191af69d88dSmrg      }
192af69d88dSmrg      pq->stats.ps_invocations *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
193af69d88dSmrg      *stats = pq->stats;
194af69d88dSmrg   }
195af69d88dSmrg      break;
196af69d88dSmrg   default:
197af69d88dSmrg      assert(0);
198af69d88dSmrg      break;
1993464ebd5Sriastradh   }
2003464ebd5Sriastradh
2017ec681f3Smrg   return true;
2024a49301eSmrg}
2034a49301eSmrg
2047ec681f3Smrgstatic void
2057ec681f3Smrgllvmpipe_get_query_result_resource(struct pipe_context *pipe,
2067ec681f3Smrg                                   struct pipe_query *q,
2077ec681f3Smrg                                   bool wait,
2087ec681f3Smrg                                   enum pipe_query_value_type result_type,
2097ec681f3Smrg                                   int index,
2107ec681f3Smrg                                   struct pipe_resource *resource,
2117ec681f3Smrg                                   unsigned offset)
2127ec681f3Smrg{
2137ec681f3Smrg   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
2147ec681f3Smrg   unsigned num_threads = MAX2(1, screen->num_threads);
2157ec681f3Smrg   struct llvmpipe_query *pq = llvmpipe_query(q);
2167ec681f3Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
2177ec681f3Smrg   bool unsignalled = false;
2187ec681f3Smrg   if (pq->fence) {
2197ec681f3Smrg      /* only have a fence if there was a scene */
2207ec681f3Smrg      if (!lp_fence_signalled(pq->fence)) {
2217ec681f3Smrg         if (!lp_fence_issued(pq->fence))
2227ec681f3Smrg            llvmpipe_flush(pipe, NULL, __FUNCTION__);
2237ec681f3Smrg
2247ec681f3Smrg         if (wait)
2257ec681f3Smrg            lp_fence_wait(pq->fence);
2267ec681f3Smrg      }
2277ec681f3Smrg      unsignalled = !lp_fence_signalled(pq->fence);
2287ec681f3Smrg   }
2297ec681f3Smrg
2304a49301eSmrg
2317ec681f3Smrg   uint64_t value = 0, value2 = 0;
2327ec681f3Smrg   unsigned num_values = 1;
2337ec681f3Smrg   if (index == -1)
2347ec681f3Smrg      if (unsignalled)
2357ec681f3Smrg         value = 0;
2367ec681f3Smrg      else
2377ec681f3Smrg         value = 1;
2387ec681f3Smrg   else {
2397ec681f3Smrg      unsigned i;
2407ec681f3Smrg
2417ec681f3Smrg      switch (pq->type) {
2427ec681f3Smrg      case PIPE_QUERY_OCCLUSION_COUNTER:
2437ec681f3Smrg         for (i = 0; i < num_threads; i++) {
2447ec681f3Smrg            value += pq->end[i];
2457ec681f3Smrg         }
2467ec681f3Smrg         break;
2477ec681f3Smrg      case PIPE_QUERY_OCCLUSION_PREDICATE:
2487ec681f3Smrg      case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
2497ec681f3Smrg         for (i = 0; i < num_threads; i++) {
2507ec681f3Smrg            /* safer (still not guaranteed) when there's an overflow */
2517ec681f3Smrg            value = value || pq->end[i];
2527ec681f3Smrg         }
2537ec681f3Smrg         break;
2547ec681f3Smrg      case PIPE_QUERY_PRIMITIVES_GENERATED:
2557ec681f3Smrg         value = pq->num_primitives_generated[0];
2567ec681f3Smrg         break;
2577ec681f3Smrg      case PIPE_QUERY_PRIMITIVES_EMITTED:
2587ec681f3Smrg         value = pq->num_primitives_written[0];
2597ec681f3Smrg         break;
2607ec681f3Smrg      case PIPE_QUERY_TIMESTAMP:
2617ec681f3Smrg         for (i = 0; i < num_threads; i++) {
2627ec681f3Smrg            if (pq->end[i] > value) {
2637ec681f3Smrg               value = pq->end[i];
2647ec681f3Smrg            }
2657ec681f3Smrg         }
2667ec681f3Smrg         break;
2677ec681f3Smrg      case PIPE_QUERY_TIME_ELAPSED: {
2687ec681f3Smrg         uint64_t start = (uint64_t)-1, end = 0;
2697ec681f3Smrg         for (i = 0; i < num_threads; i++) {
2707ec681f3Smrg            if (pq->start[i] && pq->start[i] < start)
2717ec681f3Smrg               start = pq->start[i];
2727ec681f3Smrg            if (pq->end[i] && pq->end[i] > end)
2737ec681f3Smrg               end = pq->end[i];
2747ec681f3Smrg         }
2757ec681f3Smrg         value = end - start;
2767ec681f3Smrg         break;
2777ec681f3Smrg      }
2787ec681f3Smrg      case PIPE_QUERY_SO_STATISTICS:
2797ec681f3Smrg         value = pq->num_primitives_written[0];
2807ec681f3Smrg         value2 = pq->num_primitives_generated[0];
2817ec681f3Smrg         num_values = 2;
2827ec681f3Smrg         break;
2837ec681f3Smrg      case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
2847ec681f3Smrg         value = 0;
2857ec681f3Smrg         for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++)
2867ec681f3Smrg            value |= !!(pq->num_primitives_generated[s] > pq->num_primitives_written[s]);
2877ec681f3Smrg         break;
2887ec681f3Smrg      case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
2897ec681f3Smrg         value = !!(pq->num_primitives_generated[0] > pq->num_primitives_written[0]);
2907ec681f3Smrg         break;
2917ec681f3Smrg      case PIPE_QUERY_PIPELINE_STATISTICS:
2927ec681f3Smrg         switch ((enum pipe_statistics_query_index)index) {
2937ec681f3Smrg         case PIPE_STAT_QUERY_IA_VERTICES:
2947ec681f3Smrg            value = pq->stats.ia_vertices;
2957ec681f3Smrg            break;
2967ec681f3Smrg         case PIPE_STAT_QUERY_IA_PRIMITIVES:
2977ec681f3Smrg            value = pq->stats.ia_primitives;
2987ec681f3Smrg            break;
2997ec681f3Smrg         case PIPE_STAT_QUERY_VS_INVOCATIONS:
3007ec681f3Smrg            value = pq->stats.vs_invocations;
3017ec681f3Smrg            break;
3027ec681f3Smrg         case PIPE_STAT_QUERY_GS_INVOCATIONS:
3037ec681f3Smrg            value = pq->stats.gs_invocations;
3047ec681f3Smrg            break;
3057ec681f3Smrg         case PIPE_STAT_QUERY_GS_PRIMITIVES:
3067ec681f3Smrg            value = pq->stats.gs_primitives;
3077ec681f3Smrg            break;
3087ec681f3Smrg         case PIPE_STAT_QUERY_C_INVOCATIONS:
3097ec681f3Smrg            value = pq->stats.c_invocations;
3107ec681f3Smrg            break;
3117ec681f3Smrg         case PIPE_STAT_QUERY_C_PRIMITIVES:
3127ec681f3Smrg            value = pq->stats.c_primitives;
3137ec681f3Smrg            break;
3147ec681f3Smrg         case PIPE_STAT_QUERY_PS_INVOCATIONS:
3157ec681f3Smrg            value = 0;
3167ec681f3Smrg            for (i = 0; i < num_threads; i++) {
3177ec681f3Smrg               value += pq->end[i];
3187ec681f3Smrg            }
3197ec681f3Smrg            value *= LP_RASTER_BLOCK_SIZE * LP_RASTER_BLOCK_SIZE;
3207ec681f3Smrg            break;
3217ec681f3Smrg         case PIPE_STAT_QUERY_HS_INVOCATIONS:
3227ec681f3Smrg            value = pq->stats.hs_invocations;
3237ec681f3Smrg            break;
3247ec681f3Smrg         case PIPE_STAT_QUERY_DS_INVOCATIONS:
3257ec681f3Smrg            value = pq->stats.ds_invocations;
3267ec681f3Smrg            break;
3277ec681f3Smrg         case PIPE_STAT_QUERY_CS_INVOCATIONS:
3287ec681f3Smrg            value = pq->stats.cs_invocations;
3297ec681f3Smrg            break;
3307ec681f3Smrg         }
3317ec681f3Smrg         break;
3327ec681f3Smrg      default:
3337ec681f3Smrg         fprintf(stderr, "Unknown query type %d\n", pq->type);
3347ec681f3Smrg         break;
3357ec681f3Smrg      }
3367ec681f3Smrg   }
3377ec681f3Smrg
3387ec681f3Smrg   void *dst = (uint8_t *)lpr->data + offset;
3397ec681f3Smrg
3407ec681f3Smrg   for (unsigned i = 0; i < num_values; i++) {
3417ec681f3Smrg
3427ec681f3Smrg      if (i == 1) {
3437ec681f3Smrg         value = value2;
3447ec681f3Smrg         dst = (char *)dst + ((result_type == PIPE_QUERY_TYPE_I64 ||
3457ec681f3Smrg                               result_type == PIPE_QUERY_TYPE_U64) ? 8 : 4);
3467ec681f3Smrg      }
3477ec681f3Smrg      switch (result_type) {
3487ec681f3Smrg      case PIPE_QUERY_TYPE_I32: {
3497ec681f3Smrg         int32_t *iptr = (int32_t *)dst;
3507ec681f3Smrg         if (value > 0x7fffffff)
3517ec681f3Smrg            *iptr = 0x7fffffff;
3527ec681f3Smrg         else
3537ec681f3Smrg            *iptr = (int32_t)value;
3547ec681f3Smrg         break;
3557ec681f3Smrg      }
3567ec681f3Smrg      case PIPE_QUERY_TYPE_U32: {
3577ec681f3Smrg         uint32_t *uptr = (uint32_t *)dst;
3587ec681f3Smrg         if (value > 0xffffffff)
3597ec681f3Smrg            *uptr = 0xffffffff;
3607ec681f3Smrg         else
3617ec681f3Smrg            *uptr = (uint32_t)value;
3627ec681f3Smrg         break;
3637ec681f3Smrg      }
3647ec681f3Smrg      case PIPE_QUERY_TYPE_I64: {
3657ec681f3Smrg         int64_t *iptr = (int64_t *)dst;
3667ec681f3Smrg         *iptr = (int64_t)value;
3677ec681f3Smrg         break;
3687ec681f3Smrg      }
3697ec681f3Smrg      case PIPE_QUERY_TYPE_U64: {
3707ec681f3Smrg         uint64_t *uptr = (uint64_t *)dst;
3717ec681f3Smrg         *uptr = (uint64_t)value;
3727ec681f3Smrg         break;
3737ec681f3Smrg      }
3747ec681f3Smrg      }
3757ec681f3Smrg   }
3767ec681f3Smrg}
3777ec681f3Smrg
3787ec681f3Smrgstatic bool
3794a49301eSmrgllvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
3804a49301eSmrg{
3814a49301eSmrg   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
3823464ebd5Sriastradh   struct llvmpipe_query *pq = llvmpipe_query(q);
3833464ebd5Sriastradh
3843464ebd5Sriastradh   /* Check if the query is already in the scene.  If so, we need to
3853464ebd5Sriastradh    * flush the scene now.  Real apps shouldn't re-use a query in a
3863464ebd5Sriastradh    * frame of rendering.
3873464ebd5Sriastradh    */
3883464ebd5Sriastradh   if (pq->fence && !lp_fence_issued(pq->fence)) {
3893464ebd5Sriastradh      llvmpipe_finish(pipe, __FUNCTION__);
3903464ebd5Sriastradh   }
3913464ebd5Sriastradh
3923464ebd5Sriastradh
393af69d88dSmrg   memset(pq->start, 0, sizeof(pq->start));
394af69d88dSmrg   memset(pq->end, 0, sizeof(pq->end));
3953464ebd5Sriastradh   lp_setup_begin_query(llvmpipe->setup, pq);
3963464ebd5Sriastradh
397af69d88dSmrg   switch (pq->type) {
398af69d88dSmrg   case PIPE_QUERY_PRIMITIVES_EMITTED:
3997ec681f3Smrg      pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
400af69d88dSmrg      break;
401af69d88dSmrg   case PIPE_QUERY_PRIMITIVES_GENERATED:
4027ec681f3Smrg      pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
4037ec681f3Smrg      llvmpipe->active_primgen_queries++;
404af69d88dSmrg      break;
405af69d88dSmrg   case PIPE_QUERY_SO_STATISTICS:
4067ec681f3Smrg      pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
4077ec681f3Smrg      pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
408af69d88dSmrg      break;
40901e04c3fSmrg   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
4107ec681f3Smrg      for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) {
4117ec681f3Smrg         pq->num_primitives_written[s] = llvmpipe->so_stats[s].num_primitives_written;
4127ec681f3Smrg         pq->num_primitives_generated[s] = llvmpipe->so_stats[s].primitives_storage_needed;
4137ec681f3Smrg      }
4147ec681f3Smrg      break;
4157ec681f3Smrg   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
4167ec681f3Smrg      pq->num_primitives_written[0] = llvmpipe->so_stats[pq->index].num_primitives_written;
4177ec681f3Smrg      pq->num_primitives_generated[0] = llvmpipe->so_stats[pq->index].primitives_storage_needed;
418af69d88dSmrg      break;
419af69d88dSmrg   case PIPE_QUERY_PIPELINE_STATISTICS:
420af69d88dSmrg      /* reset our cache */
421af69d88dSmrg      if (llvmpipe->active_statistics_queries == 0) {
422af69d88dSmrg         memset(&llvmpipe->pipeline_statistics, 0,
423af69d88dSmrg                sizeof(llvmpipe->pipeline_statistics));
424af69d88dSmrg      }
425af69d88dSmrg      memcpy(&pq->stats, &llvmpipe->pipeline_statistics, sizeof(pq->stats));
426af69d88dSmrg      llvmpipe->active_statistics_queries++;
427af69d88dSmrg      break;
428af69d88dSmrg   case PIPE_QUERY_OCCLUSION_COUNTER:
429af69d88dSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE:
43001e04c3fSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
431af69d88dSmrg      llvmpipe->active_occlusion_queries++;
432af69d88dSmrg      llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
433af69d88dSmrg      break;
434af69d88dSmrg   default:
435af69d88dSmrg      break;
436af69d88dSmrg   }
43701e04c3fSmrg   return true;
4384a49301eSmrg}
4394a49301eSmrg
4404a49301eSmrg
44101e04c3fSmrgstatic bool
4424a49301eSmrgllvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
4434a49301eSmrg{
4444a49301eSmrg   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
4453464ebd5Sriastradh   struct llvmpipe_query *pq = llvmpipe_query(q);
4463464ebd5Sriastradh
4473464ebd5Sriastradh   lp_setup_end_query(llvmpipe->setup, pq);
4484a49301eSmrg
449af69d88dSmrg   switch (pq->type) {
450af69d88dSmrg
451af69d88dSmrg   case PIPE_QUERY_PRIMITIVES_EMITTED:
4527ec681f3Smrg      pq->num_primitives_written[0] =
4537ec681f3Smrg         llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
454af69d88dSmrg      break;
455af69d88dSmrg   case PIPE_QUERY_PRIMITIVES_GENERATED:
4567ec681f3Smrg      assert(llvmpipe->active_primgen_queries);
4577ec681f3Smrg      llvmpipe->active_primgen_queries--;
4587ec681f3Smrg      pq->num_primitives_generated[0] =
4597ec681f3Smrg         llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
460af69d88dSmrg      break;
461af69d88dSmrg   case PIPE_QUERY_SO_STATISTICS:
4627ec681f3Smrg      pq->num_primitives_written[0] =
4637ec681f3Smrg         llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
4647ec681f3Smrg      pq->num_primitives_generated[0] =
4657ec681f3Smrg         llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
466af69d88dSmrg      break;
46701e04c3fSmrg   case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
4687ec681f3Smrg      for (unsigned s = 0; s < PIPE_MAX_VERTEX_STREAMS; s++) {
4697ec681f3Smrg         pq->num_primitives_written[s] =
4707ec681f3Smrg            llvmpipe->so_stats[s].num_primitives_written - pq->num_primitives_written[s];
4717ec681f3Smrg         pq->num_primitives_generated[s] =
4727ec681f3Smrg            llvmpipe->so_stats[s].primitives_storage_needed - pq->num_primitives_generated[s];
4737ec681f3Smrg      }
4747ec681f3Smrg      break;
4757ec681f3Smrg   case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
4767ec681f3Smrg      pq->num_primitives_written[0] =
4777ec681f3Smrg         llvmpipe->so_stats[pq->index].num_primitives_written - pq->num_primitives_written[0];
4787ec681f3Smrg      pq->num_primitives_generated[0] =
4797ec681f3Smrg         llvmpipe->so_stats[pq->index].primitives_storage_needed - pq->num_primitives_generated[0];
480af69d88dSmrg      break;
481af69d88dSmrg   case PIPE_QUERY_PIPELINE_STATISTICS:
482af69d88dSmrg      pq->stats.ia_vertices =
483af69d88dSmrg         llvmpipe->pipeline_statistics.ia_vertices - pq->stats.ia_vertices;
484af69d88dSmrg      pq->stats.ia_primitives =
485af69d88dSmrg         llvmpipe->pipeline_statistics.ia_primitives - pq->stats.ia_primitives;
486af69d88dSmrg      pq->stats.vs_invocations =
487af69d88dSmrg         llvmpipe->pipeline_statistics.vs_invocations - pq->stats.vs_invocations;
488af69d88dSmrg      pq->stats.gs_invocations =
489af69d88dSmrg         llvmpipe->pipeline_statistics.gs_invocations - pq->stats.gs_invocations;
490af69d88dSmrg      pq->stats.gs_primitives =
491af69d88dSmrg         llvmpipe->pipeline_statistics.gs_primitives - pq->stats.gs_primitives;
492af69d88dSmrg      pq->stats.c_invocations =
493af69d88dSmrg         llvmpipe->pipeline_statistics.c_invocations - pq->stats.c_invocations;
494af69d88dSmrg      pq->stats.c_primitives =
495af69d88dSmrg         llvmpipe->pipeline_statistics.c_primitives - pq->stats.c_primitives;
496af69d88dSmrg      pq->stats.ps_invocations =
497af69d88dSmrg         llvmpipe->pipeline_statistics.ps_invocations - pq->stats.ps_invocations;
4987ec681f3Smrg      pq->stats.cs_invocations =
4997ec681f3Smrg         llvmpipe->pipeline_statistics.cs_invocations - pq->stats.cs_invocations;
5007ec681f3Smrg      pq->stats.hs_invocations =
5017ec681f3Smrg         llvmpipe->pipeline_statistics.hs_invocations - pq->stats.hs_invocations;
5027ec681f3Smrg      pq->stats.ds_invocations =
5037ec681f3Smrg         llvmpipe->pipeline_statistics.ds_invocations - pq->stats.ds_invocations;
504af69d88dSmrg      llvmpipe->active_statistics_queries--;
505af69d88dSmrg      break;
506af69d88dSmrg   case PIPE_QUERY_OCCLUSION_COUNTER:
507af69d88dSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE:
50801e04c3fSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
509af69d88dSmrg      assert(llvmpipe->active_occlusion_queries);
510af69d88dSmrg      llvmpipe->active_occlusion_queries--;
511af69d88dSmrg      llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
512af69d88dSmrg      break;
513af69d88dSmrg   default:
514af69d88dSmrg      break;
515af69d88dSmrg   }
51601e04c3fSmrg
51701e04c3fSmrg   return true;
5184a49301eSmrg}
5194a49301eSmrg
520af69d88dSmrgboolean
521af69d88dSmrgllvmpipe_check_render_cond(struct llvmpipe_context *lp)
522af69d88dSmrg{
523af69d88dSmrg   struct pipe_context *pipe = &lp->pipe;
524af69d88dSmrg   boolean b, wait;
525af69d88dSmrg   uint64_t result;
526af69d88dSmrg
5277ec681f3Smrg   if (lp->render_cond_buffer) {
5287ec681f3Smrg      uint32_t data = *(uint32_t *)((char *)lp->render_cond_buffer->data + lp->render_cond_offset);
5297ec681f3Smrg      return (!data) == lp->render_cond_cond;
5307ec681f3Smrg   }
531af69d88dSmrg   if (!lp->render_cond_query)
532af69d88dSmrg      return TRUE; /* no query predicate, draw normally */
533af69d88dSmrg
534af69d88dSmrg   wait = (lp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
535af69d88dSmrg           lp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
536af69d88dSmrg
537af69d88dSmrg   b = pipe->get_query_result(pipe, lp->render_cond_query, wait, (void*)&result);
538af69d88dSmrg   if (b)
53901e04c3fSmrg      return ((!result) == lp->render_cond_cond);
540af69d88dSmrg   else
541af69d88dSmrg      return TRUE;
542af69d88dSmrg}
5434a49301eSmrg
54401e04c3fSmrgstatic void
5457ec681f3Smrgllvmpipe_set_active_query_state(struct pipe_context *pipe, bool enable)
54601e04c3fSmrg{
5477ec681f3Smrg   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
5487ec681f3Smrg
5497ec681f3Smrg   llvmpipe->queries_disabled = !enable;
5507ec681f3Smrg   /* for OQs we need to regenerate the fragment shader */
5517ec681f3Smrg   llvmpipe->dirty |= LP_NEW_OCCLUSION_QUERY;
55201e04c3fSmrg}
55301e04c3fSmrg
5544a49301eSmrgvoid llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
5554a49301eSmrg{
5564a49301eSmrg   llvmpipe->pipe.create_query = llvmpipe_create_query;
5574a49301eSmrg   llvmpipe->pipe.destroy_query = llvmpipe_destroy_query;
5584a49301eSmrg   llvmpipe->pipe.begin_query = llvmpipe_begin_query;
5594a49301eSmrg   llvmpipe->pipe.end_query = llvmpipe_end_query;
5604a49301eSmrg   llvmpipe->pipe.get_query_result = llvmpipe_get_query_result;
5617ec681f3Smrg   llvmpipe->pipe.get_query_result_resource = llvmpipe_get_query_result_resource;
56201e04c3fSmrg   llvmpipe->pipe.set_active_query_state = llvmpipe_set_active_query_state;
5634a49301eSmrg}
5644a49301eSmrg
5654a49301eSmrg
566