Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv30/nv30_query.c
4574 views
1
/*
2
* Copyright 2012 Red Hat Inc.
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 shall be included in
12
* all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
* OTHER DEALINGS IN THE SOFTWARE.
21
*
22
* Authors: Ben Skeggs
23
*
24
*/
25
26
#include "nv_object.xml.h"
27
#include "nv30/nv30-40_3d.xml.h"
28
#include "nv30/nv30_screen.h"
29
#include "nv30/nv30_context.h"
30
31
#define LIST_FIRST_ENTRY(__type, __item, __field) \
32
LIST_ENTRY(__type, (__item)->next, __field)
33
34
struct nv30_query_object {
35
struct list_head list;
36
struct nouveau_heap *hw;
37
};
38
39
static volatile void *
40
nv30_ntfy(struct nv30_screen *screen, struct nv30_query_object *qo)
41
{
42
struct nv04_notify *query = screen->query->data;
43
struct nouveau_bo *notify = screen->notify;
44
volatile void *ntfy = NULL;
45
46
if (qo && qo->hw)
47
ntfy = (char *)notify->map + query->offset + qo->hw->start;
48
49
return ntfy;
50
}
51
52
static void
53
nv30_query_object_del(struct nv30_screen *screen, struct nv30_query_object **po)
54
{
55
struct nv30_query_object *qo = *po; *po = NULL;
56
if (qo) {
57
volatile uint32_t *ntfy = nv30_ntfy(screen, qo);
58
while (ntfy[3] & 0xff000000) {
59
}
60
nouveau_heap_free(&qo->hw);
61
list_del(&qo->list);
62
FREE(qo);
63
}
64
}
65
66
static struct nv30_query_object *
67
nv30_query_object_new(struct nv30_screen *screen)
68
{
69
struct nv30_query_object *oq, *qo = CALLOC_STRUCT(nv30_query_object);
70
volatile uint32_t *ntfy;
71
72
if (!qo)
73
return NULL;
74
75
/* allocate a new hw query object, if no hw objects left we need to
76
* spin waiting for one to become free
77
*/
78
while (nouveau_heap_alloc(screen->query_heap, 32, NULL, &qo->hw)) {
79
oq = LIST_FIRST_ENTRY(struct nv30_query_object, &screen->queries, list);
80
nv30_query_object_del(screen, &oq);
81
}
82
83
list_addtail(&qo->list, &screen->queries);
84
85
ntfy = nv30_ntfy(screen, qo);
86
ntfy[0] = 0x00000000;
87
ntfy[1] = 0x00000000;
88
ntfy[2] = 0x00000000;
89
ntfy[3] = 0x01000000;
90
return qo;
91
}
92
93
struct nv30_query {
94
struct nv30_query_object *qo[2];
95
unsigned type;
96
uint32_t report;
97
uint32_t enable;
98
uint64_t result;
99
};
100
101
static inline struct nv30_query *
102
nv30_query(struct pipe_query *pipe)
103
{
104
return (struct nv30_query *)pipe;
105
}
106
107
static struct pipe_query *
108
nv30_query_create(struct pipe_context *pipe, unsigned type, unsigned index)
109
{
110
struct nv30_query *q = CALLOC_STRUCT(nv30_query);
111
if (!q)
112
return NULL;
113
114
q->type = type;
115
116
switch (q->type) {
117
case PIPE_QUERY_TIMESTAMP:
118
case PIPE_QUERY_TIME_ELAPSED:
119
q->enable = 0x0000;
120
q->report = 1;
121
break;
122
case PIPE_QUERY_OCCLUSION_COUNTER:
123
case PIPE_QUERY_OCCLUSION_PREDICATE:
124
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
125
q->enable = NV30_3D_QUERY_ENABLE;
126
q->report = 1;
127
break;
128
case NV30_QUERY_ZCULL_0:
129
case NV30_QUERY_ZCULL_1:
130
case NV30_QUERY_ZCULL_2:
131
case NV30_QUERY_ZCULL_3:
132
q->enable = 0x1804;
133
q->report = 2 + (q->type - NV30_QUERY_ZCULL_0);
134
break;
135
default:
136
FREE(q);
137
return NULL;
138
}
139
140
return (struct pipe_query *)q;
141
}
142
143
static void
144
nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
145
{
146
FREE(pq);
147
}
148
149
static bool
150
nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
151
{
152
struct nv30_context *nv30 = nv30_context(pipe);
153
struct nv30_query *q = nv30_query(pq);
154
struct nouveau_pushbuf *push = nv30->base.pushbuf;
155
156
switch (q->type) {
157
case PIPE_QUERY_TIME_ELAPSED:
158
q->qo[0] = nv30_query_object_new(nv30->screen);
159
if (q->qo[0]) {
160
BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
161
PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start);
162
}
163
break;
164
case PIPE_QUERY_TIMESTAMP:
165
return true;
166
default:
167
BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1);
168
PUSH_DATA (push, q->report);
169
break;
170
}
171
172
if (q->enable) {
173
BEGIN_NV04(push, SUBC_3D(q->enable), 1);
174
PUSH_DATA (push, 1);
175
}
176
return true;
177
}
178
179
static bool
180
nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq)
181
{
182
struct nv30_context *nv30 = nv30_context(pipe);
183
struct nv30_screen *screen = nv30->screen;
184
struct nv30_query *q = nv30_query(pq);
185
struct nouveau_pushbuf *push = nv30->base.pushbuf;
186
187
q->qo[1] = nv30_query_object_new(screen);
188
if (q->qo[1]) {
189
BEGIN_NV04(push, NV30_3D(QUERY_GET), 1);
190
PUSH_DATA (push, (q->report << 24) | q->qo[1]->hw->start);
191
}
192
193
if (q->enable) {
194
BEGIN_NV04(push, SUBC_3D(q->enable), 1);
195
PUSH_DATA (push, 0);
196
}
197
PUSH_KICK (push);
198
return true;
199
}
200
201
static bool
202
nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq,
203
bool wait, union pipe_query_result *result)
204
{
205
struct nv30_screen *screen = nv30_screen(pipe->screen);
206
struct nv30_query *q = nv30_query(pq);
207
volatile uint32_t *ntfy0 = nv30_ntfy(screen, q->qo[0]);
208
volatile uint32_t *ntfy1 = nv30_ntfy(screen, q->qo[1]);
209
210
if (ntfy1) {
211
while (ntfy1[3] & 0xff000000) {
212
if (!wait)
213
return false;
214
}
215
216
switch (q->type) {
217
case PIPE_QUERY_TIMESTAMP:
218
q->result = *(uint64_t *)&ntfy1[0];
219
break;
220
case PIPE_QUERY_TIME_ELAPSED:
221
q->result = *(uint64_t *)&ntfy1[0] - *(uint64_t *)&ntfy0[0];
222
break;
223
default:
224
q->result = ntfy1[2];
225
break;
226
}
227
228
nv30_query_object_del(screen, &q->qo[0]);
229
nv30_query_object_del(screen, &q->qo[1]);
230
}
231
232
if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
233
q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE)
234
result->b = !!q->result;
235
else
236
result->u64 = q->result;
237
return true;
238
}
239
240
static void
241
nv40_query_render_condition(struct pipe_context *pipe,
242
struct pipe_query *pq,
243
bool condition, enum pipe_render_cond_flag mode)
244
{
245
struct nv30_context *nv30 = nv30_context(pipe);
246
struct nv30_query *q = nv30_query(pq);
247
struct nouveau_pushbuf *push = nv30->base.pushbuf;
248
249
nv30->render_cond_query = pq;
250
nv30->render_cond_mode = mode;
251
nv30->render_cond_cond = condition;
252
253
if (!pq) {
254
BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
255
PUSH_DATA (push, 0x01000000);
256
return;
257
}
258
259
if (mode == PIPE_RENDER_COND_WAIT ||
260
mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
261
BEGIN_NV04(push, SUBC_3D(0x0110), 1);
262
PUSH_DATA (push, 0);
263
}
264
265
BEGIN_NV04(push, SUBC_3D(0x1e98), 1);
266
PUSH_DATA (push, 0x02000000 | q->qo[1]->hw->start);
267
}
268
269
static void
270
nv30_set_active_query_state(struct pipe_context *pipe, bool enable)
271
{
272
}
273
274
void
275
nv30_query_init(struct pipe_context *pipe)
276
{
277
struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
278
279
pipe->create_query = nv30_query_create;
280
pipe->destroy_query = nv30_query_destroy;
281
pipe->begin_query = nv30_query_begin;
282
pipe->end_query = nv30_query_end;
283
pipe->get_query_result = nv30_query_result;
284
pipe->set_active_query_state = nv30_set_active_query_state;
285
if (eng3d->oclass >= NV40_3D_CLASS)
286
pipe->render_condition = nv40_query_render_condition;
287
}
288
289