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