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 "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"
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
= (struct swr_query
*) AlignedMalloc(sizeof(struct swr_query
), 64);
49 memset(pq
, 0, sizeof(*pq
));
56 return (struct pipe_query
*)pq
;
61 swr_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
63 struct swr_query
*pq
= swr_query(q
);
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
);
76 swr_get_query_result(struct pipe_context
*pipe
,
79 union pipe_query_result
*result
)
81 struct swr_query
*pq
= swr_query(q
);
82 unsigned index
= pq
->index
;
85 if (!wait
&& !swr_is_fence_done(pq
->fence
))
88 swr_fence_finish(pipe
->screen
, NULL
, pq
->fence
, 0);
89 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
92 /* All values are reset to 0 at swr_begin_query, except starting timestamp.
93 * Counters become simply end values. */
96 case PIPE_QUERY_OCCLUSION_PREDICATE
:
97 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
98 result
->b
= pq
->result
.core
.DepthPassCount
!= 0;
100 case PIPE_QUERY_GPU_FINISHED
:
104 case PIPE_QUERY_OCCLUSION_COUNTER
:
105 result
->u64
= pq
->result
.core
.DepthPassCount
;
107 case PIPE_QUERY_TIMESTAMP
:
108 case PIPE_QUERY_TIME_ELAPSED
:
109 result
->u64
= pq
->result
.timestamp_end
- pq
->result
.timestamp_start
;
111 case PIPE_QUERY_PRIMITIVES_GENERATED
:
112 result
->u64
= pq
->result
.coreFE
.IaPrimitives
;
114 case PIPE_QUERY_PRIMITIVES_EMITTED
:
115 result
->u64
= pq
->result
.coreFE
.SoNumPrimsWritten
[index
];
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
];
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
;
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
;
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
;
154 assert(0 && "Unsupported query");
162 swr_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
164 struct swr_context
*ctx
= swr_context(pipe
);
165 struct swr_query
*pq
= swr_query(q
);
167 /* Initialize Results */
168 memset(&pq
->result
, 0, sizeof(pq
->result
));
170 case PIPE_QUERY_GPU_FINISHED
:
171 case PIPE_QUERY_TIMESTAMP
:
172 /* nothing to do, but don't want the default */
174 case PIPE_QUERY_TIME_ELAPSED
:
175 pq
->result
.timestamp_start
= swr_get_timestamp(pipe
->screen
);
178 /* Core counters required. Update draw context with location to
180 swr_update_draw_context(ctx
, &pq
->result
);
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
);
187 ctx
->active_queries
++;
196 swr_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
198 struct swr_context
*ctx
= swr_context(pipe
);
199 struct swr_query
*pq
= swr_query(q
);
202 case PIPE_QUERY_GPU_FINISHED
:
203 /* nothing to do, but don't want the default */
205 case PIPE_QUERY_TIMESTAMP
:
206 case PIPE_QUERY_TIME_ELAPSED
:
207 pq
->result
.timestamp_end
= swr_get_timestamp(pipe
->screen
);
210 /* Stats are updated asynchronously, a fence is used to signal
213 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
214 swr_fence_reference(pipe
->screen
, &pq
->fence
, screen
->flush_fence
);
216 swr_fence_submit(ctx
, pq
->fence
);
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
);
233 swr_check_render_cond(struct pipe_context
*pipe
)
235 struct swr_context
*ctx
= swr_context(pipe
);
239 if (!ctx
->render_cond_query
)
240 return true; /* no query predicate, draw normally */
242 wait
= (ctx
->render_cond_mode
== PIPE_RENDER_COND_WAIT
243 || ctx
->render_cond_mode
== PIPE_RENDER_COND_BY_REGION_WAIT
);
245 b
= pipe
->get_query_result(
246 pipe
, ctx
->render_cond_query
, wait
, (union pipe_query_result
*)&result
);
248 return ((!result
) == ctx
->render_cond_cond
);
255 swr_set_active_query_state(struct pipe_context
*pipe
, bool enable
)
260 swr_query_init(struct pipe_context
*pipe
)
262 struct swr_context
*ctx
= swr_context(pipe
);
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
;
271 ctx
->active_queries
= 0;