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
));
97 memcpy(&result
->coreFE
, &ctx
->statsFE
, sizeof(result
->coreFE
));
101 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
102 swr_fence_reference(pipe
->screen
, &pq
->fence
, screen
->flush_fence
);
104 swr_fence_submit(ctx
, pq
->fence
);
107 /* Only change stat collection if there are no active queries */
108 if (ctx
->active_queries
== 0)
109 SwrEnableStats(ctx
->swrContext
, enable_stats
);
117 swr_get_query_result(struct pipe_context
*pipe
,
118 struct pipe_query
*q
,
120 union pipe_query_result
*result
)
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
;
128 if (!wait
&& !swr_is_fence_done(pq
->fence
))
131 swr_fence_finish(pipe
->screen
, NULL
, pq
->fence
, 0);
132 swr_fence_reference(pipe
->screen
, &pq
->fence
, NULL
);
135 /* XXX: Need to handle counter rollover */
139 case PIPE_QUERY_OCCLUSION_PREDICATE
:
140 result
->b
= end
->core
.DepthPassCount
!= start
->core
.DepthPassCount
;
142 case PIPE_QUERY_GPU_FINISHED
:
146 case PIPE_QUERY_OCCLUSION_COUNTER
:
147 result
->u64
= end
->core
.DepthPassCount
- start
->core
.DepthPassCount
;
149 case PIPE_QUERY_TIMESTAMP
:
150 case PIPE_QUERY_TIME_ELAPSED
:
151 result
->u64
= end
->timestamp
- start
->timestamp
;
153 case PIPE_QUERY_PRIMITIVES_GENERATED
:
154 result
->u64
= end
->coreFE
.IaPrimitives
- start
->coreFE
.IaPrimitives
;
156 case PIPE_QUERY_PRIMITIVES_EMITTED
:
157 result
->u64
= end
->coreFE
.SoNumPrimsWritten
[index
]
158 - start
->coreFE
.SoNumPrimsWritten
[index
];
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
];
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
;
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
;
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
;
205 assert(0 && "Unsupported query");
213 swr_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
215 struct swr_context
*ctx
= swr_context(pipe
);
216 struct swr_query
*pq
= swr_query(q
);
218 assert(!pq
->enable_stats
&& "swr_begin_query: Query is already active!");
220 /* Initialize Results */
221 memset(&pq
->start
, 0, sizeof(pq
->start
));
222 memset(&pq
->end
, 0, sizeof(pq
->end
));
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
++;
230 /* override start timestamp to 0 for TIMESTAMP query */
231 if (pq
->type
== PIPE_QUERY_TIMESTAMP
)
232 pq
->start
.timestamp
= 0;
238 swr_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
240 struct swr_context
*ctx
= swr_context(pipe
);
241 struct swr_query
*pq
= swr_query(q
);
243 assert(ctx
->active_queries
244 && "swr_end_query, there are no active queries!");
245 ctx
->active_queries
--;
247 /* Gather end stats and disable SwrCore counters */
248 pq
->result
= &pq
->end
;
249 pq
->enable_stats
= FALSE
;
250 swr_gather_stats(pipe
, pq
);
256 swr_check_render_cond(struct pipe_context
*pipe
)
258 struct swr_context
*ctx
= swr_context(pipe
);
262 if (!ctx
->render_cond_query
)
263 return TRUE
; /* no query predicate, draw normally */
265 wait
= (ctx
->render_cond_mode
== PIPE_RENDER_COND_WAIT
266 || ctx
->render_cond_mode
== PIPE_RENDER_COND_BY_REGION_WAIT
);
268 b
= pipe
->get_query_result(
269 pipe
, ctx
->render_cond_query
, wait
, (union pipe_query_result
*)&result
);
271 return ((!result
) == ctx
->render_cond_cond
);
278 swr_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
283 swr_query_init(struct pipe_context
*pipe
)
285 struct swr_context
*ctx
= swr_context(pipe
);
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
;
294 ctx
->active_queries
= 0;