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_gather_stats(struct pipe_context
*pipe
, struct swr_query
*pq
)
77 struct swr_context
*ctx
= swr_context(pipe
);
80 struct swr_query_result
*result
= pq
->result
;
81 boolean enable_stats
= pq
->enable_stats
;
83 /* A few results don't require the core, so don't involve it */
85 case PIPE_QUERY_TIMESTAMP
:
86 case PIPE_QUERY_TIME_ELAPSED
:
87 result
->timestamp
= swr_get_timestamp(pipe
->screen
);
89 case PIPE_QUERY_TIMESTAMP_DISJOINT
:
90 case PIPE_QUERY_GPU_FINISHED
:
91 /* nothing to do here */
94 /* TODO: should fence instead of stalling pipeline */
95 SwrWaitForIdle(ctx
->swrContext
);
96 memcpy(&result
->core
, &ctx
->stats
, sizeof(result
->core
));
100 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
101 swr_fence_reference(pipe
->screen
, &pq
->fence
, screen
->flush_fence
);
103 swr_fence_submit(ctx
, pq
->fence
);
106 /* Only change stat collection if there are no active queries */
107 if (ctx
->active_queries
== 0)
108 SwrEnableStats(ctx
->swrContext
, enable_stats
);
116 swr_get_query_result(struct pipe_context
*pipe
,
117 struct pipe_query
*q
,
119 union pipe_query_result
*result
)
121 struct swr_query
*pq
= swr_query(q
);
122 struct swr_query_result
*start
= &pq
->start
;
123 struct swr_query_result
*end
= &pq
->end
;
124 unsigned index
= pq
->index
;
127 if (!wait
&& !swr_is_fence_done(pq
->fence
))
130 swr_fence_finish(pipe
->screen
, NULL
, pq
->fence
, 0);
131 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
134 /* XXX: Need to handle counter rollover */
138 case PIPE_QUERY_OCCLUSION_PREDICATE
:
139 result
->b
= end
->core
.DepthPassCount
!= start
->core
.DepthPassCount
;
141 case PIPE_QUERY_GPU_FINISHED
:
145 case PIPE_QUERY_OCCLUSION_COUNTER
:
146 result
->u64
= end
->core
.DepthPassCount
- start
->core
.DepthPassCount
;
148 case PIPE_QUERY_TIMESTAMP
:
149 case PIPE_QUERY_TIME_ELAPSED
:
150 result
->u64
= end
->timestamp
- start
->timestamp
;
152 case PIPE_QUERY_PRIMITIVES_GENERATED
:
153 result
->u64
= end
->core
.IaPrimitives
- start
->core
.IaPrimitives
;
155 case PIPE_QUERY_PRIMITIVES_EMITTED
:
156 result
->u64
= end
->core
.SoNumPrimsWritten
[index
]
157 - start
->core
.SoNumPrimsWritten
[index
];
160 case PIPE_QUERY_SO_STATISTICS
: {
161 struct pipe_query_data_so_statistics
*so_stats
= &result
->so_statistics
;
162 struct SWR_STATS
*start
= &pq
->start
.core
;
163 struct SWR_STATS
*end
= &pq
->end
.core
;
164 so_stats
->num_primitives_written
=
165 end
->SoNumPrimsWritten
[index
] - start
->SoNumPrimsWritten
[index
];
166 so_stats
->primitives_storage_needed
=
167 end
->SoPrimStorageNeeded
[index
] - start
->SoPrimStorageNeeded
[index
];
169 case PIPE_QUERY_TIMESTAMP_DISJOINT
:
170 /* os_get_time_nano returns nanoseconds */
171 result
->timestamp_disjoint
.frequency
= UINT64_C(1000000000);
172 result
->timestamp_disjoint
.disjoint
= FALSE
;
174 case PIPE_QUERY_PIPELINE_STATISTICS
: {
175 struct pipe_query_data_pipeline_statistics
*p_stats
=
176 &result
->pipeline_statistics
;
177 struct SWR_STATS
*start
= &pq
->start
.core
;
178 struct SWR_STATS
*end
= &pq
->end
.core
;
179 p_stats
->ia_vertices
= end
->IaVertices
- start
->IaVertices
;
180 p_stats
->ia_primitives
= end
->IaPrimitives
- start
->IaPrimitives
;
181 p_stats
->vs_invocations
= end
->VsInvocations
- start
->VsInvocations
;
182 p_stats
->gs_invocations
= end
->GsInvocations
- start
->GsInvocations
;
183 p_stats
->gs_primitives
= end
->GsPrimitives
- start
->GsPrimitives
;
184 p_stats
->c_invocations
= end
->CPrimitives
- start
->CPrimitives
;
185 p_stats
->c_primitives
= end
->CPrimitives
- start
->CPrimitives
;
186 p_stats
->ps_invocations
= end
->PsInvocations
- start
->PsInvocations
;
187 p_stats
->hs_invocations
= end
->HsInvocations
- start
->HsInvocations
;
188 p_stats
->ds_invocations
= end
->DsInvocations
- start
->DsInvocations
;
189 p_stats
->cs_invocations
= end
->CsInvocations
- start
->CsInvocations
;
191 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
: {
192 struct SWR_STATS
*start
= &pq
->start
.core
;
193 struct SWR_STATS
*end
= &pq
->end
.core
;
194 uint64_t num_primitives_written
=
195 end
->SoNumPrimsWritten
[index
] - start
->SoNumPrimsWritten
[index
];
196 uint64_t primitives_storage_needed
=
197 end
->SoPrimStorageNeeded
[index
] - start
->SoPrimStorageNeeded
[index
];
198 result
->b
= num_primitives_written
> primitives_storage_needed
;
202 assert(0 && "Unsupported query");
210 swr_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
212 struct swr_context
*ctx
= swr_context(pipe
);
213 struct swr_query
*pq
= swr_query(q
);
215 assert(!pq
->enable_stats
&& "swr_begin_query: Query is already active!");
217 /* Initialize Results */
218 memset(&pq
->start
, 0, sizeof(pq
->start
));
219 memset(&pq
->end
, 0, sizeof(pq
->end
));
221 /* Gather start stats and enable SwrCore counters */
222 pq
->result
= &pq
->start
;
223 pq
->enable_stats
= TRUE
;
224 swr_gather_stats(pipe
, pq
);
225 ctx
->active_queries
++;
227 /* override start timestamp to 0 for TIMESTAMP query */
228 if (pq
->type
== PIPE_QUERY_TIMESTAMP
)
229 pq
->start
.timestamp
= 0;
235 swr_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
237 struct swr_context
*ctx
= swr_context(pipe
);
238 struct swr_query
*pq
= swr_query(q
);
240 assert(ctx
->active_queries
241 && "swr_end_query, there are no active queries!");
242 ctx
->active_queries
--;
244 /* Gather end stats and disable SwrCore counters */
245 pq
->result
= &pq
->end
;
246 pq
->enable_stats
= FALSE
;
247 swr_gather_stats(pipe
, pq
);
253 swr_check_render_cond(struct pipe_context
*pipe
)
255 struct swr_context
*ctx
= swr_context(pipe
);
259 if (!ctx
->render_cond_query
)
260 return TRUE
; /* no query predicate, draw normally */
262 wait
= (ctx
->render_cond_mode
== PIPE_RENDER_COND_WAIT
263 || ctx
->render_cond_mode
== PIPE_RENDER_COND_BY_REGION_WAIT
);
265 b
= pipe
->get_query_result(
266 pipe
, ctx
->render_cond_query
, wait
, (union pipe_query_result
*)&result
);
268 return ((!result
) == ctx
->render_cond_cond
);
275 swr_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
280 swr_query_init(struct pipe_context
*pipe
)
282 struct swr_context
*ctx
= swr_context(pipe
);
284 pipe
->create_query
= swr_create_query
;
285 pipe
->destroy_query
= swr_destroy_query
;
286 pipe
->begin_query
= swr_begin_query
;
287 pipe
->end_query
= swr_end_query
;
288 pipe
->get_query_result
= swr_get_query_result
;
289 pipe
->set_active_query_state
= swr_set_active_query_state
;
291 ctx
->active_queries
= 0;