1b8e80941Smrg/****************************************************************************
2b8e80941Smrg * Copyright (C) 2015 Intel Corporation.   All Rights Reserved.
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21b8e80941Smrg * IN THE SOFTWARE.
22b8e80941Smrg ***************************************************************************/
23b8e80941Smrg
24b8e80941Smrg#include "pipe/p_defines.h"
25b8e80941Smrg#include "util/u_memory.h"
26b8e80941Smrg#include "util/os_time.h"
27b8e80941Smrg#include "swr_context.h"
28b8e80941Smrg#include "swr_fence.h"
29b8e80941Smrg#include "swr_query.h"
30b8e80941Smrg#include "swr_screen.h"
31b8e80941Smrg#include "swr_state.h"
32b8e80941Smrg#include "common/os.h"
33b8e80941Smrg
34b8e80941Smrgstatic struct swr_query *
35b8e80941Smrgswr_query(struct pipe_query *p)
36b8e80941Smrg{
37b8e80941Smrg   return (struct swr_query *)p;
38b8e80941Smrg}
39b8e80941Smrg
40b8e80941Smrgstatic struct pipe_query *
41b8e80941Smrgswr_create_query(struct pipe_context *pipe, unsigned type, unsigned index)
42b8e80941Smrg{
43b8e80941Smrg   struct swr_query *pq;
44b8e80941Smrg
45b8e80941Smrg   assert(type < PIPE_QUERY_TYPES);
46b8e80941Smrg   assert(index < MAX_SO_STREAMS);
47b8e80941Smrg
48b8e80941Smrg   pq = (struct swr_query *) AlignedMalloc(sizeof(struct swr_query), 64);
49b8e80941Smrg   memset(pq, 0, sizeof(*pq));
50b8e80941Smrg
51b8e80941Smrg   if (pq) {
52b8e80941Smrg      pq->type = type;
53b8e80941Smrg      pq->index = index;
54b8e80941Smrg   }
55b8e80941Smrg
56b8e80941Smrg   return (struct pipe_query *)pq;
57b8e80941Smrg}
58b8e80941Smrg
59b8e80941Smrg
60b8e80941Smrgstatic void
61b8e80941Smrgswr_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
62b8e80941Smrg{
63b8e80941Smrg   struct swr_query *pq = swr_query(q);
64b8e80941Smrg
65b8e80941Smrg   if (pq->fence) {
66b8e80941Smrg      if (swr_is_fence_pending(pq->fence))
67b8e80941Smrg         swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
68b8e80941Smrg      swr_fence_reference(pipe->screen, &pq->fence, NULL);
69b8e80941Smrg   }
70b8e80941Smrg
71b8e80941Smrg   AlignedFree(pq);
72b8e80941Smrg}
73b8e80941Smrg
74b8e80941Smrg
75b8e80941Smrgstatic boolean
76b8e80941Smrgswr_get_query_result(struct pipe_context *pipe,
77b8e80941Smrg                     struct pipe_query *q,
78b8e80941Smrg                     boolean wait,
79b8e80941Smrg                     union pipe_query_result *result)
80b8e80941Smrg{
81b8e80941Smrg   struct swr_query *pq = swr_query(q);
82b8e80941Smrg   unsigned index = pq->index;
83b8e80941Smrg
84b8e80941Smrg   if (pq->fence) {
85b8e80941Smrg      if (!wait && !swr_is_fence_done(pq->fence))
86b8e80941Smrg         return FALSE;
87b8e80941Smrg
88b8e80941Smrg      swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
89b8e80941Smrg      swr_fence_reference(pipe->screen, &pq->fence, NULL);
90b8e80941Smrg   }
91b8e80941Smrg
92b8e80941Smrg   /* All values are reset to 0 at swr_begin_query, except starting timestamp.
93b8e80941Smrg    * Counters become simply end values.  */
94b8e80941Smrg   switch (pq->type) {
95b8e80941Smrg   /* Booleans */
96b8e80941Smrg   case PIPE_QUERY_OCCLUSION_PREDICATE:
97b8e80941Smrg   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
98b8e80941Smrg      result->b = pq->result.core.DepthPassCount != 0;
99b8e80941Smrg      break;
100b8e80941Smrg   case PIPE_QUERY_GPU_FINISHED:
101b8e80941Smrg      result->b = TRUE;
102b8e80941Smrg      break;
103b8e80941Smrg   /* Counters */
104b8e80941Smrg   case PIPE_QUERY_OCCLUSION_COUNTER:
105b8e80941Smrg      result->u64 = pq->result.core.DepthPassCount;
106b8e80941Smrg      break;
107b8e80941Smrg   case PIPE_QUERY_TIMESTAMP:
108b8e80941Smrg   case PIPE_QUERY_TIME_ELAPSED:
109b8e80941Smrg      result->u64 = pq->result.timestamp_end - pq->result.timestamp_start;
110b8e80941Smrg      break;
111b8e80941Smrg   case PIPE_QUERY_PRIMITIVES_GENERATED:
112b8e80941Smrg      result->u64 = pq->result.coreFE.IaPrimitives;
113b8e80941Smrg      break;
114b8e80941Smrg   case PIPE_QUERY_PRIMITIVES_EMITTED:
115b8e80941Smrg      result->u64 = pq->result.coreFE.SoNumPrimsWritten[index];
116b8e80941Smrg      break;
117b8e80941Smrg   /* Structures */
118b8e80941Smrg   case PIPE_QUERY_SO_STATISTICS: {
119b8e80941Smrg      struct pipe_query_data_so_statistics *so_stats = &result->so_statistics;
120b8e80941Smrg      so_stats->num_primitives_written =
121b8e80941Smrg         pq->result.coreFE.SoNumPrimsWritten[index];
122b8e80941Smrg      so_stats->primitives_storage_needed =
123b8e80941Smrg         pq->result.coreFE.SoPrimStorageNeeded[index];
124b8e80941Smrg   } break;
125b8e80941Smrg   case PIPE_QUERY_TIMESTAMP_DISJOINT:
126b8e80941Smrg      /* os_get_time_nano returns nanoseconds */
127b8e80941Smrg      result->timestamp_disjoint.frequency = UINT64_C(1000000000);
128b8e80941Smrg      result->timestamp_disjoint.disjoint = FALSE;
129b8e80941Smrg      break;
130b8e80941Smrg   case PIPE_QUERY_PIPELINE_STATISTICS: {
131b8e80941Smrg      struct pipe_query_data_pipeline_statistics *p_stats =
132b8e80941Smrg         &result->pipeline_statistics;
133b8e80941Smrg      p_stats->ia_vertices = pq->result.coreFE.IaVertices;
134b8e80941Smrg      p_stats->ia_primitives = pq->result.coreFE.IaPrimitives;
135b8e80941Smrg      p_stats->vs_invocations = pq->result.coreFE.VsInvocations;
136b8e80941Smrg      p_stats->gs_invocations = pq->result.coreFE.GsInvocations;
137b8e80941Smrg      p_stats->gs_primitives = pq->result.coreFE.GsPrimitives;
138b8e80941Smrg      p_stats->c_invocations = pq->result.coreFE.CPrimitives;
139b8e80941Smrg      p_stats->c_primitives = pq->result.coreFE.CPrimitives;
140b8e80941Smrg      p_stats->ps_invocations = pq->result.core.PsInvocations;
141b8e80941Smrg      p_stats->hs_invocations = pq->result.coreFE.HsInvocations;
142b8e80941Smrg      p_stats->ds_invocations = pq->result.coreFE.DsInvocations;
143b8e80941Smrg      p_stats->cs_invocations = pq->result.core.CsInvocations;
144b8e80941Smrg    } break;
145b8e80941Smrg   case PIPE_QUERY_SO_OVERFLOW_PREDICATE: {
146b8e80941Smrg      uint64_t num_primitives_written =
147b8e80941Smrg         pq->result.coreFE.SoNumPrimsWritten[index];
148b8e80941Smrg      uint64_t primitives_storage_needed =
149b8e80941Smrg         pq->result.coreFE.SoPrimStorageNeeded[index];
150b8e80941Smrg      result->b = num_primitives_written > primitives_storage_needed;
151b8e80941Smrg   }
152b8e80941Smrg      break;
153b8e80941Smrg   default:
154b8e80941Smrg      assert(0 && "Unsupported query");
155b8e80941Smrg      break;
156b8e80941Smrg   }
157b8e80941Smrg
158b8e80941Smrg   return TRUE;
159b8e80941Smrg}
160b8e80941Smrg
161b8e80941Smrgstatic boolean
162b8e80941Smrgswr_begin_query(struct pipe_context *pipe, struct pipe_query *q)
163b8e80941Smrg{
164b8e80941Smrg   struct swr_context *ctx = swr_context(pipe);
165b8e80941Smrg   struct swr_query *pq = swr_query(q);
166b8e80941Smrg
167b8e80941Smrg   /* Initialize Results */
168b8e80941Smrg   memset(&pq->result, 0, sizeof(pq->result));
169b8e80941Smrg   switch (pq->type) {
170b8e80941Smrg   case PIPE_QUERY_GPU_FINISHED:
171b8e80941Smrg   case PIPE_QUERY_TIMESTAMP:
172b8e80941Smrg      /* nothing to do, but don't want the default */
173b8e80941Smrg      break;
174b8e80941Smrg   case PIPE_QUERY_TIME_ELAPSED:
175b8e80941Smrg      pq->result.timestamp_start = swr_get_timestamp(pipe->screen);
176b8e80941Smrg      break;
177b8e80941Smrg   default:
178b8e80941Smrg      /* Core counters required.  Update draw context with location to
179b8e80941Smrg       * store results. */
180b8e80941Smrg      swr_update_draw_context(ctx, &pq->result);
181b8e80941Smrg
182b8e80941Smrg      /* Only change stat collection if there are no active queries */
183b8e80941Smrg      if (ctx->active_queries == 0) {
184b8e80941Smrg         ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, TRUE);
185b8e80941Smrg         ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, TRUE);
186b8e80941Smrg      }
187b8e80941Smrg      ctx->active_queries++;
188b8e80941Smrg      break;
189b8e80941Smrg   }
190b8e80941Smrg
191b8e80941Smrg
192b8e80941Smrg   return true;
193b8e80941Smrg}
194b8e80941Smrg
195b8e80941Smrgstatic bool
196b8e80941Smrgswr_end_query(struct pipe_context *pipe, struct pipe_query *q)
197b8e80941Smrg{
198b8e80941Smrg   struct swr_context *ctx = swr_context(pipe);
199b8e80941Smrg   struct swr_query *pq = swr_query(q);
200b8e80941Smrg
201b8e80941Smrg   switch (pq->type) {
202b8e80941Smrg   case PIPE_QUERY_GPU_FINISHED:
203b8e80941Smrg      /* nothing to do, but don't want the default */
204b8e80941Smrg      break;
205b8e80941Smrg   case PIPE_QUERY_TIMESTAMP:
206b8e80941Smrg   case PIPE_QUERY_TIME_ELAPSED:
207b8e80941Smrg      pq->result.timestamp_end = swr_get_timestamp(pipe->screen);
208b8e80941Smrg      break;
209b8e80941Smrg   default:
210b8e80941Smrg      /* Stats are updated asynchronously, a fence is used to signal
211b8e80941Smrg       * completion. */
212b8e80941Smrg      if (!pq->fence) {
213b8e80941Smrg         struct swr_screen *screen = swr_screen(pipe->screen);
214b8e80941Smrg         swr_fence_reference(pipe->screen, &pq->fence, screen->flush_fence);
215b8e80941Smrg      }
216b8e80941Smrg      swr_fence_submit(ctx, pq->fence);
217b8e80941Smrg
218b8e80941Smrg      /* Only change stat collection if there are no active queries */
219b8e80941Smrg      ctx->active_queries--;
220b8e80941Smrg      if (ctx->active_queries == 0) {
221b8e80941Smrg         ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, FALSE);
222b8e80941Smrg         ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, FALSE);
223b8e80941Smrg      }
224b8e80941Smrg
225b8e80941Smrg      break;
226b8e80941Smrg   }
227b8e80941Smrg
228b8e80941Smrg   return true;
229b8e80941Smrg}
230b8e80941Smrg
231b8e80941Smrg
232b8e80941Smrgboolean
233b8e80941Smrgswr_check_render_cond(struct pipe_context *pipe)
234b8e80941Smrg{
235b8e80941Smrg   struct swr_context *ctx = swr_context(pipe);
236b8e80941Smrg   boolean b, wait;
237b8e80941Smrg   uint64_t result;
238b8e80941Smrg
239b8e80941Smrg   if (!ctx->render_cond_query)
240b8e80941Smrg      return TRUE; /* no query predicate, draw normally */
241b8e80941Smrg
242b8e80941Smrg   wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT
243b8e80941Smrg           || ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
244b8e80941Smrg
245b8e80941Smrg   b = pipe->get_query_result(
246b8e80941Smrg      pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result);
247b8e80941Smrg   if (b)
248b8e80941Smrg      return ((!result) == ctx->render_cond_cond);
249b8e80941Smrg   else
250b8e80941Smrg      return TRUE;
251b8e80941Smrg}
252b8e80941Smrg
253b8e80941Smrg
254b8e80941Smrgstatic void
255b8e80941Smrgswr_set_active_query_state(struct pipe_context *pipe, boolean enable)
256b8e80941Smrg{
257b8e80941Smrg}
258b8e80941Smrg
259b8e80941Smrgvoid
260b8e80941Smrgswr_query_init(struct pipe_context *pipe)
261b8e80941Smrg{
262b8e80941Smrg   struct swr_context *ctx = swr_context(pipe);
263b8e80941Smrg
264b8e80941Smrg   pipe->create_query = swr_create_query;
265b8e80941Smrg   pipe->destroy_query = swr_destroy_query;
266b8e80941Smrg   pipe->begin_query = swr_begin_query;
267b8e80941Smrg   pipe->end_query = swr_end_query;
268b8e80941Smrg   pipe->get_query_result = swr_get_query_result;
269b8e80941Smrg   pipe->set_active_query_state = swr_set_active_query_state;
270b8e80941Smrg
271b8e80941Smrg   ctx->active_queries = 0;
272b8e80941Smrg}
273