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 *
svga_query(struct pipe_query * q)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
define_query_vgpu9(struct svga_context * svga,struct svga_query * sq)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
begin_query_vgpu9(struct svga_context * svga,struct svga_query * sq)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
end_query_vgpu9(struct svga_context * svga,struct svga_query * sq)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
get_query_result_vgpu9(struct svga_context * svga,struct svga_query * sq,bool wait,uint64_t * result)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 *
allocate_query_block(struct svga_context * svga)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
allocate_query_slot(struct svga_context * svga,struct svga_qmem_alloc_entry * alloc)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
deallocate_query_slot(struct svga_context * svga,struct svga_qmem_alloc_entry * alloc,unsigned index)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 *
allocate_query_block_entry(struct svga_context * svga,unsigned len)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
allocate_query(struct svga_context * svga,SVGA3dQueryType type,unsigned len)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
deallocate_query(struct svga_context * svga,struct svga_query * sq)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
destroy_gb_query_obj(struct svga_context * svga)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
define_query_vgpu10(struct svga_context * svga,struct svga_query * sq,int resultLen)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
destroy_query_vgpu10(struct svga_context * svga,struct svga_query * sq)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
rebind_vgpu10_query(struct svga_context * svga)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
begin_query_vgpu10(struct svga_context * svga,struct svga_query * sq)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
end_query_vgpu10(struct svga_context * svga,struct svga_query * sq)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
get_query_result_vgpu10(struct svga_context * svga,struct svga_query * sq,bool wait,void * result,int resultLen)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 *
svga_create_query(struct pipe_context * pipe,unsigned query_type,unsigned index)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
svga_destroy_query(struct pipe_context * pipe,struct pipe_query * q)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
svga_begin_query(struct pipe_context * pipe,struct pipe_query * q)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
svga_end_query(struct pipe_context * pipe,struct pipe_query * q)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
svga_get_query_result(struct pipe_context * pipe,struct pipe_query * q,bool wait,union pipe_query_result * vresult)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
svga_render_condition(struct pipe_context * pipe,struct pipe_query * q,bool condition,enum pipe_render_cond_flag mode)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 synchornously.
1283 */
1284 static uint64_t
svga_get_timestamp(struct pipe_context * pipe)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
svga_set_active_query_state(struct pipe_context * pipe,bool enable)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
svga_toggle_render_condition(struct svga_context * svga,boolean render_condition_enabled,boolean on)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
svga_init_query_functions(struct svga_context * svga)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