101e04c3fSmrg/****************************************************************************
201e04c3fSmrg * Copyright (C) 2015 Intel Corporation.   All Rights Reserved.
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg ***************************************************************************/
2301e04c3fSmrg
2401e04c3fSmrg#include "pipe/p_defines.h"
2501e04c3fSmrg#include "util/u_memory.h"
2601e04c3fSmrg#include "util/os_time.h"
2701e04c3fSmrg#include "swr_context.h"
2801e04c3fSmrg#include "swr_fence.h"
2901e04c3fSmrg#include "swr_query.h"
3001e04c3fSmrg#include "swr_screen.h"
3101e04c3fSmrg#include "swr_state.h"
3201e04c3fSmrg#include "common/os.h"
3301e04c3fSmrg
3401e04c3fSmrgstatic struct swr_query *
3501e04c3fSmrgswr_query(struct pipe_query *p)
3601e04c3fSmrg{
3701e04c3fSmrg   return (struct swr_query *)p;
3801e04c3fSmrg}
3901e04c3fSmrg
4001e04c3fSmrgstatic struct pipe_query *
4101e04c3fSmrgswr_create_query(struct pipe_context *pipe, unsigned type, unsigned index)
4201e04c3fSmrg{
4301e04c3fSmrg   struct swr_query *pq;
4401e04c3fSmrg
4501e04c3fSmrg   assert(type < PIPE_QUERY_TYPES);
4601e04c3fSmrg   assert(index < MAX_SO_STREAMS);
4701e04c3fSmrg
4801e04c3fSmrg   pq = (struct swr_query *) AlignedMalloc(sizeof(struct swr_query), 64);
4901e04c3fSmrg
5001e04c3fSmrg   if (pq) {
517ec681f3Smrg      memset(pq, 0, sizeof(*pq));
5201e04c3fSmrg      pq->type = type;
5301e04c3fSmrg      pq->index = index;
5401e04c3fSmrg   }
5501e04c3fSmrg
5601e04c3fSmrg   return (struct pipe_query *)pq;
5701e04c3fSmrg}
5801e04c3fSmrg
5901e04c3fSmrg
6001e04c3fSmrgstatic void
6101e04c3fSmrgswr_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
6201e04c3fSmrg{
6301e04c3fSmrg   struct swr_query *pq = swr_query(q);
6401e04c3fSmrg
6501e04c3fSmrg   if (pq->fence) {
6601e04c3fSmrg      if (swr_is_fence_pending(pq->fence))
6701e04c3fSmrg         swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
6801e04c3fSmrg      swr_fence_reference(pipe->screen, &pq->fence, NULL);
6901e04c3fSmrg   }
7001e04c3fSmrg
7101e04c3fSmrg   AlignedFree(pq);
7201e04c3fSmrg}
7301e04c3fSmrg
7401e04c3fSmrg
757ec681f3Smrgstatic bool
7601e04c3fSmrgswr_get_query_result(struct pipe_context *pipe,
7701e04c3fSmrg                     struct pipe_query *q,
787ec681f3Smrg                     bool wait,
7901e04c3fSmrg                     union pipe_query_result *result)
8001e04c3fSmrg{
8101e04c3fSmrg   struct swr_query *pq = swr_query(q);
8201e04c3fSmrg   unsigned index = pq->index;
8301e04c3fSmrg
8401e04c3fSmrg   if (pq->fence) {
8501e04c3fSmrg      if (!wait && !swr_is_fence_done(pq->fence))
867ec681f3Smrg         return false;
8701e04c3fSmrg
8801e04c3fSmrg      swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
8901e04c3fSmrg      swr_fence_reference(pipe->screen, &pq->fence, NULL);
9001e04c3fSmrg   }
9101e04c3fSmrg
9201e04c3fSmrg   /* All values are reset to 0 at swr_begin_query, except starting timestamp.
9301e04c3fSmrg    * Counters become simply end values.  */
9401e04c3fSmrg   switch (pq->type) {
9501e04c3fSmrg   /* Booleans */
9601e04c3fSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE:
9701e04c3fSmrg   case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
9801e04c3fSmrg      result->b = pq->result.core.DepthPassCount != 0;
9901e04c3fSmrg      break;
10001e04c3fSmrg   case PIPE_QUERY_GPU_FINISHED:
1017ec681f3Smrg      result->b = true;
10201e04c3fSmrg      break;
10301e04c3fSmrg   /* Counters */
10401e04c3fSmrg   case PIPE_QUERY_OCCLUSION_COUNTER:
10501e04c3fSmrg      result->u64 = pq->result.core.DepthPassCount;
10601e04c3fSmrg      break;
10701e04c3fSmrg   case PIPE_QUERY_TIMESTAMP:
10801e04c3fSmrg   case PIPE_QUERY_TIME_ELAPSED:
10901e04c3fSmrg      result->u64 = pq->result.timestamp_end - pq->result.timestamp_start;
11001e04c3fSmrg      break;
11101e04c3fSmrg   case PIPE_QUERY_PRIMITIVES_GENERATED:
11201e04c3fSmrg      result->u64 = pq->result.coreFE.IaPrimitives;
11301e04c3fSmrg      break;
11401e04c3fSmrg   case PIPE_QUERY_PRIMITIVES_EMITTED:
11501e04c3fSmrg      result->u64 = pq->result.coreFE.SoNumPrimsWritten[index];
11601e04c3fSmrg      break;
11701e04c3fSmrg   /* Structures */
11801e04c3fSmrg   case PIPE_QUERY_SO_STATISTICS: {
11901e04c3fSmrg      struct pipe_query_data_so_statistics *so_stats = &result->so_statistics;
12001e04c3fSmrg      so_stats->num_primitives_written =
12101e04c3fSmrg         pq->result.coreFE.SoNumPrimsWritten[index];
12201e04c3fSmrg      so_stats->primitives_storage_needed =
12301e04c3fSmrg         pq->result.coreFE.SoPrimStorageNeeded[index];
12401e04c3fSmrg   } break;
12501e04c3fSmrg   case PIPE_QUERY_TIMESTAMP_DISJOINT:
12601e04c3fSmrg      /* os_get_time_nano returns nanoseconds */
12701e04c3fSmrg      result->timestamp_disjoint.frequency = UINT64_C(1000000000);
12801e04c3fSmrg      result->timestamp_disjoint.disjoint = FALSE;
12901e04c3fSmrg      break;
13001e04c3fSmrg   case PIPE_QUERY_PIPELINE_STATISTICS: {
13101e04c3fSmrg      struct pipe_query_data_pipeline_statistics *p_stats =
13201e04c3fSmrg         &result->pipeline_statistics;
13301e04c3fSmrg      p_stats->ia_vertices = pq->result.coreFE.IaVertices;
13401e04c3fSmrg      p_stats->ia_primitives = pq->result.coreFE.IaPrimitives;
13501e04c3fSmrg      p_stats->vs_invocations = pq->result.coreFE.VsInvocations;
13601e04c3fSmrg      p_stats->gs_invocations = pq->result.coreFE.GsInvocations;
13701e04c3fSmrg      p_stats->gs_primitives = pq->result.coreFE.GsPrimitives;
13801e04c3fSmrg      p_stats->c_invocations = pq->result.coreFE.CPrimitives;
13901e04c3fSmrg      p_stats->c_primitives = pq->result.coreFE.CPrimitives;
14001e04c3fSmrg      p_stats->ps_invocations = pq->result.core.PsInvocations;
14101e04c3fSmrg      p_stats->hs_invocations = pq->result.coreFE.HsInvocations;
14201e04c3fSmrg      p_stats->ds_invocations = pq->result.coreFE.DsInvocations;
14301e04c3fSmrg      p_stats->cs_invocations = pq->result.core.CsInvocations;
14401e04c3fSmrg    } break;
14501e04c3fSmrg   case PIPE_QUERY_SO_OVERFLOW_PREDICATE: {
14601e04c3fSmrg      uint64_t num_primitives_written =
14701e04c3fSmrg         pq->result.coreFE.SoNumPrimsWritten[index];
14801e04c3fSmrg      uint64_t primitives_storage_needed =
14901e04c3fSmrg         pq->result.coreFE.SoPrimStorageNeeded[index];
15001e04c3fSmrg      result->b = num_primitives_written > primitives_storage_needed;
15101e04c3fSmrg   }
15201e04c3fSmrg      break;
15301e04c3fSmrg   default:
15401e04c3fSmrg      assert(0 && "Unsupported query");
15501e04c3fSmrg      break;
15601e04c3fSmrg   }
15701e04c3fSmrg
1587ec681f3Smrg   return true;
15901e04c3fSmrg}
16001e04c3fSmrg
1617ec681f3Smrgstatic bool
16201e04c3fSmrgswr_begin_query(struct pipe_context *pipe, struct pipe_query *q)
16301e04c3fSmrg{
16401e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
16501e04c3fSmrg   struct swr_query *pq = swr_query(q);
16601e04c3fSmrg
16701e04c3fSmrg   /* Initialize Results */
16801e04c3fSmrg   memset(&pq->result, 0, sizeof(pq->result));
16901e04c3fSmrg   switch (pq->type) {
17001e04c3fSmrg   case PIPE_QUERY_GPU_FINISHED:
17101e04c3fSmrg   case PIPE_QUERY_TIMESTAMP:
17201e04c3fSmrg      /* nothing to do, but don't want the default */
17301e04c3fSmrg      break;
17401e04c3fSmrg   case PIPE_QUERY_TIME_ELAPSED:
17501e04c3fSmrg      pq->result.timestamp_start = swr_get_timestamp(pipe->screen);
17601e04c3fSmrg      break;
17701e04c3fSmrg   default:
17801e04c3fSmrg      /* Core counters required.  Update draw context with location to
17901e04c3fSmrg       * store results. */
18001e04c3fSmrg      swr_update_draw_context(ctx, &pq->result);
18101e04c3fSmrg
18201e04c3fSmrg      /* Only change stat collection if there are no active queries */
18301e04c3fSmrg      if (ctx->active_queries == 0) {
18401e04c3fSmrg         ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, TRUE);
18501e04c3fSmrg         ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, TRUE);
18601e04c3fSmrg      }
18701e04c3fSmrg      ctx->active_queries++;
18801e04c3fSmrg      break;
18901e04c3fSmrg   }
19001e04c3fSmrg
19101e04c3fSmrg
19201e04c3fSmrg   return true;
19301e04c3fSmrg}
19401e04c3fSmrg
19501e04c3fSmrgstatic bool
19601e04c3fSmrgswr_end_query(struct pipe_context *pipe, struct pipe_query *q)
19701e04c3fSmrg{
19801e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
19901e04c3fSmrg   struct swr_query *pq = swr_query(q);
20001e04c3fSmrg
20101e04c3fSmrg   switch (pq->type) {
20201e04c3fSmrg   case PIPE_QUERY_GPU_FINISHED:
20301e04c3fSmrg      /* nothing to do, but don't want the default */
20401e04c3fSmrg      break;
20501e04c3fSmrg   case PIPE_QUERY_TIMESTAMP:
20601e04c3fSmrg   case PIPE_QUERY_TIME_ELAPSED:
20701e04c3fSmrg      pq->result.timestamp_end = swr_get_timestamp(pipe->screen);
20801e04c3fSmrg      break;
20901e04c3fSmrg   default:
21001e04c3fSmrg      /* Stats are updated asynchronously, a fence is used to signal
21101e04c3fSmrg       * completion. */
21201e04c3fSmrg      if (!pq->fence) {
21301e04c3fSmrg         struct swr_screen *screen = swr_screen(pipe->screen);
21401e04c3fSmrg         swr_fence_reference(pipe->screen, &pq->fence, screen->flush_fence);
21501e04c3fSmrg      }
21601e04c3fSmrg      swr_fence_submit(ctx, pq->fence);
21701e04c3fSmrg
21801e04c3fSmrg      /* Only change stat collection if there are no active queries */
21901e04c3fSmrg      ctx->active_queries--;
22001e04c3fSmrg      if (ctx->active_queries == 0) {
22101e04c3fSmrg         ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, FALSE);
22201e04c3fSmrg         ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, FALSE);
22301e04c3fSmrg      }
22401e04c3fSmrg
22501e04c3fSmrg      break;
22601e04c3fSmrg   }
22701e04c3fSmrg
22801e04c3fSmrg   return true;
22901e04c3fSmrg}
23001e04c3fSmrg
23101e04c3fSmrg
2327ec681f3Smrgbool
23301e04c3fSmrgswr_check_render_cond(struct pipe_context *pipe)
23401e04c3fSmrg{
23501e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
2367ec681f3Smrg   bool b, wait;
23701e04c3fSmrg   uint64_t result;
23801e04c3fSmrg
23901e04c3fSmrg   if (!ctx->render_cond_query)
2407ec681f3Smrg      return true; /* no query predicate, draw normally */
24101e04c3fSmrg
24201e04c3fSmrg   wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT
24301e04c3fSmrg           || ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
24401e04c3fSmrg
24501e04c3fSmrg   b = pipe->get_query_result(
24601e04c3fSmrg      pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result);
24701e04c3fSmrg   if (b)
24801e04c3fSmrg      return ((!result) == ctx->render_cond_cond);
24901e04c3fSmrg   else
2507ec681f3Smrg      return true;
25101e04c3fSmrg}
25201e04c3fSmrg
25301e04c3fSmrg
25401e04c3fSmrgstatic void
2557ec681f3Smrgswr_set_active_query_state(struct pipe_context *pipe, bool enable)
25601e04c3fSmrg{
25701e04c3fSmrg}
25801e04c3fSmrg
25901e04c3fSmrgvoid
26001e04c3fSmrgswr_query_init(struct pipe_context *pipe)
26101e04c3fSmrg{
26201e04c3fSmrg   struct swr_context *ctx = swr_context(pipe);
26301e04c3fSmrg
26401e04c3fSmrg   pipe->create_query = swr_create_query;
26501e04c3fSmrg   pipe->destroy_query = swr_destroy_query;
26601e04c3fSmrg   pipe->begin_query = swr_begin_query;
26701e04c3fSmrg   pipe->end_query = swr_end_query;
26801e04c3fSmrg   pipe->get_query_result = swr_get_query_result;
26901e04c3fSmrg   pipe->set_active_query_state = swr_set_active_query_state;
27001e04c3fSmrg
27101e04c3fSmrg   ctx->active_queries = 0;
27201e04c3fSmrg}
273