1 /****************************************************************************
2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
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:
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
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
22 ***************************************************************************/
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"
34 static struct swr_query
*
35 swr_query(struct pipe_query
*p
)
37 return (struct swr_query
*)p
;
40 static struct pipe_query
*
41 swr_create_query(struct pipe_context
*pipe
, unsigned type
, unsigned index
)
45 assert(type
< PIPE_QUERY_TYPES
);
46 assert(index
< MAX_SO_STREAMS
);
48 pq
= CALLOC_STRUCT(swr_query
);
55 return (struct pipe_query
*)pq
;
60 swr_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
62 struct swr_query
*pq
= swr_query(q
);
65 if (!swr_is_fence_pending(pq
->fence
)) {
66 swr_fence_submit(swr_context(pipe
), pq
->fence
);
67 swr_fence_finish(pipe
->screen
, pq
->fence
, 0);
69 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
76 // XXX Create a fence callback, rather than stalling SwrWaitForIdle
78 swr_gather_stats(struct pipe_context
*pipe
, struct swr_query
*pq
)
80 struct swr_context
*ctx
= swr_context(pipe
);
83 union pipe_query_result
*result
= pq
->result
;
84 boolean enable_stats
= pq
->enable_stats
;
85 SWR_STATS swr_stats
= {0};
88 if (!swr_is_fence_pending(pq
->fence
)) {
89 swr_fence_submit(ctx
, pq
->fence
);
90 swr_fence_finish(pipe
->screen
, pq
->fence
, 0);
92 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
96 * These queries don't need SWR Stats enabled in the core
100 case PIPE_QUERY_TIMESTAMP
:
101 case PIPE_QUERY_TIME_ELAPSED
:
102 result
->u64
= swr_get_timestamp(pipe
->screen
);
105 case PIPE_QUERY_TIMESTAMP_DISJOINT
:
106 /* nothing to do here */
109 case PIPE_QUERY_GPU_FINISHED
:
110 result
->b
= TRUE
; /* XXX TODO Add an api func to SWR to compare drawId
115 /* Any query that needs SwrCore stats */
120 * All other results are collected from SwrCore counters
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
);
129 case PIPE_QUERY_OCCLUSION_PREDICATE
:
130 case PIPE_QUERY_OCCLUSION_COUNTER
:
131 result
->u64
= swr_stats
.DepthPassCount
;
133 case PIPE_QUERY_PRIMITIVES_GENERATED
:
134 result
->u64
= swr_stats
.IaPrimitives
;
136 case PIPE_QUERY_PRIMITIVES_EMITTED
:
137 result
->u64
= swr_stats
.SoNumPrimsWritten
[pq
->index
];
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
];
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
;
163 assert(0 && "Unsupported query");
167 /* Only change stat collection if there are no active queries */
168 if (ctx
->active_queries
== 0)
169 SwrEnableStats(ctx
->swrContext
, enable_stats
);
174 swr_get_query_result(struct pipe_context
*pipe
,
175 struct pipe_query
*q
,
177 union pipe_query_result
*result
)
179 struct swr_context
*ctx
= swr_context(pipe
);
180 struct swr_query
*pq
= swr_query(q
);
183 if (!swr_is_fence_pending(pq
->fence
)) {
184 swr_fence_submit(ctx
, pq
->fence
);
187 swr_fence_finish(pipe
->screen
, pq
->fence
, 0);
189 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
192 /* XXX: Need to handle counter rollover */
196 case PIPE_QUERY_OCCLUSION_PREDICATE
:
197 result
->b
= pq
->end
.u64
!= pq
->start
.u64
? TRUE
: FALSE
;
199 case PIPE_QUERY_GPU_FINISHED
:
200 result
->b
= pq
->end
.b
;
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
;
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
;
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
;
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
;
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
;
254 assert(0 && "Unsupported query");
262 swr_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
264 struct swr_context
*ctx
= swr_context(pipe
);
265 struct swr_query
*pq
= swr_query(q
);
267 /* Initialize Results */
268 memset(&pq
->start
, 0, sizeof(pq
->start
));
269 memset(&pq
->end
, 0, sizeof(pq
->end
));
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
++;
277 /* override start timestamp to 0 for TIMESTAMP query */
278 if (pq
->type
== PIPE_QUERY_TIMESTAMP
)
285 swr_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
287 struct swr_context
*ctx
= swr_context(pipe
);
288 struct swr_query
*pq
= swr_query(q
);
290 assert(ctx
->active_queries
291 && "swr_end_query, there are no active queries!");
292 ctx
->active_queries
--;
294 /* Gather end stats and disable SwrCore counters */
295 pq
->result
= &pq
->end
;
296 pq
->enable_stats
= FALSE
;
297 swr_gather_stats(pipe
, pq
);
303 swr_check_render_cond(struct pipe_context
*pipe
)
305 struct swr_context
*ctx
= swr_context(pipe
);
309 if (!ctx
->render_cond_query
)
310 return TRUE
; /* no query predicate, draw normally */
312 wait
= (ctx
->render_cond_mode
== PIPE_RENDER_COND_WAIT
313 || ctx
->render_cond_mode
== PIPE_RENDER_COND_BY_REGION_WAIT
);
315 b
= pipe
->get_query_result(
316 pipe
, ctx
->render_cond_query
, wait
, (union pipe_query_result
*)&result
);
318 return ((!result
) == ctx
->render_cond_cond
);
325 swr_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
330 swr_query_init(struct pipe_context
*pipe
)
332 struct swr_context
*ctx
= swr_context(pipe
);
334 pipe
->create_query
= swr_create_query
;
335 pipe
->destroy_query
= swr_destroy_query
;
336 pipe
->begin_query
= swr_begin_query
;
337 pipe
->end_query
= swr_end_query
;
338 pipe
->get_query_result
= swr_get_query_result
;
339 pipe
->set_active_query_state
= swr_set_active_query_state
;
341 ctx
->active_queries
= 0;