Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/swr/swr_query.cpp
4570 views
1
/****************************************************************************
2
* Copyright (C) 2015 Intel Corporation. All Rights Reserved.
3
*
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:
10
*
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
13
* Software.
14
*
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
21
* IN THE SOFTWARE.
22
***************************************************************************/
23
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"
33
34
static struct swr_query *
35
swr_query(struct pipe_query *p)
36
{
37
return (struct swr_query *)p;
38
}
39
40
static struct pipe_query *
41
swr_create_query(struct pipe_context *pipe, unsigned type, unsigned index)
42
{
43
struct swr_query *pq;
44
45
assert(type < PIPE_QUERY_TYPES);
46
assert(index < MAX_SO_STREAMS);
47
48
pq = (struct swr_query *) AlignedMalloc(sizeof(struct swr_query), 64);
49
50
if (pq) {
51
memset(pq, 0, sizeof(*pq));
52
pq->type = type;
53
pq->index = index;
54
}
55
56
return (struct pipe_query *)pq;
57
}
58
59
60
static void
61
swr_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
62
{
63
struct swr_query *pq = swr_query(q);
64
65
if (pq->fence) {
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);
69
}
70
71
AlignedFree(pq);
72
}
73
74
75
static bool
76
swr_get_query_result(struct pipe_context *pipe,
77
struct pipe_query *q,
78
bool wait,
79
union pipe_query_result *result)
80
{
81
struct swr_query *pq = swr_query(q);
82
unsigned index = pq->index;
83
84
if (pq->fence) {
85
if (!wait && !swr_is_fence_done(pq->fence))
86
return false;
87
88
swr_fence_finish(pipe->screen, NULL, pq->fence, 0);
89
swr_fence_reference(pipe->screen, &pq->fence, NULL);
90
}
91
92
/* All values are reset to 0 at swr_begin_query, except starting timestamp.
93
* Counters become simply end values. */
94
switch (pq->type) {
95
/* Booleans */
96
case PIPE_QUERY_OCCLUSION_PREDICATE:
97
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
98
result->b = pq->result.core.DepthPassCount != 0;
99
break;
100
case PIPE_QUERY_GPU_FINISHED:
101
result->b = true;
102
break;
103
/* Counters */
104
case PIPE_QUERY_OCCLUSION_COUNTER:
105
result->u64 = pq->result.core.DepthPassCount;
106
break;
107
case PIPE_QUERY_TIMESTAMP:
108
case PIPE_QUERY_TIME_ELAPSED:
109
result->u64 = pq->result.timestamp_end - pq->result.timestamp_start;
110
break;
111
case PIPE_QUERY_PRIMITIVES_GENERATED:
112
result->u64 = pq->result.coreFE.IaPrimitives;
113
break;
114
case PIPE_QUERY_PRIMITIVES_EMITTED:
115
result->u64 = pq->result.coreFE.SoNumPrimsWritten[index];
116
break;
117
/* Structures */
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];
124
} break;
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;
129
break;
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;
144
} break;
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;
151
}
152
break;
153
default:
154
assert(0 && "Unsupported query");
155
break;
156
}
157
158
return true;
159
}
160
161
static bool
162
swr_begin_query(struct pipe_context *pipe, struct pipe_query *q)
163
{
164
struct swr_context *ctx = swr_context(pipe);
165
struct swr_query *pq = swr_query(q);
166
167
/* Initialize Results */
168
memset(&pq->result, 0, sizeof(pq->result));
169
switch (pq->type) {
170
case PIPE_QUERY_GPU_FINISHED:
171
case PIPE_QUERY_TIMESTAMP:
172
/* nothing to do, but don't want the default */
173
break;
174
case PIPE_QUERY_TIME_ELAPSED:
175
pq->result.timestamp_start = swr_get_timestamp(pipe->screen);
176
break;
177
default:
178
/* Core counters required. Update draw context with location to
179
* store results. */
180
swr_update_draw_context(ctx, &pq->result);
181
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);
186
}
187
ctx->active_queries++;
188
break;
189
}
190
191
192
return true;
193
}
194
195
static bool
196
swr_end_query(struct pipe_context *pipe, struct pipe_query *q)
197
{
198
struct swr_context *ctx = swr_context(pipe);
199
struct swr_query *pq = swr_query(q);
200
201
switch (pq->type) {
202
case PIPE_QUERY_GPU_FINISHED:
203
/* nothing to do, but don't want the default */
204
break;
205
case PIPE_QUERY_TIMESTAMP:
206
case PIPE_QUERY_TIME_ELAPSED:
207
pq->result.timestamp_end = swr_get_timestamp(pipe->screen);
208
break;
209
default:
210
/* Stats are updated asynchronously, a fence is used to signal
211
* completion. */
212
if (!pq->fence) {
213
struct swr_screen *screen = swr_screen(pipe->screen);
214
swr_fence_reference(pipe->screen, &pq->fence, screen->flush_fence);
215
}
216
swr_fence_submit(ctx, pq->fence);
217
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);
223
}
224
225
break;
226
}
227
228
return true;
229
}
230
231
232
bool
233
swr_check_render_cond(struct pipe_context *pipe)
234
{
235
struct swr_context *ctx = swr_context(pipe);
236
bool b, wait;
237
uint64_t result;
238
239
if (!ctx->render_cond_query)
240
return true; /* no query predicate, draw normally */
241
242
wait = (ctx->render_cond_mode == PIPE_RENDER_COND_WAIT
243
|| ctx->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
244
245
b = pipe->get_query_result(
246
pipe, ctx->render_cond_query, wait, (union pipe_query_result *)&result);
247
if (b)
248
return ((!result) == ctx->render_cond_cond);
249
else
250
return true;
251
}
252
253
254
static void
255
swr_set_active_query_state(struct pipe_context *pipe, bool enable)
256
{
257
}
258
259
void
260
swr_query_init(struct pipe_context *pipe)
261
{
262
struct swr_context *ctx = swr_context(pipe);
263
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;
270
271
ctx->active_queries = 0;
272
}
273
274