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