swr: [rasterizer common] os.h portability header changes
[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_pending(pq->fence))
66 swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
67 swr_fence_reference(pipe->screen, &pq->fence, NULL);
68 }
69
70 FREE(pq);
71 }
72
73
74 static void
75 swr_gather_stats(struct pipe_context *pipe, struct swr_query *pq)
76 {
77 struct swr_context *ctx = swr_context(pipe);
78
79 assert(pq->result);
80 struct swr_query_result *result = pq->result;
81 boolean enable_stats = pq->enable_stats;
82
83 /* A few results don't require the core, so don't involve it */
84 switch (pq->type) {
85 case PIPE_QUERY_TIMESTAMP:
86 case PIPE_QUERY_TIME_ELAPSED:
87 result->timestamp = swr_get_timestamp(pipe->screen);
88 break;
89 case PIPE_QUERY_TIMESTAMP_DISJOINT:
90 case PIPE_QUERY_GPU_FINISHED:
91 /* nothing to do here */
92 break;
93 default:
94 /* TODO: should fence instead of stalling pipeline */
95 SwrWaitForIdle(ctx->swrContext);
96 memcpy(&result->core, &ctx->stats, sizeof(result->core));
97 memcpy(&result->coreFE, &ctx->statsFE, sizeof(result->coreFE));
98
99 #if 0
100 if (!pq->fence) {
101 struct swr_screen *screen = swr_screen(pipe->screen);
102 swr_fence_reference(pipe->screen, &pq->fence, screen->flush_fence);
103 }
104 swr_fence_submit(ctx, pq->fence);
105 #endif
106
107 /* Only change stat collection if there are no active queries */
108 if (ctx->active_queries == 0)
109 SwrEnableStats(ctx->swrContext, enable_stats);
110
111 break;
112 }
113 }
114
115
116 static boolean
117 swr_get_query_result(struct pipe_context *pipe,
118 struct pipe_query *q,
119 boolean wait,
120 union pipe_query_result *result)
121 {
122 struct swr_query *pq = swr_query(q);
123 struct swr_query_result *start = &pq->start;
124 struct swr_query_result *end = &pq->end;
125 unsigned index = pq->index;
126
127 if (pq->fence) {
128 if (!wait && !swr_is_fence_done(pq->fence))
129 return FALSE;
130
131 swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
132 swr_fence_reference(pipe->screen, &pq->fence, NULL);
133 }
134
135 /* XXX: Need to handle counter rollover */
136
137 switch (pq->type) {
138 /* Booleans */
139 case PIPE_QUERY_OCCLUSION_PREDICATE:
140 result->b = end->core.DepthPassCount != start->core.DepthPassCount;
141 break;
142 case PIPE_QUERY_GPU_FINISHED:
143 result->b = TRUE;
144 break;
145 /* Counters */
146 case PIPE_QUERY_OCCLUSION_COUNTER:
147 result->u64 = end->core.DepthPassCount - start->core.DepthPassCount;
148 break;
149 case PIPE_QUERY_TIMESTAMP:
150 case PIPE_QUERY_TIME_ELAPSED:
151 result->u64 = end->timestamp - start->timestamp;
152 break;
153 case PIPE_QUERY_PRIMITIVES_GENERATED:
154 result->u64 = end->coreFE.IaPrimitives - start->coreFE.IaPrimitives;
155 break;
156 case PIPE_QUERY_PRIMITIVES_EMITTED:
157 result->u64 = end->coreFE.SoNumPrimsWritten[index]
158 - start->coreFE.SoNumPrimsWritten[index];
159 break;
160 /* Structures */
161 case PIPE_QUERY_SO_STATISTICS: {
162 struct pipe_query_data_so_statistics *so_stats = &result->so_statistics;
163 struct SWR_STATS_FE *start = &pq->start.coreFE;
164 struct SWR_STATS_FE *end = &pq->end.coreFE;
165 so_stats->num_primitives_written =
166 end->SoNumPrimsWritten[index] - start->SoNumPrimsWritten[index];
167 so_stats->primitives_storage_needed =
168 end->SoPrimStorageNeeded[index] - start->SoPrimStorageNeeded[index];
169 } break;
170 case PIPE_QUERY_TIMESTAMP_DISJOINT:
171 /* os_get_time_nano returns nanoseconds */
172 result->timestamp_disjoint.frequency = UINT64_C(1000000000);
173 result->timestamp_disjoint.disjoint = FALSE;
174 break;
175 case PIPE_QUERY_PIPELINE_STATISTICS: {
176 struct pipe_query_data_pipeline_statistics *p_stats =
177 &result->pipeline_statistics;
178 struct SWR_STATS *start = &pq->start.core;
179 struct SWR_STATS *end = &pq->end.core;
180 struct SWR_STATS_FE *startFE = &pq->start.coreFE;
181 struct SWR_STATS_FE *endFE = &pq->end.coreFE;
182 p_stats->ia_vertices = endFE->IaVertices - startFE->IaVertices;
183 p_stats->ia_primitives = endFE->IaPrimitives - startFE->IaPrimitives;
184 p_stats->vs_invocations = endFE->VsInvocations - startFE->VsInvocations;
185 p_stats->gs_invocations = endFE->GsInvocations - startFE->GsInvocations;
186 p_stats->gs_primitives = endFE->GsPrimitives - startFE->GsPrimitives;
187 p_stats->c_invocations = endFE->CPrimitives - startFE->CPrimitives;
188 p_stats->c_primitives = endFE->CPrimitives - startFE->CPrimitives;
189 p_stats->ps_invocations = end->PsInvocations - start->PsInvocations;
190 p_stats->hs_invocations = endFE->HsInvocations - startFE->HsInvocations;
191 p_stats->ds_invocations = endFE->DsInvocations - startFE->DsInvocations;
192 p_stats->cs_invocations = end->CsInvocations - start->CsInvocations;
193 } break;
194 case PIPE_QUERY_SO_OVERFLOW_PREDICATE: {
195 struct SWR_STATS_FE *start = &pq->start.coreFE;
196 struct SWR_STATS_FE *end = &pq->end.coreFE;
197 uint64_t num_primitives_written =
198 end->SoNumPrimsWritten[index] - start->SoNumPrimsWritten[index];
199 uint64_t primitives_storage_needed =
200 end->SoPrimStorageNeeded[index] - start->SoPrimStorageNeeded[index];
201 result->b = num_primitives_written > primitives_storage_needed;
202 }
203 break;
204 default:
205 assert(0 && "Unsupported query");
206 break;
207 }
208
209 return TRUE;
210 }
211
212 static boolean
213 swr_begin_query(struct pipe_context *pipe, struct pipe_query *q)
214 {
215 struct swr_context *ctx = swr_context(pipe);
216 struct swr_query *pq = swr_query(q);
217
218 assert(!pq->enable_stats && "swr_begin_query: Query is already active!");
219
220 /* Initialize Results */
221 memset(&pq->start, 0, sizeof(pq->start));
222 memset(&pq->end, 0, sizeof(pq->end));
223
224 /* Gather start stats and enable SwrCore counters */
225 pq->result = &pq->start;
226 pq->enable_stats = TRUE;
227 swr_gather_stats(pipe, pq);
228 ctx->active_queries++;
229
230 /* override start timestamp to 0 for TIMESTAMP query */
231 if (pq->type == PIPE_QUERY_TIMESTAMP)
232 pq->start.timestamp = 0;
233
234 return true;
235 }
236
237 static bool
238 swr_end_query(struct pipe_context *pipe, struct pipe_query *q)
239 {
240 struct swr_context *ctx = swr_context(pipe);
241 struct swr_query *pq = swr_query(q);
242
243 assert(ctx->active_queries
244 && "swr_end_query, there are no active queries!");
245 ctx->active_queries--;
246
247 /* Gather end stats and disable SwrCore counters */
248 pq->result = &pq->end;
249 pq->enable_stats = FALSE;
250 swr_gather_stats(pipe, pq);
251 return true;
252 }
253
254
255 boolean
256 swr_check_render_cond(struct pipe_context *pipe)
257 {
258 struct swr_context *ctx = swr_context(pipe);
259 boolean b, wait;
260 uint64_t result;
261
262 if (!ctx->render_cond_query)
263 return TRUE; /* no query predicate, draw normally */
264
265 wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT
266 || ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
267
268 b = pipe->get_query_result(
269 pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result);
270 if (b)
271 return ((!result) == ctx->render_cond_cond);
272 else
273 return TRUE;
274 }
275
276
277 static void
278 swr_set_active_query_state(struct pipe_context *pipe, boolean enable)
279 {
280 }
281
282 void
283 swr_query_init(struct pipe_context *pipe)
284 {
285 struct swr_context *ctx = swr_context(pipe);
286
287 pipe->create_query = swr_create_query;
288 pipe->destroy_query = swr_destroy_query;
289 pipe->begin_query = swr_begin_query;
290 pipe->end_query = swr_end_query;
291 pipe->get_query_result = swr_get_query_result;
292 pipe->set_active_query_state = swr_set_active_query_state;
293
294 ctx->active_queries = 0;
295 }