Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/svga/svga_pipe_query.c
4570 views
1
/**********************************************************
2
* Copyright 2008-2015 VMware, Inc. All rights reserved.
3
*
4
* Permission is hereby granted, free of charge, to any person
5
* obtaining a copy of this software and associated documentation
6
* files (the "Software"), to deal in the Software without
7
* restriction, including without limitation the rights to use, copy,
8
* modify, merge, publish, distribute, sublicense, and/or sell copies
9
* of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be
13
* included in all copies or substantial portions of the Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*
24
**********************************************************/
25
26
#include "pipe/p_state.h"
27
#include "pipe/p_context.h"
28
29
#include "util/u_bitmask.h"
30
#include "util/u_memory.h"
31
32
#include "svga_cmd.h"
33
#include "svga_context.h"
34
#include "svga_screen.h"
35
#include "svga_resource_buffer.h"
36
#include "svga_winsys.h"
37
#include "svga_debug.h"
38
39
40
/* Fixme: want a public base class for all pipe structs, even if there
41
* isn't much in them.
42
*/
43
struct pipe_query {
44
int dummy;
45
};
46
47
struct svga_query {
48
struct pipe_query base;
49
unsigned type; /**< PIPE_QUERY_x or SVGA_QUERY_x */
50
SVGA3dQueryType svga_type; /**< SVGA3D_QUERYTYPE_x or unused */
51
52
unsigned id; /** Per-context query identifier */
53
boolean active; /** TRUE if query is active */
54
55
struct pipe_fence_handle *fence;
56
57
/** For PIPE_QUERY_OCCLUSION_COUNTER / SVGA3D_QUERYTYPE_OCCLUSION */
58
59
/* For VGPU9 */
60
struct svga_winsys_buffer *hwbuf;
61
volatile SVGA3dQueryResult *queryResult;
62
63
/** For VGPU10 */
64
struct svga_winsys_gb_query *gb_query;
65
SVGA3dDXQueryFlags flags;
66
unsigned offset; /**< offset to the gb_query memory */
67
struct pipe_query *predicate; /** The associated query that can be used for predicate */
68
69
/** For non-GPU SVGA_QUERY_x queries */
70
uint64_t begin_count, end_count;
71
};
72
73
74
/** cast wrapper */
75
static inline struct svga_query *
76
svga_query(struct pipe_query *q)
77
{
78
return (struct svga_query *)q;
79
}
80
81
/**
82
* VGPU9
83
*/
84
85
static bool
86
svga_get_query_result(struct pipe_context *pipe,
87
struct pipe_query *q,
88
bool wait,
89
union pipe_query_result *result);
90
91
static enum pipe_error
92
define_query_vgpu9(struct svga_context *svga,
93
struct svga_query *sq)
94
{
95
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
96
97
sq->hwbuf = svga_winsys_buffer_create(svga, 1,
98
SVGA_BUFFER_USAGE_PINNED,
99
sizeof *sq->queryResult);
100
if (!sq->hwbuf)
101
return PIPE_ERROR_OUT_OF_MEMORY;
102
103
sq->queryResult = (SVGA3dQueryResult *)
104
sws->buffer_map(sws, sq->hwbuf, PIPE_MAP_WRITE);
105
if (!sq->queryResult) {
106
sws->buffer_destroy(sws, sq->hwbuf);
107
return PIPE_ERROR_OUT_OF_MEMORY;
108
}
109
110
sq->queryResult->totalSize = sizeof *sq->queryResult;
111
sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
112
113
/* We request the buffer to be pinned and assume it is always mapped.
114
* The reason is that we don't want to wait for fences when checking the
115
* query status.
116
*/
117
sws->buffer_unmap(sws, sq->hwbuf);
118
119
return PIPE_OK;
120
}
121
122
static void
123
begin_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
124
{
125
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
126
127
if (sq->queryResult->state == SVGA3D_QUERYSTATE_PENDING) {
128
/* The application doesn't care for the pending query result.
129
* We cannot let go of the existing buffer and just get a new one
130
* because its storage may be reused for other purposes and clobbered
131
* by the host when it determines the query result. So the only
132
* option here is to wait for the existing query's result -- not a
133
* big deal, given that no sane application would do this.
134
*/
135
uint64_t result;
136
svga_get_query_result(&svga->pipe, &sq->base, TRUE, (void*)&result);
137
assert(sq->queryResult->state != SVGA3D_QUERYSTATE_PENDING);
138
}
139
140
sq->queryResult->state = SVGA3D_QUERYSTATE_NEW;
141
sws->fence_reference(sws, &sq->fence, NULL);
142
143
SVGA_RETRY(svga, SVGA3D_BeginQuery(svga->swc, sq->svga_type));
144
}
145
146
static void
147
end_query_vgpu9(struct svga_context *svga, struct svga_query *sq)
148
{
149
/* Set to PENDING before sending EndQuery. */
150
sq->queryResult->state = SVGA3D_QUERYSTATE_PENDING;
151
152
SVGA_RETRY(svga, SVGA3D_EndQuery(svga->swc, sq->svga_type, sq->hwbuf));
153
}
154
155
static bool
156
get_query_result_vgpu9(struct svga_context *svga, struct svga_query *sq,
157
bool wait, uint64_t *result)
158
{
159
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
160
SVGA3dQueryState state;
161
162
if (!sq->fence) {
163
/* The query status won't be updated by the host unless
164
* SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
165
* a synchronous wait on the host.
166
*/
167
SVGA_RETRY(svga, SVGA3D_WaitForQuery(svga->swc, sq->svga_type,
168
sq->hwbuf));
169
svga_context_flush(svga, &sq->fence);
170
assert(sq->fence);
171
}
172
173
state = sq->queryResult->state;
174
if (state == SVGA3D_QUERYSTATE_PENDING) {
175
if (!wait)
176
return false;
177
sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
178
SVGA_FENCE_FLAG_QUERY);
179
state = sq->queryResult->state;
180
}
181
182
assert(state == SVGA3D_QUERYSTATE_SUCCEEDED ||
183
state == SVGA3D_QUERYSTATE_FAILED);
184
185
*result = (uint64_t)sq->queryResult->result32;
186
return true;
187
}
188
189
190
/**
191
* VGPU10
192
*
193
* There is one query mob allocated for each context to be shared by all
194
* query types. The mob is used to hold queries's state and result. Since
195
* each query result type is of different length, to ease the query allocation
196
* management, the mob is divided into memory blocks. Each memory block
197
* will hold queries of the same type. Multiple memory blocks can be allocated
198
* for a particular query type.
199
*
200
* Currently each memory block is of 184 bytes. We support up to 512
201
* memory blocks. The query memory size is arbitrary right now.
202
* Each occlusion query takes about 8 bytes. One memory block can accomodate
203
* 23 occlusion queries. 512 of those blocks can support up to 11K occlusion
204
* queries. That seems reasonable for now. If we think this limit is
205
* not enough, we can increase the limit or try to grow the mob in runtime.
206
* Note, SVGA device does not impose one mob per context for queries,
207
* we could allocate multiple mobs for queries; however, wddm KMD does not
208
* currently support that.
209
*
210
* Also note that the GL guest driver does not issue any of the
211
* following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
212
*/
213
#define SVGA_QUERY_MEM_BLOCK_SIZE (sizeof(SVGADXQueryResultUnion) * 2)
214
#define SVGA_QUERY_MEM_SIZE (512 * SVGA_QUERY_MEM_BLOCK_SIZE)
215
216
struct svga_qmem_alloc_entry
217
{
218
unsigned start_offset; /* start offset of the memory block */
219
unsigned block_index; /* block index of the memory block */
220
unsigned query_size; /* query size in this memory block */
221
unsigned nquery; /* number of queries allocated */
222
struct util_bitmask *alloc_mask; /* allocation mask */
223
struct svga_qmem_alloc_entry *next; /* next memory block */
224
};
225
226
227
/**
228
* Allocate a memory block from the query object memory
229
* \return NULL if out of memory, else pointer to the query memory block
230
*/
231
static struct svga_qmem_alloc_entry *
232
allocate_query_block(struct svga_context *svga)
233
{
234
int index;
235
unsigned offset;
236
struct svga_qmem_alloc_entry *alloc_entry = NULL;
237
238
/* Find the next available query block */
239
index = util_bitmask_add(svga->gb_query_alloc_mask);
240
241
if (index == UTIL_BITMASK_INVALID_INDEX)
242
return NULL;
243
244
offset = index * SVGA_QUERY_MEM_BLOCK_SIZE;
245
if (offset >= svga->gb_query_len) {
246
unsigned i;
247
248
/* Deallocate the out-of-range index */
249
util_bitmask_clear(svga->gb_query_alloc_mask, index);
250
index = -1;
251
252
/**
253
* All the memory blocks are allocated, lets see if there is
254
* any empty memory block around that can be freed up.
255
*/
256
for (i = 0; i < SVGA3D_QUERYTYPE_MAX && index == -1; i++) {
257
struct svga_qmem_alloc_entry *prev_alloc_entry = NULL;
258
259
alloc_entry = svga->gb_query_map[i];
260
while (alloc_entry && index == -1) {
261
if (alloc_entry->nquery == 0) {
262
/* This memory block is empty, it can be recycled. */
263
if (prev_alloc_entry) {
264
prev_alloc_entry->next = alloc_entry->next;
265
} else {
266
svga->gb_query_map[i] = alloc_entry->next;
267
}
268
index = alloc_entry->block_index;
269
} else {
270
prev_alloc_entry = alloc_entry;
271
alloc_entry = alloc_entry->next;
272
}
273
}
274
}
275
276
if (index == -1) {
277
debug_printf("Query memory object is full\n");
278
return NULL;
279
}
280
}
281
282
if (!alloc_entry) {
283
assert(index != -1);
284
alloc_entry = CALLOC_STRUCT(svga_qmem_alloc_entry);
285
alloc_entry->block_index = index;
286
}
287
288
return alloc_entry;
289
}
290
291
/**
292
* Allocate a slot in the specified memory block.
293
* All slots in this memory block are of the same size.
294
*
295
* \return -1 if out of memory, else index of the query slot
296
*/
297
static int
298
allocate_query_slot(struct svga_context *svga,
299
struct svga_qmem_alloc_entry *alloc)
300
{
301
int index;
302
unsigned offset;
303
304
/* Find the next available slot */
305
index = util_bitmask_add(alloc->alloc_mask);
306
307
if (index == UTIL_BITMASK_INVALID_INDEX)
308
return -1;
309
310
offset = index * alloc->query_size;
311
if (offset >= SVGA_QUERY_MEM_BLOCK_SIZE)
312
return -1;
313
314
alloc->nquery++;
315
316
return index;
317
}
318
319
/**
320
* Deallocate the specified slot in the memory block.
321
* If all slots are freed up, then deallocate the memory block
322
* as well, so it can be allocated for other query type
323
*/
324
static void
325
deallocate_query_slot(struct svga_context *svga,
326
struct svga_qmem_alloc_entry *alloc,
327
unsigned index)
328
{
329
assert(index != UTIL_BITMASK_INVALID_INDEX);
330
331
util_bitmask_clear(alloc->alloc_mask, index);
332
alloc->nquery--;
333
334
/**
335
* Don't worry about deallocating the empty memory block here.
336
* The empty memory block will be recycled when no more memory block
337
* can be allocated.
338
*/
339
}
340
341
static struct svga_qmem_alloc_entry *
342
allocate_query_block_entry(struct svga_context *svga,
343
unsigned len)
344
{
345
struct svga_qmem_alloc_entry *alloc_entry;
346
347
alloc_entry = allocate_query_block(svga);
348
if (!alloc_entry)
349
return NULL;
350
351
assert(alloc_entry->block_index != -1);
352
alloc_entry->start_offset =
353
alloc_entry->block_index * SVGA_QUERY_MEM_BLOCK_SIZE;
354
alloc_entry->nquery = 0;
355
alloc_entry->alloc_mask = util_bitmask_create();
356
alloc_entry->next = NULL;
357
alloc_entry->query_size = len;
358
359
return alloc_entry;
360
}
361
362
/**
363
* Allocate a memory slot for a query of the specified type.
364
* It will first search through the memory blocks that are allocated
365
* for the query type. If no memory slot is available, it will try
366
* to allocate another memory block within the query object memory for
367
* this query type.
368
*/
369
static int
370
allocate_query(struct svga_context *svga,
371
SVGA3dQueryType type,
372
unsigned len)
373
{
374
struct svga_qmem_alloc_entry *alloc_entry;
375
int slot_index = -1;
376
unsigned offset;
377
378
assert(type < SVGA3D_QUERYTYPE_MAX);
379
380
alloc_entry = svga->gb_query_map[type];
381
382
if (!alloc_entry) {
383
/**
384
* No query memory block has been allocated for this query type,
385
* allocate one now
386
*/
387
alloc_entry = allocate_query_block_entry(svga, len);
388
if (!alloc_entry)
389
return -1;
390
svga->gb_query_map[type] = alloc_entry;
391
}
392
393
/* Allocate a slot within the memory block allocated for this query type */
394
slot_index = allocate_query_slot(svga, alloc_entry);
395
396
if (slot_index == -1) {
397
/* This query memory block is full, allocate another one */
398
alloc_entry = allocate_query_block_entry(svga, len);
399
if (!alloc_entry)
400
return -1;
401
alloc_entry->next = svga->gb_query_map[type];
402
svga->gb_query_map[type] = alloc_entry;
403
slot_index = allocate_query_slot(svga, alloc_entry);
404
}
405
406
assert(slot_index != -1);
407
offset = slot_index * len + alloc_entry->start_offset;
408
409
return offset;
410
}
411
412
413
/**
414
* Deallocate memory slot allocated for the specified query
415
*/
416
static void
417
deallocate_query(struct svga_context *svga,
418
struct svga_query *sq)
419
{
420
struct svga_qmem_alloc_entry *alloc_entry;
421
unsigned slot_index;
422
unsigned offset = sq->offset;
423
424
alloc_entry = svga->gb_query_map[sq->svga_type];
425
426
while (alloc_entry) {
427
if (offset >= alloc_entry->start_offset &&
428
offset < alloc_entry->start_offset + SVGA_QUERY_MEM_BLOCK_SIZE) {
429
430
/* The slot belongs to this memory block, deallocate it */
431
slot_index = (offset - alloc_entry->start_offset) /
432
alloc_entry->query_size;
433
deallocate_query_slot(svga, alloc_entry, slot_index);
434
alloc_entry = NULL;
435
} else {
436
alloc_entry = alloc_entry->next;
437
}
438
}
439
}
440
441
442
/**
443
* Destroy the gb query object and all the related query structures
444
*/
445
static void
446
destroy_gb_query_obj(struct svga_context *svga)
447
{
448
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
449
unsigned i;
450
451
for (i = 0; i < SVGA3D_QUERYTYPE_MAX; i++) {
452
struct svga_qmem_alloc_entry *alloc_entry, *next;
453
alloc_entry = svga->gb_query_map[i];
454
while (alloc_entry) {
455
next = alloc_entry->next;
456
util_bitmask_destroy(alloc_entry->alloc_mask);
457
FREE(alloc_entry);
458
alloc_entry = next;
459
}
460
svga->gb_query_map[i] = NULL;
461
}
462
463
if (svga->gb_query)
464
sws->query_destroy(sws, svga->gb_query);
465
svga->gb_query = NULL;
466
467
util_bitmask_destroy(svga->gb_query_alloc_mask);
468
}
469
470
/**
471
* Define query and create the gb query object if it is not already created.
472
* There is only one gb query object per context which will be shared by
473
* queries of all types.
474
*/
475
static enum pipe_error
476
define_query_vgpu10(struct svga_context *svga,
477
struct svga_query *sq, int resultLen)
478
{
479
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
480
int qlen;
481
enum pipe_error ret = PIPE_OK;
482
483
SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
484
485
if (svga->gb_query == NULL) {
486
/* Create a gb query object */
487
svga->gb_query = sws->query_create(sws, SVGA_QUERY_MEM_SIZE);
488
if (!svga->gb_query)
489
return PIPE_ERROR_OUT_OF_MEMORY;
490
svga->gb_query_len = SVGA_QUERY_MEM_SIZE;
491
memset (svga->gb_query_map, 0, sizeof(svga->gb_query_map));
492
svga->gb_query_alloc_mask = util_bitmask_create();
493
494
/* Bind the query object to the context */
495
SVGA_RETRY(svga, svga->swc->query_bind(svga->swc, svga->gb_query,
496
SVGA_QUERY_FLAG_SET));
497
}
498
499
sq->gb_query = svga->gb_query;
500
501
/* Make sure query length is in multiples of 8 bytes */
502
qlen = align(resultLen + sizeof(SVGA3dQueryState), 8);
503
504
/* Find a slot for this query in the gb object */
505
sq->offset = allocate_query(svga, sq->svga_type, qlen);
506
if (sq->offset == -1)
507
return PIPE_ERROR_OUT_OF_MEMORY;
508
509
assert((sq->offset & 7) == 0);
510
511
SVGA_DBG(DEBUG_QUERY, " query type=%d qid=0x%x offset=%d\n",
512
sq->svga_type, sq->id, sq->offset);
513
514
/**
515
* Send SVGA3D commands to define the query
516
*/
517
SVGA_RETRY_OOM(svga, ret, SVGA3D_vgpu10_DefineQuery(svga->swc, sq->id,
518
sq->svga_type,
519
sq->flags));
520
if (ret != PIPE_OK)
521
return PIPE_ERROR_OUT_OF_MEMORY;
522
523
SVGA_RETRY(svga, SVGA3D_vgpu10_BindQuery(svga->swc, sq->gb_query, sq->id));
524
SVGA_RETRY(svga, SVGA3D_vgpu10_SetQueryOffset(svga->swc, sq->id,
525
sq->offset));
526
527
return PIPE_OK;
528
}
529
530
static void
531
destroy_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
532
{
533
SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyQuery(svga->swc, sq->id));
534
535
/* Deallocate the memory slot allocated for this query */
536
deallocate_query(svga, sq);
537
}
538
539
540
/**
541
* Rebind queryies to the context.
542
*/
543
static void
544
rebind_vgpu10_query(struct svga_context *svga)
545
{
546
SVGA_RETRY(svga, svga->swc->query_bind(svga->swc, svga->gb_query,
547
SVGA_QUERY_FLAG_REF));
548
svga->rebind.flags.query = FALSE;
549
}
550
551
552
static enum pipe_error
553
begin_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
554
{
555
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
556
int status = 0;
557
558
sws->fence_reference(sws, &sq->fence, NULL);
559
560
/* Initialize the query state to NEW */
561
status = sws->query_init(sws, sq->gb_query, sq->offset, SVGA3D_QUERYSTATE_NEW);
562
if (status)
563
return PIPE_ERROR;
564
565
if (svga->rebind.flags.query) {
566
rebind_vgpu10_query(svga);
567
}
568
569
/* Send the BeginQuery command to the device */
570
SVGA_RETRY(svga, SVGA3D_vgpu10_BeginQuery(svga->swc, sq->id));
571
return PIPE_OK;
572
}
573
574
static void
575
end_query_vgpu10(struct svga_context *svga, struct svga_query *sq)
576
{
577
if (svga->rebind.flags.query) {
578
rebind_vgpu10_query(svga);
579
}
580
581
SVGA_RETRY(svga, SVGA3D_vgpu10_EndQuery(svga->swc, sq->id));
582
}
583
584
static bool
585
get_query_result_vgpu10(struct svga_context *svga, struct svga_query *sq,
586
bool wait, void *result, int resultLen)
587
{
588
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
589
SVGA3dQueryState queryState;
590
591
if (svga->rebind.flags.query) {
592
rebind_vgpu10_query(svga);
593
}
594
595
sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
596
597
if (queryState != SVGA3D_QUERYSTATE_SUCCEEDED && !sq->fence) {
598
/* We don't have the query result yet, and the query hasn't been
599
* submitted. We need to submit it now since the GL spec says
600
* "Querying the state for a given occlusion query forces that
601
* occlusion query to complete within a finite amount of time."
602
*/
603
svga_context_flush(svga, &sq->fence);
604
}
605
606
if (queryState == SVGA3D_QUERYSTATE_PENDING ||
607
queryState == SVGA3D_QUERYSTATE_NEW) {
608
if (!wait)
609
return false;
610
sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
611
SVGA_FENCE_FLAG_QUERY);
612
sws->query_get_result(sws, sq->gb_query, sq->offset, &queryState, result, resultLen);
613
}
614
615
assert(queryState == SVGA3D_QUERYSTATE_SUCCEEDED ||
616
queryState == SVGA3D_QUERYSTATE_FAILED);
617
618
return true;
619
}
620
621
static struct pipe_query *
622
svga_create_query(struct pipe_context *pipe,
623
unsigned query_type,
624
unsigned index)
625
{
626
struct svga_context *svga = svga_context(pipe);
627
struct svga_query *sq;
628
enum pipe_error ret;
629
630
assert(query_type < SVGA_QUERY_MAX);
631
632
sq = CALLOC_STRUCT(svga_query);
633
if (!sq)
634
goto fail;
635
636
/* Allocate an integer ID for the query */
637
sq->id = util_bitmask_add(svga->query_id_bm);
638
if (sq->id == UTIL_BITMASK_INVALID_INDEX)
639
goto fail;
640
641
SVGA_DBG(DEBUG_QUERY, "%s type=%d sq=0x%x id=%d\n", __FUNCTION__,
642
query_type, sq, sq->id);
643
644
switch (query_type) {
645
case PIPE_QUERY_OCCLUSION_COUNTER:
646
sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
647
if (svga_have_vgpu10(svga)) {
648
ret = define_query_vgpu10(svga, sq,
649
sizeof(SVGADXOcclusionQueryResult));
650
if (ret != PIPE_OK)
651
goto fail;
652
653
/**
654
* In OpenGL, occlusion counter query can be used in conditional
655
* rendering; however, in DX10, only OCCLUSION_PREDICATE query can
656
* be used for predication. Hence, we need to create an occlusion
657
* predicate query along with the occlusion counter query. So when
658
* the occlusion counter query is used for predication, the associated
659
* query of occlusion predicate type will be used
660
* in the SetPredication command.
661
*/
662
sq->predicate = svga_create_query(pipe, PIPE_QUERY_OCCLUSION_PREDICATE, index);
663
664
} else {
665
ret = define_query_vgpu9(svga, sq);
666
if (ret != PIPE_OK)
667
goto fail;
668
}
669
break;
670
case PIPE_QUERY_OCCLUSION_PREDICATE:
671
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
672
if (svga_have_vgpu10(svga)) {
673
sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE;
674
ret = define_query_vgpu10(svga, sq,
675
sizeof(SVGADXOcclusionPredicateQueryResult));
676
if (ret != PIPE_OK)
677
goto fail;
678
} else {
679
sq->svga_type = SVGA3D_QUERYTYPE_OCCLUSION;
680
ret = define_query_vgpu9(svga, sq);
681
if (ret != PIPE_OK)
682
goto fail;
683
}
684
break;
685
case PIPE_QUERY_PRIMITIVES_GENERATED:
686
case PIPE_QUERY_PRIMITIVES_EMITTED:
687
case PIPE_QUERY_SO_STATISTICS:
688
assert(svga_have_vgpu10(svga));
689
690
/* Until the device supports the new query type for multiple streams,
691
* we will use the single stream query type for stream 0.
692
*/
693
if (svga_have_sm5(svga) && index > 0) {
694
assert(index < 4);
695
696
sq->svga_type = SVGA3D_QUERYTYPE_SOSTATS_STREAM0 + index;
697
}
698
else {
699
assert(index == 0);
700
sq->svga_type = SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS;
701
}
702
ret = define_query_vgpu10(svga, sq,
703
sizeof(SVGADXStreamOutStatisticsQueryResult));
704
if (ret != PIPE_OK)
705
goto fail;
706
break;
707
case PIPE_QUERY_TIMESTAMP:
708
assert(svga_have_vgpu10(svga));
709
sq->svga_type = SVGA3D_QUERYTYPE_TIMESTAMP;
710
ret = define_query_vgpu10(svga, sq,
711
sizeof(SVGADXTimestampQueryResult));
712
if (ret != PIPE_OK)
713
goto fail;
714
break;
715
case SVGA_QUERY_NUM_DRAW_CALLS:
716
case SVGA_QUERY_NUM_FALLBACKS:
717
case SVGA_QUERY_NUM_FLUSHES:
718
case SVGA_QUERY_NUM_VALIDATIONS:
719
case SVGA_QUERY_NUM_BUFFERS_MAPPED:
720
case SVGA_QUERY_NUM_TEXTURES_MAPPED:
721
case SVGA_QUERY_NUM_BYTES_UPLOADED:
722
case SVGA_QUERY_NUM_COMMAND_BUFFERS:
723
case SVGA_QUERY_COMMAND_BUFFER_SIZE:
724
case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
725
case SVGA_QUERY_MEMORY_USED:
726
case SVGA_QUERY_NUM_SHADERS:
727
case SVGA_QUERY_NUM_RESOURCES:
728
case SVGA_QUERY_NUM_STATE_OBJECTS:
729
case SVGA_QUERY_NUM_SURFACE_VIEWS:
730
case SVGA_QUERY_NUM_GENERATE_MIPMAP:
731
case SVGA_QUERY_NUM_READBACKS:
732
case SVGA_QUERY_NUM_RESOURCE_UPDATES:
733
case SVGA_QUERY_NUM_BUFFER_UPLOADS:
734
case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
735
case SVGA_QUERY_NUM_CONST_UPDATES:
736
case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
737
case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
738
case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
739
case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
740
case SVGA_QUERY_SHADER_MEM_USED:
741
break;
742
case SVGA_QUERY_FLUSH_TIME:
743
case SVGA_QUERY_MAP_BUFFER_TIME:
744
/* These queries need os_time_get() */
745
svga->hud.uses_time = TRUE;
746
break;
747
748
default:
749
assert(!"unexpected query type in svga_create_query()");
750
}
751
752
sq->type = query_type;
753
754
return &sq->base;
755
756
fail:
757
FREE(sq);
758
return NULL;
759
}
760
761
static void
762
svga_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
763
{
764
struct svga_context *svga = svga_context(pipe);
765
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
766
struct svga_query *sq;
767
768
if (!q) {
769
destroy_gb_query_obj(svga);
770
return;
771
}
772
773
sq = svga_query(q);
774
775
SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
776
sq, sq->id);
777
778
switch (sq->type) {
779
case PIPE_QUERY_OCCLUSION_COUNTER:
780
case PIPE_QUERY_OCCLUSION_PREDICATE:
781
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
782
if (svga_have_vgpu10(svga)) {
783
/* make sure to also destroy any associated predicate query */
784
if (sq->predicate)
785
svga_destroy_query(pipe, sq->predicate);
786
destroy_query_vgpu10(svga, sq);
787
} else {
788
sws->buffer_destroy(sws, sq->hwbuf);
789
}
790
sws->fence_reference(sws, &sq->fence, NULL);
791
break;
792
case PIPE_QUERY_PRIMITIVES_GENERATED:
793
case PIPE_QUERY_PRIMITIVES_EMITTED:
794
case PIPE_QUERY_SO_STATISTICS:
795
case PIPE_QUERY_TIMESTAMP:
796
assert(svga_have_vgpu10(svga));
797
destroy_query_vgpu10(svga, sq);
798
sws->fence_reference(sws, &sq->fence, NULL);
799
break;
800
case SVGA_QUERY_NUM_DRAW_CALLS:
801
case SVGA_QUERY_NUM_FALLBACKS:
802
case SVGA_QUERY_NUM_FLUSHES:
803
case SVGA_QUERY_NUM_VALIDATIONS:
804
case SVGA_QUERY_MAP_BUFFER_TIME:
805
case SVGA_QUERY_NUM_BUFFERS_MAPPED:
806
case SVGA_QUERY_NUM_TEXTURES_MAPPED:
807
case SVGA_QUERY_NUM_BYTES_UPLOADED:
808
case SVGA_QUERY_NUM_COMMAND_BUFFERS:
809
case SVGA_QUERY_COMMAND_BUFFER_SIZE:
810
case SVGA_QUERY_FLUSH_TIME:
811
case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
812
case SVGA_QUERY_MEMORY_USED:
813
case SVGA_QUERY_NUM_SHADERS:
814
case SVGA_QUERY_NUM_RESOURCES:
815
case SVGA_QUERY_NUM_STATE_OBJECTS:
816
case SVGA_QUERY_NUM_SURFACE_VIEWS:
817
case SVGA_QUERY_NUM_GENERATE_MIPMAP:
818
case SVGA_QUERY_NUM_READBACKS:
819
case SVGA_QUERY_NUM_RESOURCE_UPDATES:
820
case SVGA_QUERY_NUM_BUFFER_UPLOADS:
821
case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
822
case SVGA_QUERY_NUM_CONST_UPDATES:
823
case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
824
case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
825
case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
826
case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
827
case SVGA_QUERY_SHADER_MEM_USED:
828
/* nothing */
829
break;
830
default:
831
assert(!"svga: unexpected query type in svga_destroy_query()");
832
}
833
834
/* Free the query id */
835
util_bitmask_clear(svga->query_id_bm, sq->id);
836
837
FREE(sq);
838
}
839
840
841
static bool
842
svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
843
{
844
struct svga_context *svga = svga_context(pipe);
845
struct svga_query *sq = svga_query(q);
846
enum pipe_error ret = PIPE_OK;
847
848
assert(sq);
849
assert(sq->type < SVGA_QUERY_MAX);
850
851
/* Need to flush out buffered drawing commands so that they don't
852
* get counted in the query results.
853
*/
854
svga_hwtnl_flush_retry(svga);
855
856
switch (sq->type) {
857
case PIPE_QUERY_OCCLUSION_COUNTER:
858
case PIPE_QUERY_OCCLUSION_PREDICATE:
859
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
860
if (svga_have_vgpu10(svga)) {
861
ret = begin_query_vgpu10(svga, sq);
862
/* also need to start the associated occlusion predicate query */
863
if (sq->predicate) {
864
enum pipe_error status;
865
status = begin_query_vgpu10(svga, svga_query(sq->predicate));
866
assert(status == PIPE_OK);
867
(void) status;
868
}
869
} else {
870
begin_query_vgpu9(svga, sq);
871
}
872
assert(ret == PIPE_OK);
873
(void) ret;
874
break;
875
case PIPE_QUERY_PRIMITIVES_GENERATED:
876
case PIPE_QUERY_PRIMITIVES_EMITTED:
877
case PIPE_QUERY_SO_STATISTICS:
878
case PIPE_QUERY_TIMESTAMP:
879
assert(svga_have_vgpu10(svga));
880
ret = begin_query_vgpu10(svga, sq);
881
assert(ret == PIPE_OK);
882
break;
883
case SVGA_QUERY_NUM_DRAW_CALLS:
884
sq->begin_count = svga->hud.num_draw_calls;
885
break;
886
case SVGA_QUERY_NUM_FALLBACKS:
887
sq->begin_count = svga->hud.num_fallbacks;
888
break;
889
case SVGA_QUERY_NUM_FLUSHES:
890
sq->begin_count = svga->hud.num_flushes;
891
break;
892
case SVGA_QUERY_NUM_VALIDATIONS:
893
sq->begin_count = svga->hud.num_validations;
894
break;
895
case SVGA_QUERY_MAP_BUFFER_TIME:
896
sq->begin_count = svga->hud.map_buffer_time;
897
break;
898
case SVGA_QUERY_NUM_BUFFERS_MAPPED:
899
sq->begin_count = svga->hud.num_buffers_mapped;
900
break;
901
case SVGA_QUERY_NUM_TEXTURES_MAPPED:
902
sq->begin_count = svga->hud.num_textures_mapped;
903
break;
904
case SVGA_QUERY_NUM_BYTES_UPLOADED:
905
sq->begin_count = svga->hud.num_bytes_uploaded;
906
break;
907
case SVGA_QUERY_NUM_COMMAND_BUFFERS:
908
sq->begin_count = svga->swc->num_command_buffers;
909
break;
910
case SVGA_QUERY_COMMAND_BUFFER_SIZE:
911
sq->begin_count = svga->hud.command_buffer_size;
912
break;
913
case SVGA_QUERY_FLUSH_TIME:
914
sq->begin_count = svga->hud.flush_time;
915
break;
916
case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
917
sq->begin_count = svga->hud.surface_write_flushes;
918
break;
919
case SVGA_QUERY_NUM_READBACKS:
920
sq->begin_count = svga->hud.num_readbacks;
921
break;
922
case SVGA_QUERY_NUM_RESOURCE_UPDATES:
923
sq->begin_count = svga->hud.num_resource_updates;
924
break;
925
case SVGA_QUERY_NUM_BUFFER_UPLOADS:
926
sq->begin_count = svga->hud.num_buffer_uploads;
927
break;
928
case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
929
sq->begin_count = svga->hud.num_const_buf_updates;
930
break;
931
case SVGA_QUERY_NUM_CONST_UPDATES:
932
sq->begin_count = svga->hud.num_const_updates;
933
break;
934
case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
935
sq->begin_count = svga->swc->num_shader_reloc;
936
break;
937
case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
938
sq->begin_count = svga->swc->num_surf_reloc;
939
break;
940
case SVGA_QUERY_MEMORY_USED:
941
case SVGA_QUERY_NUM_SHADERS:
942
case SVGA_QUERY_NUM_RESOURCES:
943
case SVGA_QUERY_NUM_STATE_OBJECTS:
944
case SVGA_QUERY_NUM_SURFACE_VIEWS:
945
case SVGA_QUERY_NUM_GENERATE_MIPMAP:
946
case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
947
case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
948
case SVGA_QUERY_SHADER_MEM_USED:
949
/* nothing */
950
break;
951
default:
952
assert(!"unexpected query type in svga_begin_query()");
953
}
954
955
SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d type=%d svga_type=%d\n",
956
__FUNCTION__, sq, sq->id, sq->type, sq->svga_type);
957
958
sq->active = TRUE;
959
960
return true;
961
}
962
963
964
static bool
965
svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
966
{
967
struct svga_context *svga = svga_context(pipe);
968
struct svga_query *sq = svga_query(q);
969
970
assert(sq);
971
assert(sq->type < SVGA_QUERY_MAX);
972
973
SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x type=%d\n",
974
__FUNCTION__, sq, sq->type);
975
976
if (sq->type == PIPE_QUERY_TIMESTAMP && !sq->active)
977
svga_begin_query(pipe, q);
978
979
SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d type=%d svga_type=%d\n",
980
__FUNCTION__, sq, sq->id, sq->type, sq->svga_type);
981
982
svga_hwtnl_flush_retry(svga);
983
984
assert(sq->active);
985
986
switch (sq->type) {
987
case PIPE_QUERY_OCCLUSION_COUNTER:
988
case PIPE_QUERY_OCCLUSION_PREDICATE:
989
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
990
if (svga_have_vgpu10(svga)) {
991
end_query_vgpu10(svga, sq);
992
/* also need to end the associated occlusion predicate query */
993
if (sq->predicate) {
994
end_query_vgpu10(svga, svga_query(sq->predicate));
995
}
996
} else {
997
end_query_vgpu9(svga, sq);
998
}
999
break;
1000
case PIPE_QUERY_PRIMITIVES_GENERATED:
1001
case PIPE_QUERY_PRIMITIVES_EMITTED:
1002
case PIPE_QUERY_SO_STATISTICS:
1003
case PIPE_QUERY_TIMESTAMP:
1004
assert(svga_have_vgpu10(svga));
1005
end_query_vgpu10(svga, sq);
1006
break;
1007
case SVGA_QUERY_NUM_DRAW_CALLS:
1008
sq->end_count = svga->hud.num_draw_calls;
1009
break;
1010
case SVGA_QUERY_NUM_FALLBACKS:
1011
sq->end_count = svga->hud.num_fallbacks;
1012
break;
1013
case SVGA_QUERY_NUM_FLUSHES:
1014
sq->end_count = svga->hud.num_flushes;
1015
break;
1016
case SVGA_QUERY_NUM_VALIDATIONS:
1017
sq->end_count = svga->hud.num_validations;
1018
break;
1019
case SVGA_QUERY_MAP_BUFFER_TIME:
1020
sq->end_count = svga->hud.map_buffer_time;
1021
break;
1022
case SVGA_QUERY_NUM_BUFFERS_MAPPED:
1023
sq->end_count = svga->hud.num_buffers_mapped;
1024
break;
1025
case SVGA_QUERY_NUM_TEXTURES_MAPPED:
1026
sq->end_count = svga->hud.num_textures_mapped;
1027
break;
1028
case SVGA_QUERY_NUM_BYTES_UPLOADED:
1029
sq->end_count = svga->hud.num_bytes_uploaded;
1030
break;
1031
case SVGA_QUERY_NUM_COMMAND_BUFFERS:
1032
sq->end_count = svga->swc->num_command_buffers;
1033
break;
1034
case SVGA_QUERY_COMMAND_BUFFER_SIZE:
1035
sq->end_count = svga->hud.command_buffer_size;
1036
break;
1037
case SVGA_QUERY_FLUSH_TIME:
1038
sq->end_count = svga->hud.flush_time;
1039
break;
1040
case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
1041
sq->end_count = svga->hud.surface_write_flushes;
1042
break;
1043
case SVGA_QUERY_NUM_READBACKS:
1044
sq->end_count = svga->hud.num_readbacks;
1045
break;
1046
case SVGA_QUERY_NUM_RESOURCE_UPDATES:
1047
sq->end_count = svga->hud.num_resource_updates;
1048
break;
1049
case SVGA_QUERY_NUM_BUFFER_UPLOADS:
1050
sq->end_count = svga->hud.num_buffer_uploads;
1051
break;
1052
case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
1053
sq->end_count = svga->hud.num_const_buf_updates;
1054
break;
1055
case SVGA_QUERY_NUM_CONST_UPDATES:
1056
sq->end_count = svga->hud.num_const_updates;
1057
break;
1058
case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
1059
sq->end_count = svga->swc->num_shader_reloc;
1060
break;
1061
case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
1062
sq->end_count = svga->swc->num_surf_reloc;
1063
break;
1064
case SVGA_QUERY_MEMORY_USED:
1065
case SVGA_QUERY_NUM_SHADERS:
1066
case SVGA_QUERY_NUM_RESOURCES:
1067
case SVGA_QUERY_NUM_STATE_OBJECTS:
1068
case SVGA_QUERY_NUM_SURFACE_VIEWS:
1069
case SVGA_QUERY_NUM_GENERATE_MIPMAP:
1070
case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
1071
case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
1072
case SVGA_QUERY_SHADER_MEM_USED:
1073
/* nothing */
1074
break;
1075
default:
1076
assert(!"unexpected query type in svga_end_query()");
1077
}
1078
sq->active = FALSE;
1079
return true;
1080
}
1081
1082
1083
static bool
1084
svga_get_query_result(struct pipe_context *pipe,
1085
struct pipe_query *q,
1086
bool wait,
1087
union pipe_query_result *vresult)
1088
{
1089
struct svga_screen *svgascreen = svga_screen(pipe->screen);
1090
struct svga_context *svga = svga_context(pipe);
1091
struct svga_query *sq = svga_query(q);
1092
uint64_t *result = (uint64_t *)vresult;
1093
bool ret = true;
1094
1095
assert(sq);
1096
1097
SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d wait: %d\n",
1098
__FUNCTION__, sq, sq->id, wait);
1099
1100
switch (sq->type) {
1101
case PIPE_QUERY_OCCLUSION_COUNTER:
1102
if (svga_have_vgpu10(svga)) {
1103
SVGADXOcclusionQueryResult occResult;
1104
ret = get_query_result_vgpu10(svga, sq, wait,
1105
(void *)&occResult, sizeof(occResult));
1106
*result = (uint64_t)occResult.samplesRendered;
1107
} else {
1108
ret = get_query_result_vgpu9(svga, sq, wait, result);
1109
}
1110
break;
1111
case PIPE_QUERY_OCCLUSION_PREDICATE:
1112
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
1113
if (svga_have_vgpu10(svga)) {
1114
SVGADXOcclusionPredicateQueryResult occResult;
1115
ret = get_query_result_vgpu10(svga, sq, wait,
1116
(void *)&occResult, sizeof(occResult));
1117
vresult->b = occResult.anySamplesRendered != 0;
1118
} else {
1119
uint64_t count = 0;
1120
ret = get_query_result_vgpu9(svga, sq, wait, &count);
1121
vresult->b = count != 0;
1122
}
1123
break;
1124
}
1125
case PIPE_QUERY_SO_STATISTICS: {
1126
SVGADXStreamOutStatisticsQueryResult sResult;
1127
struct pipe_query_data_so_statistics *pResult =
1128
(struct pipe_query_data_so_statistics *)vresult;
1129
1130
assert(svga_have_vgpu10(svga));
1131
ret = get_query_result_vgpu10(svga, sq, wait,
1132
(void *)&sResult, sizeof(sResult));
1133
pResult->num_primitives_written = sResult.numPrimitivesWritten;
1134
pResult->primitives_storage_needed = sResult.numPrimitivesRequired;
1135
break;
1136
}
1137
case PIPE_QUERY_TIMESTAMP: {
1138
SVGADXTimestampQueryResult sResult;
1139
1140
assert(svga_have_vgpu10(svga));
1141
ret = get_query_result_vgpu10(svga, sq, wait,
1142
(void *)&sResult, sizeof(sResult));
1143
*result = (uint64_t)sResult.timestamp;
1144
break;
1145
}
1146
case PIPE_QUERY_PRIMITIVES_GENERATED: {
1147
SVGADXStreamOutStatisticsQueryResult sResult;
1148
1149
assert(svga_have_vgpu10(svga));
1150
ret = get_query_result_vgpu10(svga, sq, wait,
1151
(void *)&sResult, sizeof sResult);
1152
*result = (uint64_t)sResult.numPrimitivesRequired;
1153
break;
1154
}
1155
case PIPE_QUERY_PRIMITIVES_EMITTED: {
1156
SVGADXStreamOutStatisticsQueryResult sResult;
1157
1158
assert(svga_have_vgpu10(svga));
1159
ret = get_query_result_vgpu10(svga, sq, wait,
1160
(void *)&sResult, sizeof sResult);
1161
*result = (uint64_t)sResult.numPrimitivesWritten;
1162
break;
1163
}
1164
/* These are per-frame counters */
1165
case SVGA_QUERY_NUM_DRAW_CALLS:
1166
case SVGA_QUERY_NUM_FALLBACKS:
1167
case SVGA_QUERY_NUM_FLUSHES:
1168
case SVGA_QUERY_NUM_VALIDATIONS:
1169
case SVGA_QUERY_MAP_BUFFER_TIME:
1170
case SVGA_QUERY_NUM_BUFFERS_MAPPED:
1171
case SVGA_QUERY_NUM_TEXTURES_MAPPED:
1172
case SVGA_QUERY_NUM_BYTES_UPLOADED:
1173
case SVGA_QUERY_NUM_COMMAND_BUFFERS:
1174
case SVGA_QUERY_COMMAND_BUFFER_SIZE:
1175
case SVGA_QUERY_FLUSH_TIME:
1176
case SVGA_QUERY_SURFACE_WRITE_FLUSHES:
1177
case SVGA_QUERY_NUM_READBACKS:
1178
case SVGA_QUERY_NUM_RESOURCE_UPDATES:
1179
case SVGA_QUERY_NUM_BUFFER_UPLOADS:
1180
case SVGA_QUERY_NUM_CONST_BUF_UPDATES:
1181
case SVGA_QUERY_NUM_CONST_UPDATES:
1182
case SVGA_QUERY_NUM_SHADER_RELOCATIONS:
1183
case SVGA_QUERY_NUM_SURFACE_RELOCATIONS:
1184
vresult->u64 = sq->end_count - sq->begin_count;
1185
break;
1186
/* These are running total counters */
1187
case SVGA_QUERY_MEMORY_USED:
1188
vresult->u64 = svgascreen->hud.total_resource_bytes;
1189
break;
1190
case SVGA_QUERY_NUM_SHADERS:
1191
vresult->u64 = svga->hud.num_shaders;
1192
break;
1193
case SVGA_QUERY_NUM_RESOURCES:
1194
vresult->u64 = svgascreen->hud.num_resources;
1195
break;
1196
case SVGA_QUERY_NUM_STATE_OBJECTS:
1197
vresult->u64 = (svga->hud.num_blend_objects +
1198
svga->hud.num_depthstencil_objects +
1199
svga->hud.num_rasterizer_objects +
1200
svga->hud.num_sampler_objects +
1201
svga->hud.num_samplerview_objects +
1202
svga->hud.num_vertexelement_objects);
1203
break;
1204
case SVGA_QUERY_NUM_SURFACE_VIEWS:
1205
vresult->u64 = svga->hud.num_surface_views;
1206
break;
1207
case SVGA_QUERY_NUM_GENERATE_MIPMAP:
1208
vresult->u64 = svga->hud.num_generate_mipmap;
1209
break;
1210
case SVGA_QUERY_NUM_FAILED_ALLOCATIONS:
1211
vresult->u64 = svgascreen->hud.num_failed_allocations;
1212
break;
1213
case SVGA_QUERY_NUM_COMMANDS_PER_DRAW:
1214
vresult->f = (float) svga->swc->num_commands
1215
/ (float) svga->swc->num_draw_commands;
1216
break;
1217
case SVGA_QUERY_SHADER_MEM_USED:
1218
vresult->u64 = svga->hud.shader_mem_used;
1219
break;
1220
default:
1221
assert(!"unexpected query type in svga_get_query_result");
1222
}
1223
1224
SVGA_DBG(DEBUG_QUERY, "%s result %d\n", __FUNCTION__, *((uint64_t *)vresult));
1225
1226
return ret;
1227
}
1228
1229
static void
1230
svga_render_condition(struct pipe_context *pipe, struct pipe_query *q,
1231
bool condition, enum pipe_render_cond_flag mode)
1232
{
1233
struct svga_context *svga = svga_context(pipe);
1234
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
1235
struct svga_query *sq = svga_query(q);
1236
SVGA3dQueryId queryId;
1237
1238
SVGA_DBG(DEBUG_QUERY, "%s\n", __FUNCTION__);
1239
1240
assert(svga_have_vgpu10(svga));
1241
if (sq == NULL) {
1242
queryId = SVGA3D_INVALID_ID;
1243
}
1244
else {
1245
assert(sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSION ||
1246
sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE);
1247
1248
if (sq->svga_type == SVGA3D_QUERYTYPE_OCCLUSION) {
1249
assert(sq->predicate);
1250
/**
1251
* For conditional rendering, make sure to use the associated
1252
* predicate query.
1253
*/
1254
sq = svga_query(sq->predicate);
1255
}
1256
queryId = sq->id;
1257
1258
if ((mode == PIPE_RENDER_COND_WAIT ||
1259
mode == PIPE_RENDER_COND_BY_REGION_WAIT) && sq->fence) {
1260
sws->fence_finish(sws, sq->fence, PIPE_TIMEOUT_INFINITE,
1261
SVGA_FENCE_FLAG_QUERY);
1262
}
1263
}
1264
/*
1265
* if the kernel module doesn't support the predication command,
1266
* we'll just render unconditionally.
1267
* This is probably acceptable for the typical case of occlusion culling.
1268
*/
1269
if (sws->have_set_predication_cmd) {
1270
SVGA_RETRY(svga, SVGA3D_vgpu10_SetPredication(svga->swc, queryId,
1271
(uint32) condition));
1272
svga->pred.query_id = queryId;
1273
svga->pred.cond = condition;
1274
}
1275
1276
svga->render_condition = (sq != NULL);
1277
}
1278
1279
1280
/*
1281
* This function is a workaround because we lack the ability to query
1282
* renderer's time synchronously.
1283
*/
1284
static uint64_t
1285
svga_get_timestamp(struct pipe_context *pipe)
1286
{
1287
struct pipe_query *q = svga_create_query(pipe, PIPE_QUERY_TIMESTAMP, 0);
1288
union pipe_query_result result;
1289
1290
svga_begin_query(pipe, q);
1291
svga_end_query(pipe,q);
1292
svga_get_query_result(pipe, q, TRUE, &result);
1293
svga_destroy_query(pipe, q);
1294
1295
return result.u64;
1296
}
1297
1298
1299
static void
1300
svga_set_active_query_state(struct pipe_context *pipe, bool enable)
1301
{
1302
}
1303
1304
1305
/**
1306
* \brief Toggle conditional rendering if already enabled
1307
*
1308
* \param svga[in] The svga context
1309
* \param render_condition_enabled[in] Whether to ignore requests to turn
1310
* conditional rendering off
1311
* \param on[in] Whether to turn conditional rendering on or off
1312
*/
1313
void
1314
svga_toggle_render_condition(struct svga_context *svga,
1315
boolean render_condition_enabled,
1316
boolean on)
1317
{
1318
SVGA3dQueryId query_id;
1319
1320
if (render_condition_enabled ||
1321
svga->pred.query_id == SVGA3D_INVALID_ID) {
1322
return;
1323
}
1324
1325
/*
1326
* If we get here, it means that the system supports
1327
* conditional rendering since svga->pred.query_id has already been
1328
* modified for this context and thus support has already been
1329
* verified.
1330
*/
1331
query_id = on ? svga->pred.query_id : SVGA3D_INVALID_ID;
1332
1333
SVGA_RETRY(svga, SVGA3D_vgpu10_SetPredication(svga->swc, query_id,
1334
(uint32) svga->pred.cond));
1335
}
1336
1337
1338
void
1339
svga_init_query_functions(struct svga_context *svga)
1340
{
1341
svga->pipe.create_query = svga_create_query;
1342
svga->pipe.destroy_query = svga_destroy_query;
1343
svga->pipe.begin_query = svga_begin_query;
1344
svga->pipe.end_query = svga_end_query;
1345
svga->pipe.get_query_result = svga_get_query_result;
1346
svga->pipe.set_active_query_state = svga_set_active_query_state;
1347
svga->pipe.render_condition = svga_render_condition;
1348
svga->pipe.get_timestamp = svga_get_timestamp;
1349
}
1350
1351