Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/etnaviv/etnaviv_query_acc.c
4570 views
1
/*
2
* Copyright (c) 2017 Etnaviv Project
3
* Copyright (C) 2017 Zodiac Inflight Innovations
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sub license,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the
13
* next paragraph) shall be included in all copies or substantial portions
14
* of the Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
* DEALINGS IN THE SOFTWARE.
23
*
24
* Authors:
25
* Rob Clark <[email protected]>
26
* Christian Gmeiner <[email protected]>
27
*/
28
29
#include "util/u_inlines.h"
30
#include "util/u_memory.h"
31
32
#include "etnaviv_context.h"
33
#include "etnaviv_debug.h"
34
#include "etnaviv_emit.h"
35
#include "etnaviv_query_acc.h"
36
#include "etnaviv_screen.h"
37
38
39
extern const struct etna_acc_sample_provider occlusion_provider;
40
extern const struct etna_acc_sample_provider perfmon_provider;
41
42
static const struct etna_acc_sample_provider *acc_sample_provider[] =
43
{
44
&occlusion_provider,
45
&perfmon_provider,
46
};
47
48
static void
49
etna_acc_destroy_query(struct etna_context *ctx, struct etna_query *q)
50
{
51
struct etna_acc_query *aq = etna_acc_query(q);
52
53
pipe_resource_reference(&aq->prsc, NULL);
54
list_del(&aq->node);
55
56
FREE(aq);
57
}
58
59
static void
60
realloc_query_bo(struct etna_context *ctx, struct etna_acc_query *aq)
61
{
62
struct etna_resource *rsc;
63
void *map;
64
65
pipe_resource_reference(&aq->prsc, NULL);
66
67
/* allocate resource with space for 64 * 64bit values */
68
aq->prsc = pipe_buffer_create(&ctx->screen->base, PIPE_BIND_QUERY_BUFFER,
69
0, 0x1000);
70
71
/* don't assume the buffer is zero-initialized */
72
rsc = etna_resource(aq->prsc);
73
74
etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_WRITE);
75
76
map = etna_bo_map(rsc->bo);
77
memset(map, 0, 0x1000);
78
etna_bo_cpu_fini(rsc->bo);
79
}
80
81
static void
82
etna_acc_begin_query(struct etna_context *ctx, struct etna_query *q)
83
{
84
struct etna_acc_query *aq = etna_acc_query(q);
85
const struct etna_acc_sample_provider *p = aq->provider;
86
87
/* ->begin_query() discards previous results, so realloc bo */
88
realloc_query_bo(ctx, aq);
89
90
p->resume(aq, ctx);
91
aq->samples++;
92
93
/* add to active list */
94
assert(list_is_empty(&aq->node));
95
list_addtail(&aq->node, &ctx->active_acc_queries);
96
}
97
98
static void
99
etna_acc_end_query(struct etna_context *ctx, struct etna_query *q)
100
{
101
struct etna_acc_query *aq = etna_acc_query(q);
102
const struct etna_acc_sample_provider *p = aq->provider;
103
104
p->suspend(aq, ctx);
105
aq->samples++;
106
107
/* remove from active list */
108
list_delinit(&aq->node);
109
}
110
111
static bool
112
etna_acc_get_query_result(struct etna_context *ctx, struct etna_query *q,
113
bool wait, union pipe_query_result *result)
114
{
115
struct etna_acc_query *aq = etna_acc_query(q);
116
struct etna_resource *rsc = etna_resource(aq->prsc);
117
const struct etna_acc_sample_provider *p = aq->provider;
118
119
assert(list_is_empty(&aq->node));
120
121
if (rsc->status & ETNA_PENDING_WRITE) {
122
if (!wait) {
123
/* piglit spec@arb_occlusion_query@occlusion_query_conform
124
* test, and silly apps perhaps, get stuck in a loop trying
125
* to get query result forever with wait==false.. we don't
126
* wait to flush unnecessarily but we also don't want to
127
* spin forever.
128
*/
129
if (aq->no_wait_cnt++ > 5) {
130
ctx->base.flush(&ctx->base, NULL, 0);
131
aq->no_wait_cnt = 0;
132
}
133
134
return false;
135
} else {
136
/* flush that GPU executes all query related actions */
137
ctx->base.flush(&ctx->base, NULL, 0);
138
}
139
}
140
141
/* get the result */
142
int ret = etna_bo_cpu_prep(rsc->bo, DRM_ETNA_PREP_READ);
143
if (ret)
144
return false;
145
146
void *ptr = etna_bo_map(rsc->bo);
147
bool success = p->result(aq, ptr, result);
148
149
if (success)
150
aq->samples = 0;
151
152
etna_bo_cpu_fini(rsc->bo);
153
154
return success;
155
}
156
157
static const struct etna_query_funcs acc_query_funcs = {
158
.destroy_query = etna_acc_destroy_query,
159
.begin_query = etna_acc_begin_query,
160
.end_query = etna_acc_end_query,
161
.get_query_result = etna_acc_get_query_result,
162
};
163
164
struct etna_query *
165
etna_acc_create_query(struct etna_context *ctx, unsigned query_type)
166
{
167
const struct etna_acc_sample_provider *p = NULL;
168
struct etna_acc_query *aq;
169
struct etna_query *q;
170
171
/* find a sample provide for the requested query type */
172
for (unsigned i = 0; i < ARRAY_SIZE(acc_sample_provider); i++) {
173
p = acc_sample_provider[i];
174
175
if (p->supports(query_type))
176
break;
177
else
178
p = NULL;
179
}
180
181
if (!p)
182
return NULL;
183
184
aq = p->allocate(ctx, query_type);
185
if (!aq)
186
return NULL;
187
188
aq->provider = p;
189
190
list_inithead(&aq->node);
191
192
q = &aq->base;
193
q->funcs = &acc_query_funcs;
194
q->type = query_type;
195
196
return q;
197
}
198
199