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_finish(pipe
->screen
, NULL
, pq
->fence
, 0);
67 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
75 swr_get_query_result(struct pipe_context
*pipe
,
78 union pipe_query_result
*result
)
80 struct swr_query
*pq
= swr_query(q
);
81 unsigned index
= pq
->index
;
84 if (!wait
&& !swr_is_fence_done(pq
->fence
))
87 swr_fence_finish(pipe
->screen
, NULL
, pq
->fence
, 0);
88 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
91 /* All values are reset to 0 at swr_begin_query, except starting timestamp.
92 * Counters become simply end values. */
95 case PIPE_QUERY_OCCLUSION_PREDICATE
:
96 result
->b
= pq
->result
.core
.DepthPassCount
!= 0;
98 case PIPE_QUERY_GPU_FINISHED
:
102 case PIPE_QUERY_OCCLUSION_COUNTER
:
103 result
->u64
= pq
->result
.core
.DepthPassCount
;
105 case PIPE_QUERY_TIMESTAMP
:
106 case PIPE_QUERY_TIME_ELAPSED
:
107 result
->u64
= pq
->result
.timestamp_end
- pq
->result
.timestamp_start
;
109 case PIPE_QUERY_PRIMITIVES_GENERATED
:
110 result
->u64
= pq
->result
.coreFE
.IaPrimitives
;
112 case PIPE_QUERY_PRIMITIVES_EMITTED
:
113 result
->u64
= pq
->result
.coreFE
.SoNumPrimsWritten
[index
];
116 case PIPE_QUERY_SO_STATISTICS
: {
117 struct pipe_query_data_so_statistics
*so_stats
= &result
->so_statistics
;
118 so_stats
->num_primitives_written
=
119 pq
->result
.coreFE
.SoNumPrimsWritten
[index
];
120 so_stats
->primitives_storage_needed
=
121 pq
->result
.coreFE
.SoPrimStorageNeeded
[index
];
123 case PIPE_QUERY_TIMESTAMP_DISJOINT
:
124 /* os_get_time_nano returns nanoseconds */
125 result
->timestamp_disjoint
.frequency
= UINT64_C(1000000000);
126 result
->timestamp_disjoint
.disjoint
= FALSE
;
128 case PIPE_QUERY_PIPELINE_STATISTICS
: {
129 struct pipe_query_data_pipeline_statistics
*p_stats
=
130 &result
->pipeline_statistics
;
131 p_stats
->ia_vertices
= pq
->result
.coreFE
.IaVertices
;
132 p_stats
->ia_primitives
= pq
->result
.coreFE
.IaPrimitives
;
133 p_stats
->vs_invocations
= pq
->result
.coreFE
.VsInvocations
;
134 p_stats
->gs_invocations
= pq
->result
.coreFE
.GsInvocations
;
135 p_stats
->gs_primitives
= pq
->result
.coreFE
.GsPrimitives
;
136 p_stats
->c_invocations
= pq
->result
.coreFE
.CPrimitives
;
137 p_stats
->c_primitives
= pq
->result
.coreFE
.CPrimitives
;
138 p_stats
->ps_invocations
= pq
->result
.core
.PsInvocations
;
139 p_stats
->hs_invocations
= pq
->result
.coreFE
.HsInvocations
;
140 p_stats
->ds_invocations
= pq
->result
.coreFE
.DsInvocations
;
141 p_stats
->cs_invocations
= pq
->result
.core
.CsInvocations
;
143 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
: {
144 uint64_t num_primitives_written
=
145 pq
->result
.coreFE
.SoNumPrimsWritten
[index
];
146 uint64_t primitives_storage_needed
=
147 pq
->result
.coreFE
.SoPrimStorageNeeded
[index
];
148 result
->b
= num_primitives_written
> primitives_storage_needed
;
152 assert(0 && "Unsupported query");
160 swr_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
162 struct swr_context
*ctx
= swr_context(pipe
);
163 struct swr_query
*pq
= swr_query(q
);
165 /* Initialize Results */
166 memset(&pq
->result
, 0, sizeof(pq
->result
));
168 case PIPE_QUERY_GPU_FINISHED
:
169 case PIPE_QUERY_TIMESTAMP
:
170 /* nothing to do, but don't want the default */
172 case PIPE_QUERY_TIME_ELAPSED
:
173 pq
->result
.timestamp_start
= swr_get_timestamp(pipe
->screen
);
176 /* Core counters required. Update draw context with location to
178 swr_update_draw_context(ctx
, &pq
->result
);
180 /* Only change stat collection if there are no active queries */
181 if (ctx
->active_queries
== 0) {
182 SwrEnableStatsFE(ctx
->swrContext
, TRUE
);
183 SwrEnableStatsBE(ctx
->swrContext
, TRUE
);
185 ctx
->active_queries
++;
194 swr_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
196 struct swr_context
*ctx
= swr_context(pipe
);
197 struct swr_query
*pq
= swr_query(q
);
200 case PIPE_QUERY_GPU_FINISHED
:
201 /* nothing to do, but don't want the default */
203 case PIPE_QUERY_TIMESTAMP
:
204 case PIPE_QUERY_TIME_ELAPSED
:
205 pq
->result
.timestamp_end
= swr_get_timestamp(pipe
->screen
);
208 /* Stats are updated asynchronously, a fence is used to signal
211 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
212 swr_fence_reference(pipe
->screen
, &pq
->fence
, screen
->flush_fence
);
214 swr_fence_submit(ctx
, pq
->fence
);
216 /* Only change stat collection if there are no active queries */
217 ctx
->active_queries
--;
218 if (ctx
->active_queries
== 0) {
219 SwrEnableStatsFE(ctx
->swrContext
, FALSE
);
220 SwrEnableStatsBE(ctx
->swrContext
, FALSE
);
231 swr_check_render_cond(struct pipe_context
*pipe
)
233 struct swr_context
*ctx
= swr_context(pipe
);
237 if (!ctx
->render_cond_query
)
238 return TRUE
; /* no query predicate, draw normally */
240 wait
= (ctx
->render_cond_mode
== PIPE_RENDER_COND_WAIT
241 || ctx
->render_cond_mode
== PIPE_RENDER_COND_BY_REGION_WAIT
);
243 b
= pipe
->get_query_result(
244 pipe
, ctx
->render_cond_query
, wait
, (union pipe_query_result
*)&result
);
246 return ((!result
) == ctx
->render_cond_cond
);
253 swr_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
258 swr_query_init(struct pipe_context
*pipe
)
260 struct swr_context
*ctx
= swr_context(pipe
);
262 pipe
->create_query
= swr_create_query
;
263 pipe
->destroy_query
= swr_destroy_query
;
264 pipe
->begin_query
= swr_begin_query
;
265 pipe
->end_query
= swr_end_query
;
266 pipe
->get_query_result
= swr_get_query_result
;
267 pipe
->set_active_query_state
= swr_set_active_query_state
;
269 ctx
->active_queries
= 0;