OSDN Git Service

gallium/swr: add OpenSWR driver
[android-x86/external-mesa.git] / src / gallium / drivers / swr / swr_query.cpp
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 "os/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
33
34 static struct swr_query *
35 swr_query(struct pipe_query *p)
36 {
37    return (struct swr_query *)p;
38 }
39
40 static struct pipe_query *
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 = CALLOC_STRUCT(swr_query);
49
50    if (pq) {
51       pq->type = type;
52       pq->index = index;
53    }
54
55    return (struct pipe_query *)pq;
56 }
57
58
59 static void
60 swr_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
61 {
62    struct swr_query *pq = swr_query(q);
63
64    if (pq->fence) {
65       if (!swr_is_fence_done(swr_fence(pq->fence))) {
66          swr_fence_submit(swr_context(pipe), pq->fence);
67          swr_fence_finish(pipe->screen, pq->fence, 0);
68       }
69       swr_fence_reference(pipe->screen, &pq->fence, NULL);
70    }
71
72    FREE(pq);
73 }
74
75
76 // XXX Create a fence callback, rather than stalling SwrWaitForIdle
77 static void
78 swr_gather_stats(struct pipe_context *pipe, struct swr_query *pq)
79 {
80    struct swr_context *ctx = swr_context(pipe);
81
82    assert(pq->result);
83    union pipe_query_result *result = pq->result;
84    boolean enable_stats = pq->enable_stats;
85    SWR_STATS swr_stats = {0};
86
87    if (pq->fence) {
88       if (!swr_is_fence_done(swr_fence(pq->fence))) {
89          swr_fence_submit(ctx, pq->fence);
90          swr_fence_finish(pipe->screen, pq->fence, 0);
91       }
92       swr_fence_reference(pipe->screen, &pq->fence, NULL);
93    }
94
95    /*
96     * These queries don't need SWR Stats enabled in the core
97     * Set and return.
98     */
99    switch (pq->type) {
100    case PIPE_QUERY_TIMESTAMP:
101    case PIPE_QUERY_TIME_ELAPSED:
102       result->u64 = swr_get_timestamp(pipe->screen);
103       return;
104       break;
105    case PIPE_QUERY_TIMESTAMP_DISJOINT:
106       /* nothing to do here */
107       return;
108       break;
109    case PIPE_QUERY_GPU_FINISHED:
110       result->b = TRUE; /* XXX TODO Add an api func to SWR to compare drawId
111                            vs LastRetiredId? */
112       return;
113       break;
114    default:
115       /* Any query that needs SwrCore stats */
116       break;
117    }
118
119    /*
120     * All other results are collected from SwrCore counters
121     */
122
123    /* XXX, Should turn this into a fence callback and skip the stall */
124    SwrGetStats(ctx->swrContext, &swr_stats);
125    /* SwrGetStats returns immediately, wait for collection */
126    SwrWaitForIdle(ctx->swrContext);
127
128    switch (pq->type) {
129    case PIPE_QUERY_OCCLUSION_PREDICATE:
130    case PIPE_QUERY_OCCLUSION_COUNTER:
131       result->u64 = swr_stats.DepthPassCount;
132       break;
133    case PIPE_QUERY_PRIMITIVES_GENERATED:
134       result->u64 = swr_stats.IaPrimitives;
135       break;
136    case PIPE_QUERY_PRIMITIVES_EMITTED:
137       result->u64 = swr_stats.SoNumPrimsWritten[pq->index];
138       break;
139    case PIPE_QUERY_SO_STATISTICS:
140    case PIPE_QUERY_SO_OVERFLOW_PREDICATE: {
141       struct pipe_query_data_so_statistics *so_stats = &result->so_statistics;
142       so_stats->num_primitives_written =
143          swr_stats.SoNumPrimsWritten[pq->index];
144       so_stats->primitives_storage_needed =
145          swr_stats.SoPrimStorageNeeded[pq->index];
146    } break;
147    case PIPE_QUERY_PIPELINE_STATISTICS: {
148       struct pipe_query_data_pipeline_statistics *p_stats =
149          &result->pipeline_statistics;
150       p_stats->ia_vertices = swr_stats.IaVertices;
151       p_stats->ia_primitives = swr_stats.IaPrimitives;
152       p_stats->vs_invocations = swr_stats.VsInvocations;
153       p_stats->gs_invocations = swr_stats.GsInvocations;
154       p_stats->gs_primitives = swr_stats.GsPrimitives;
155       p_stats->c_invocations = swr_stats.CPrimitives;
156       p_stats->c_primitives = swr_stats.CPrimitives;
157       p_stats->ps_invocations = swr_stats.PsInvocations;
158       p_stats->hs_invocations = swr_stats.HsInvocations;
159       p_stats->ds_invocations = swr_stats.DsInvocations;
160       p_stats->cs_invocations = swr_stats.CsInvocations;
161    } break;
162    default:
163       assert(0 && "Unsupported query");
164       break;
165    }
166
167    /* Only change stat collection if there are no active queries */
168    if (ctx->active_queries == 0)
169       SwrEnableStats(ctx->swrContext, enable_stats);
170 }
171
172
173 static boolean
174 swr_get_query_result(struct pipe_context *pipe,
175                      struct pipe_query *q,
176                      boolean wait,
177                      union pipe_query_result *result)
178 {
179    struct swr_context *ctx = swr_context(pipe);
180    struct swr_query *pq = swr_query(q);
181
182    if (pq->fence) {
183       if (!swr_is_fence_done(swr_fence(pq->fence))) {
184          swr_fence_submit(ctx, pq->fence);
185          if (!wait)
186             return FALSE;
187          swr_fence_finish(pipe->screen, pq->fence, 0);
188       }
189       swr_fence_reference(pipe->screen, &pq->fence, NULL);
190    }
191
192    /* XXX: Need to handle counter rollover */
193
194    switch (pq->type) {
195    /* Booleans */
196    case PIPE_QUERY_OCCLUSION_PREDICATE:
197       result->b = pq->end.u64 != pq->start.u64 ? TRUE : FALSE;
198       break;
199    case PIPE_QUERY_GPU_FINISHED:
200       result->b = pq->end.b;
201       break;
202    /* Counters */
203    case PIPE_QUERY_OCCLUSION_COUNTER:
204    case PIPE_QUERY_TIMESTAMP:
205    case PIPE_QUERY_TIME_ELAPSED:
206    case PIPE_QUERY_PRIMITIVES_GENERATED:
207    case PIPE_QUERY_PRIMITIVES_EMITTED:
208       result->u64 = pq->end.u64 - pq->start.u64;
209       break;
210    /* Structures */
211    case PIPE_QUERY_SO_STATISTICS: {
212       struct pipe_query_data_so_statistics *so_stats = &result->so_statistics;
213       struct pipe_query_data_so_statistics *start = &pq->start.so_statistics;
214       struct pipe_query_data_so_statistics *end = &pq->end.so_statistics;
215       so_stats->num_primitives_written =
216          end->num_primitives_written - start->num_primitives_written;
217       so_stats->primitives_storage_needed =
218          end->primitives_storage_needed - start->primitives_storage_needed;
219    } break;
220    case PIPE_QUERY_TIMESTAMP_DISJOINT: {
221       /* os_get_time_nano returns nanoseconds */
222       result->timestamp_disjoint.frequency = UINT64_C(1000000000);
223       result->timestamp_disjoint.disjoint = FALSE;
224    } break;
225    case PIPE_QUERY_PIPELINE_STATISTICS: {
226       struct pipe_query_data_pipeline_statistics *p_stats =
227          &result->pipeline_statistics;
228       struct pipe_query_data_pipeline_statistics *start =
229          &pq->start.pipeline_statistics;
230       struct pipe_query_data_pipeline_statistics *end =
231          &pq->end.pipeline_statistics;
232       p_stats->ia_vertices = end->ia_vertices - start->ia_vertices;
233       p_stats->ia_primitives = end->ia_primitives - start->ia_primitives;
234       p_stats->vs_invocations = end->vs_invocations - start->vs_invocations;
235       p_stats->gs_invocations = end->gs_invocations - start->gs_invocations;
236       p_stats->gs_primitives = end->gs_primitives - start->gs_primitives;
237       p_stats->c_invocations = end->c_invocations - start->c_invocations;
238       p_stats->c_primitives = end->c_primitives - start->c_primitives;
239       p_stats->ps_invocations = end->ps_invocations - start->ps_invocations;
240       p_stats->hs_invocations = end->hs_invocations - start->hs_invocations;
241       p_stats->ds_invocations = end->ds_invocations - start->ds_invocations;
242       p_stats->cs_invocations = end->cs_invocations - start->cs_invocations;
243    } break;
244    case PIPE_QUERY_SO_OVERFLOW_PREDICATE: {
245       struct pipe_query_data_so_statistics *start = &pq->start.so_statistics;
246       struct pipe_query_data_so_statistics *end = &pq->end.so_statistics;
247       uint64_t num_primitives_written =
248          end->num_primitives_written - start->num_primitives_written;
249       uint64_t primitives_storage_needed =
250          end->primitives_storage_needed - start->primitives_storage_needed;
251       result->b = num_primitives_written > primitives_storage_needed;
252    } break;
253    default:
254       assert(0 && "Unsupported query");
255       break;
256    }
257
258    return TRUE;
259 }
260
261 static boolean
262 swr_begin_query(struct pipe_context *pipe, struct pipe_query *q)
263 {
264    struct swr_context *ctx = swr_context(pipe);
265    struct swr_query *pq = swr_query(q);
266
267    /* Initialize Results */
268    memset(&pq->start, 0, sizeof(pq->start));
269    memset(&pq->end, 0, sizeof(pq->end));
270
271    /* Gather start stats and enable SwrCore counters */
272    pq->result = &pq->start;
273    pq->enable_stats = TRUE;
274    swr_gather_stats(pipe, pq);
275    ctx->active_queries++;
276
277    /* override start timestamp to 0 for TIMESTAMP query */
278    if (pq->type == PIPE_QUERY_TIMESTAMP)
279       pq->start.u64 = 0;
280
281    return true;
282 }
283
284 static void
285 swr_end_query(struct pipe_context *pipe, struct pipe_query *q)
286 {
287    struct swr_context *ctx = swr_context(pipe);
288    struct swr_query *pq = swr_query(q);
289
290    assert(ctx->active_queries
291           && "swr_end_query, there are no active queries!");
292    ctx->active_queries--;
293
294    /* Gather end stats and disable SwrCore counters */
295    pq->result = &pq->end;
296    pq->enable_stats = FALSE;
297    swr_gather_stats(pipe, pq);
298 }
299
300
301 boolean
302 swr_check_render_cond(struct pipe_context *pipe)
303 {
304    struct swr_context *ctx = swr_context(pipe);
305    boolean b, wait;
306    uint64_t result;
307
308    if (!ctx->render_cond_query)
309       return TRUE; /* no query predicate, draw normally */
310
311    wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT
312            || ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
313
314    b = pipe->get_query_result(
315       pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result);
316    if (b)
317       return (!result == ctx->render_cond_cond);
318    else
319       return TRUE;
320 }
321
322 void
323 swr_query_init(struct pipe_context *pipe)
324 {
325    struct swr_context *ctx = swr_context(pipe);
326
327    pipe->create_query = swr_create_query;
328    pipe->destroy_query = swr_destroy_query;
329    pipe->begin_query = swr_begin_query;
330    pipe->end_query = swr_end_query;
331    pipe->get_query_result = swr_get_query_result;
332
333    ctx->active_queries = 0;
334 }