1 /**********************************************************
2 * Copyright 2008-2015 VMware, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
24 **********************************************************/
26 #include "pipe/p_state.h"
27 #include "pipe/p_context.h"
29 #include "util/u_bitmask.h"
30 #include "util/u_memory.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"
40 /* Fixme: want a public base class for all pipe structs, even if there
48 struct pipe_query base
;
49 unsigned type
; /**< PIPE_QUERY_x or SVGA_QUERY_x */
50 SVGA3dQueryType svga_type
; /**< SVGA3D_QUERYTYPE_x or unused */
52 unsigned id
; /** Per-context query identifier */
54 struct pipe_fence_handle
*fence
;
56 /** For PIPE_QUERY_OCCLUSION_COUNTER / SVGA3D_QUERYTYPE_OCCLUSION */
59 struct svga_winsys_buffer
*hwbuf
;
60 volatile SVGA3dQueryResult
*queryResult
;
63 struct svga_winsys_gb_query
*gb_query
;
64 SVGA3dDXQueryFlags flags
;
65 unsigned offset
; /**< offset to the gb_query memory */
66 struct pipe_query
*predicate
; /** The associated query that can be used for predicate */
68 /** For non-GPU SVGA_QUERY_x queries */
69 uint64_t begin_count
, end_count
;
74 static inline struct svga_query
*
75 svga_query( struct pipe_query
*q
)
77 return (struct svga_query
*)q
;
82 svga_get_query_result(struct pipe_context
*pipe
,
85 union pipe_query_result
*result
);
87 static enum pipe_error
88 define_query_vgpu9(struct svga_context
*svga
,
89 struct svga_query
*sq
)
91 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
93 sq
->hwbuf
= svga_winsys_buffer_create(svga
, 1,
94 SVGA_BUFFER_USAGE_PINNED
,
95 sizeof *sq
->queryResult
);
97 return PIPE_ERROR_OUT_OF_MEMORY
;
99 sq
->queryResult
= (SVGA3dQueryResult
*)
100 sws
->buffer_map(sws
, sq
->hwbuf
, PIPE_TRANSFER_WRITE
);
101 if (!sq
->queryResult
) {
102 sws
->buffer_destroy(sws
, sq
->hwbuf
);
103 return PIPE_ERROR_OUT_OF_MEMORY
;
106 sq
->queryResult
->totalSize
= sizeof *sq
->queryResult
;
107 sq
->queryResult
->state
= SVGA3D_QUERYSTATE_NEW
;
109 /* We request the buffer to be pinned and assume it is always mapped.
110 * The reason is that we don't want to wait for fences when checking the
113 sws
->buffer_unmap(sws
, sq
->hwbuf
);
118 static enum pipe_error
119 begin_query_vgpu9(struct svga_context
*svga
, struct svga_query
*sq
)
121 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
122 enum pipe_error ret
= PIPE_OK
;
124 if (sq
->queryResult
->state
== SVGA3D_QUERYSTATE_PENDING
) {
125 /* The application doesn't care for the pending query result.
126 * We cannot let go of the existing buffer and just get a new one
127 * because its storage may be reused for other purposes and clobbered
128 * by the host when it determines the query result. So the only
129 * option here is to wait for the existing query's result -- not a
130 * big deal, given that no sane application would do this.
133 svga_get_query_result(&svga
->pipe
, &sq
->base
, TRUE
, (void*)&result
);
134 assert(sq
->queryResult
->state
!= SVGA3D_QUERYSTATE_PENDING
);
137 sq
->queryResult
->state
= SVGA3D_QUERYSTATE_NEW
;
138 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
140 ret
= SVGA3D_BeginQuery(svga
->swc
, sq
->svga_type
);
141 if (ret
!= PIPE_OK
) {
142 svga_context_flush(svga
, NULL
);
143 ret
= SVGA3D_BeginQuery(svga
->swc
, sq
->svga_type
);
148 static enum pipe_error
149 end_query_vgpu9(struct svga_context
*svga
, struct svga_query
*sq
)
151 enum pipe_error ret
= PIPE_OK
;
153 /* Set to PENDING before sending EndQuery. */
154 sq
->queryResult
->state
= SVGA3D_QUERYSTATE_PENDING
;
156 ret
= SVGA3D_EndQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
157 if (ret
!= PIPE_OK
) {
158 svga_context_flush(svga
, NULL
);
159 ret
= SVGA3D_EndQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
165 get_query_result_vgpu9(struct svga_context
*svga
, struct svga_query
*sq
,
166 boolean wait
, uint64_t *result
)
168 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
170 SVGA3dQueryState state
;
173 /* The query status won't be updated by the host unless
174 * SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
175 * a synchronous wait on the host.
177 ret
= SVGA3D_WaitForQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
178 if (ret
!= PIPE_OK
) {
179 svga_context_flush(svga
, NULL
);
180 ret
= SVGA3D_WaitForQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
182 assert (ret
== PIPE_OK
);
183 svga_context_flush(svga
, &sq
->fence
);
187 state
= sq
->queryResult
->state
;
188 if (state
== SVGA3D_QUERYSTATE_PENDING
) {
191 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
192 state
= sq
->queryResult
->state
;
195 assert(state
== SVGA3D_QUERYSTATE_SUCCEEDED
||
196 state
== SVGA3D_QUERYSTATE_FAILED
);
198 *result
= (uint64_t)sq
->queryResult
->result32
;
206 * There is one query mob allocated for each context to be shared by all
207 * query types. The mob is used to hold queries's state and result. Since
208 * each query result type is of different length, to ease the query allocation
209 * management, the mob is divided into memory blocks. Each memory block
210 * will hold queries of the same type. Multiple memory blocks can be allocated
211 * for a particular query type.
213 * Currently each memory block is of 184 bytes. We support up to 128
214 * memory blocks. The query memory size is arbitrary right now.
215 * Each occlusion query takes about 8 bytes. One memory block can accomodate
216 * 23 occlusion queries. 128 of those blocks can support up to 2944 occlusion
217 * queries. That seems reasonable for now. If we think this limit is
218 * not enough, we can increase the limit or try to grow the mob in runtime.
219 * Note, SVGA device does not impose one mob per context for queries,
220 * we could allocate multiple mobs for queries; however, wddm KMD does not
221 * currently support that.
223 * Also note that the GL guest driver does not issue any of the
224 * following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
226 #define SVGA_QUERY_MEM_BLOCK_SIZE (sizeof(SVGADXQueryResultUnion) * 2)
227 #define SVGA_QUERY_MEM_SIZE (128 * SVGA_QUERY_MEM_BLOCK_SIZE)
229 struct svga_qmem_alloc_entry
231 unsigned start_offset
; /* start offset of the memory block */
232 unsigned block_index
; /* block index of the memory block */
233 unsigned query_size
; /* query size in this memory block */
234 unsigned nquery
; /* number of queries allocated */
235 struct util_bitmask
*alloc_mask
; /* allocation mask */
236 struct svga_qmem_alloc_entry
*next
; /* next memory block */
241 * Allocate a memory block from the query object memory
242 * \return -1 if out of memory, else index of the query memory block
245 allocate_query_block(struct svga_context
*svga
)
250 /* Find the next available query block */
251 index
= util_bitmask_add(svga
->gb_query_alloc_mask
);
253 if (index
== UTIL_BITMASK_INVALID_INDEX
)
256 offset
= index
* SVGA_QUERY_MEM_BLOCK_SIZE
;
257 if (offset
>= svga
->gb_query_len
) {
261 * All the memory blocks are allocated, lets see if there is
262 * any empty memory block around that can be freed up.
265 for (i
= 0; i
< SVGA_QUERY_MAX
&& index
== -1; i
++) {
266 struct svga_qmem_alloc_entry
*alloc_entry
;
267 struct svga_qmem_alloc_entry
*prev_alloc_entry
= NULL
;
269 alloc_entry
= svga
->gb_query_map
[i
];
270 while (alloc_entry
&& index
== -1) {
271 if (alloc_entry
->nquery
== 0) {
272 /* This memory block is empty, it can be recycled. */
273 if (prev_alloc_entry
) {
274 prev_alloc_entry
->next
= alloc_entry
->next
;
276 svga
->gb_query_map
[i
] = alloc_entry
->next
;
278 index
= alloc_entry
->block_index
;
280 prev_alloc_entry
= alloc_entry
;
281 alloc_entry
= alloc_entry
->next
;
291 * Allocate a slot in the specified memory block.
292 * All slots in this memory block are of the same size.
294 * \return -1 if out of memory, else index of the query slot
297 allocate_query_slot(struct svga_context
*svga
,
298 struct svga_qmem_alloc_entry
*alloc
)
303 /* Find the next available slot */
304 index
= util_bitmask_add(alloc
->alloc_mask
);
306 if (index
== UTIL_BITMASK_INVALID_INDEX
)
309 offset
= index
* alloc
->query_size
;
310 if (offset
>= SVGA_QUERY_MEM_BLOCK_SIZE
)
319 * Deallocate the specified slot in the memory block.
320 * If all slots are freed up, then deallocate the memory block
321 * as well, so it can be allocated for other query type
324 deallocate_query_slot(struct svga_context
*svga
,
325 struct svga_qmem_alloc_entry
*alloc
,
328 assert(index
!= UTIL_BITMASK_INVALID_INDEX
);
330 util_bitmask_clear(alloc
->alloc_mask
, index
);
334 * Don't worry about deallocating the empty memory block here.
335 * The empty memory block will be recycled when no more memory block
340 static struct svga_qmem_alloc_entry
*
341 allocate_query_block_entry(struct svga_context
*svga
,
344 struct svga_qmem_alloc_entry
*alloc_entry
;
345 int block_index
= -1;
347 block_index
= allocate_query_block(svga
);
348 if (block_index
== -1)
350 alloc_entry
= CALLOC_STRUCT(svga_qmem_alloc_entry
);
354 alloc_entry
->block_index
= block_index
;
355 alloc_entry
->start_offset
= block_index
* SVGA_QUERY_MEM_BLOCK_SIZE
;
356 alloc_entry
->nquery
= 0;
357 alloc_entry
->alloc_mask
= util_bitmask_create();
358 alloc_entry
->next
= NULL
;
359 alloc_entry
->query_size
= len
;
365 * Allocate a memory slot for a query of the specified type.
366 * It will first search through the memory blocks that are allocated
367 * for the query type. If no memory slot is available, it will try
368 * to allocate another memory block within the query object memory for
372 allocate_query(struct svga_context
*svga
,
373 SVGA3dQueryType type
,
376 struct svga_qmem_alloc_entry
*alloc_entry
;
380 assert(type
< SVGA_QUERY_MAX
);
382 alloc_entry
= svga
->gb_query_map
[type
];
386 * No query memory block has been allocated for this query type,
389 alloc_entry
= allocate_query_block_entry(svga
, len
);
392 svga
->gb_query_map
[type
] = alloc_entry
;
395 /* Allocate a slot within the memory block allocated for this query type */
396 slot_index
= allocate_query_slot(svga
, alloc_entry
);
398 if (slot_index
== -1) {
399 /* This query memory block is full, allocate another one */
400 alloc_entry
= allocate_query_block_entry(svga
, len
);
403 alloc_entry
->next
= svga
->gb_query_map
[type
];
404 svga
->gb_query_map
[type
] = alloc_entry
;
405 slot_index
= allocate_query_slot(svga
, alloc_entry
);
408 assert(slot_index
!= -1);
409 offset
= slot_index
* len
+ alloc_entry
->start_offset
;
416 * Deallocate memory slot allocated for the specified query
419 deallocate_query(struct svga_context
*svga
,
420 struct svga_query
*sq
)
422 struct svga_qmem_alloc_entry
*alloc_entry
;
424 unsigned offset
= sq
->offset
;
426 alloc_entry
= svga
->gb_query_map
[sq
->svga_type
];
428 while (alloc_entry
) {
429 if (offset
>= alloc_entry
->start_offset
&&
430 offset
< alloc_entry
->start_offset
+ SVGA_QUERY_MEM_BLOCK_SIZE
) {
432 /* The slot belongs to this memory block, deallocate it */
433 slot_index
= (offset
- alloc_entry
->start_offset
) /
434 alloc_entry
->query_size
;
435 deallocate_query_slot(svga
, alloc_entry
, slot_index
);
438 alloc_entry
= alloc_entry
->next
;
445 * Destroy the gb query object and all the related query structures
448 destroy_gb_query_obj(struct svga_context
*svga
)
450 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
453 for (i
= 0; i
< SVGA_QUERY_MAX
; i
++) {
454 struct svga_qmem_alloc_entry
*alloc_entry
, *next
;
455 alloc_entry
= svga
->gb_query_map
[i
];
456 while (alloc_entry
) {
457 next
= alloc_entry
->next
;
458 util_bitmask_destroy(alloc_entry
->alloc_mask
);
462 svga
->gb_query_map
[i
] = NULL
;
466 sws
->query_destroy(sws
, svga
->gb_query
);
467 svga
->gb_query
= NULL
;
469 util_bitmask_destroy(svga
->gb_query_alloc_mask
);
473 * Define query and create the gb query object if it is not already created.
474 * There is only one gb query object per context which will be shared by
475 * queries of all types.
477 static enum pipe_error
478 define_query_vgpu10(struct svga_context
*svga
,
479 struct svga_query
*sq
, int resultLen
)
481 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
483 enum pipe_error ret
= PIPE_OK
;
485 SVGA_DBG(DEBUG_QUERY
, "%s\n", __FUNCTION__
);
487 if (svga
->gb_query
== NULL
) {
488 /* Create a gb query object */
489 svga
->gb_query
= sws
->query_create(sws
, SVGA_QUERY_MEM_SIZE
);
491 return PIPE_ERROR_OUT_OF_MEMORY
;
492 svga
->gb_query_len
= SVGA_QUERY_MEM_SIZE
;
493 memset (svga
->gb_query_map
, 0, sizeof(svga
->gb_query_map
));
494 svga
->gb_query_alloc_mask
= util_bitmask_create();
496 /* Bind the query object to the context */
497 if (svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
498 SVGA_QUERY_FLAG_SET
) != PIPE_OK
) {
499 svga_context_flush(svga
, NULL
);
500 svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
501 SVGA_QUERY_FLAG_SET
);
505 sq
->gb_query
= svga
->gb_query
;
507 /* Allocate an integer ID for this query */
508 sq
->id
= util_bitmask_add(svga
->query_id_bm
);
509 if (sq
->id
== UTIL_BITMASK_INVALID_INDEX
)
510 return PIPE_ERROR_OUT_OF_MEMORY
;
512 /* Find a slot for this query in the gb object */
513 qlen
= resultLen
+ sizeof(SVGA3dQueryState
);
514 sq
->offset
= allocate_query(svga
, sq
->svga_type
, qlen
);
515 if (sq
->offset
== -1)
516 return PIPE_ERROR_OUT_OF_MEMORY
;
518 SVGA_DBG(DEBUG_QUERY
, " query type=%d qid=0x%x offset=%d\n",
519 sq
->svga_type
, sq
->id
, sq
->offset
);
522 * Send SVGA3D commands to define the query
524 ret
= SVGA3D_vgpu10_DefineQuery(svga
->swc
, sq
->id
, sq
->svga_type
, sq
->flags
);
525 if (ret
!= PIPE_OK
) {
526 svga_context_flush(svga
, NULL
);
527 ret
= SVGA3D_vgpu10_DefineQuery(svga
->swc
, sq
->id
, sq
->svga_type
, sq
->flags
);
530 return PIPE_ERROR_OUT_OF_MEMORY
;
532 ret
= SVGA3D_vgpu10_BindQuery(svga
->swc
, sq
->gb_query
, sq
->id
);
533 if (ret
!= PIPE_OK
) {
534 svga_context_flush(svga
, NULL
);
535 ret
= SVGA3D_vgpu10_BindQuery(svga
->swc
, sq
->gb_query
, sq
->id
);
537 assert(ret
== PIPE_OK
);
539 ret
= SVGA3D_vgpu10_SetQueryOffset(svga
->swc
, sq
->id
, sq
->offset
);
540 if (ret
!= PIPE_OK
) {
541 svga_context_flush(svga
, NULL
);
542 ret
= SVGA3D_vgpu10_SetQueryOffset(svga
->swc
, sq
->id
, sq
->offset
);
544 assert(ret
== PIPE_OK
);
549 static enum pipe_error
550 destroy_query_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
)
554 ret
= SVGA3D_vgpu10_DestroyQuery(svga
->swc
, sq
->id
);
556 /* Deallocate the memory slot allocated for this query */
557 deallocate_query(svga
, sq
);
564 * Rebind queryies to the context.
567 rebind_vgpu10_query(struct svga_context
*svga
)
569 if (svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
570 SVGA_QUERY_FLAG_REF
) != PIPE_OK
) {
571 svga_context_flush(svga
, NULL
);
572 svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
573 SVGA_QUERY_FLAG_REF
);
576 svga
->rebind
.flags
.query
= FALSE
;
580 static enum pipe_error
581 begin_query_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
)
583 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
584 enum pipe_error ret
= PIPE_OK
;
587 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
589 /* Initialize the query state to NEW */
590 status
= sws
->query_init(sws
, sq
->gb_query
, sq
->offset
, SVGA3D_QUERYSTATE_NEW
);
594 if (svga
->rebind
.flags
.query
) {
595 rebind_vgpu10_query(svga
);
598 /* Send the BeginQuery command to the device */
599 ret
= SVGA3D_vgpu10_BeginQuery(svga
->swc
, sq
->id
);
600 if (ret
!= PIPE_OK
) {
601 svga_context_flush(svga
, NULL
);
602 ret
= SVGA3D_vgpu10_BeginQuery(svga
->swc
, sq
->id
);
607 static enum pipe_error
608 end_query_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
)
610 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
611 enum pipe_error ret
= PIPE_OK
;
613 if (svga
->rebind
.flags
.query
) {
614 rebind_vgpu10_query(svga
);
617 ret
= SVGA3D_vgpu10_EndQuery(svga
->swc
, sq
->id
);
618 if (ret
!= PIPE_OK
) {
619 svga_context_flush(svga
, NULL
);
620 ret
= SVGA3D_vgpu10_EndQuery(svga
->swc
, sq
->id
);
623 /* Finish fence is copied here from get_query_result_vgpu10. This helps
624 * with cases where svga_begin_query might be called again before
625 * svga_get_query_result, such as GL_TIME_ELAPSED.
628 svga_context_flush(svga
, &sq
->fence
);
630 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
636 get_query_result_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
,
637 boolean wait
, void *result
, int resultLen
)
639 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
640 SVGA3dQueryState queryState
;
642 if (svga
->rebind
.flags
.query
) {
643 rebind_vgpu10_query(svga
);
646 sws
->query_get_result(sws
, sq
->gb_query
, sq
->offset
, &queryState
, result
, resultLen
);
648 if (queryState
== SVGA3D_QUERYSTATE_PENDING
) {
651 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
652 sws
->query_get_result(sws
, sq
->gb_query
, sq
->offset
, &queryState
, result
, resultLen
);
655 assert(queryState
== SVGA3D_QUERYSTATE_SUCCEEDED
||
656 queryState
== SVGA3D_QUERYSTATE_FAILED
);
661 static struct pipe_query
*
662 svga_create_query(struct pipe_context
*pipe
,
666 struct svga_context
*svga
= svga_context(pipe
);
667 struct svga_query
*sq
;
669 assert(query_type
< SVGA_QUERY_MAX
);
671 sq
= CALLOC_STRUCT(svga_query
);
675 /* Allocate an integer ID for the query */
676 sq
->id
= util_bitmask_add(svga
->query_id_bm
);
677 if (sq
->id
== UTIL_BITMASK_INVALID_INDEX
)
680 SVGA_DBG(DEBUG_QUERY
, "%s type=%d sq=0x%x id=%d\n", __FUNCTION__
,
681 query_type
, sq
, sq
->id
);
683 switch (query_type
) {
684 case PIPE_QUERY_OCCLUSION_COUNTER
:
685 sq
->svga_type
= SVGA3D_QUERYTYPE_OCCLUSION
;
686 if (svga_have_vgpu10(svga
)) {
687 define_query_vgpu10(svga
, sq
, sizeof(SVGADXOcclusionQueryResult
));
690 * In OpenGL, occlusion counter query can be used in conditional
691 * rendering; however, in DX10, only OCCLUSION_PREDICATE query can
692 * be used for predication. Hence, we need to create an occlusion
693 * predicate query along with the occlusion counter query. So when
694 * the occlusion counter query is used for predication, the associated
695 * query of occlusion predicate type will be used
696 * in the SetPredication command.
698 sq
->predicate
= svga_create_query(pipe
, PIPE_QUERY_OCCLUSION_PREDICATE
, index
);
701 define_query_vgpu9(svga
, sq
);
704 case PIPE_QUERY_OCCLUSION_PREDICATE
:
705 assert(svga_have_vgpu10(svga
));
706 sq
->svga_type
= SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE
;
707 define_query_vgpu10(svga
, sq
, sizeof(SVGADXOcclusionPredicateQueryResult
));
709 case PIPE_QUERY_PRIMITIVES_GENERATED
:
710 case PIPE_QUERY_PRIMITIVES_EMITTED
:
711 case PIPE_QUERY_SO_STATISTICS
:
712 assert(svga_have_vgpu10(svga
));
713 sq
->svga_type
= SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS
;
714 define_query_vgpu10(svga
, sq
,
715 sizeof(SVGADXStreamOutStatisticsQueryResult
));
717 case PIPE_QUERY_TIMESTAMP
:
718 assert(svga_have_vgpu10(svga
));
719 sq
->svga_type
= SVGA3D_QUERYTYPE_TIMESTAMP
;
720 define_query_vgpu10(svga
, sq
,
721 sizeof(SVGADXTimestampQueryResult
));
723 case SVGA_QUERY_NUM_DRAW_CALLS
:
724 case SVGA_QUERY_NUM_FALLBACKS
:
725 case SVGA_QUERY_NUM_FLUSHES
:
726 case SVGA_QUERY_NUM_VALIDATIONS
:
727 case SVGA_QUERY_MAP_BUFFER_TIME
:
728 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
729 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
730 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
731 case SVGA_QUERY_FLUSH_TIME
:
732 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
733 case SVGA_QUERY_MEMORY_USED
:
734 case SVGA_QUERY_NUM_SHADERS
:
735 case SVGA_QUERY_NUM_RESOURCES
:
736 case SVGA_QUERY_NUM_STATE_OBJECTS
:
737 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
738 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
741 assert(!"unexpected query type in svga_create_query()");
744 sq
->type
= query_type
;
754 svga_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
756 struct svga_context
*svga
= svga_context(pipe
);
757 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
758 struct svga_query
*sq
;
761 destroy_gb_query_obj(svga
);
767 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d\n", __FUNCTION__
,
771 case PIPE_QUERY_OCCLUSION_COUNTER
:
772 if (svga_have_vgpu10(svga
)) {
773 /* make sure to also destroy any associated predicate query */
775 svga_destroy_query(pipe
, sq
->predicate
);
776 destroy_query_vgpu10(svga
, sq
);
778 sws
->buffer_destroy(sws
, sq
->hwbuf
);
780 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
782 case PIPE_QUERY_OCCLUSION_PREDICATE
:
783 assert(svga_have_vgpu10(svga
));
784 destroy_query_vgpu10(svga
, sq
);
785 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
787 case PIPE_QUERY_PRIMITIVES_GENERATED
:
788 case PIPE_QUERY_PRIMITIVES_EMITTED
:
789 case PIPE_QUERY_SO_STATISTICS
:
790 case PIPE_QUERY_TIMESTAMP
:
791 assert(svga_have_vgpu10(svga
));
792 destroy_query_vgpu10(svga
, sq
);
793 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
795 case SVGA_QUERY_NUM_DRAW_CALLS
:
796 case SVGA_QUERY_NUM_FALLBACKS
:
797 case SVGA_QUERY_NUM_FLUSHES
:
798 case SVGA_QUERY_NUM_VALIDATIONS
:
799 case SVGA_QUERY_MAP_BUFFER_TIME
:
800 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
801 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
802 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
803 case SVGA_QUERY_FLUSH_TIME
:
804 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
805 case SVGA_QUERY_MEMORY_USED
:
806 case SVGA_QUERY_NUM_SHADERS
:
807 case SVGA_QUERY_NUM_RESOURCES
:
808 case SVGA_QUERY_NUM_STATE_OBJECTS
:
809 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
810 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
814 assert(!"svga: unexpected query type in svga_destroy_query()");
817 /* Free the query id */
818 util_bitmask_clear(svga
->query_id_bm
, sq
->id
);
825 svga_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
827 struct svga_context
*svga
= svga_context(pipe
);
828 struct svga_query
*sq
= svga_query(q
);
832 assert(sq
->type
< SVGA_QUERY_MAX
);
834 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d\n", __FUNCTION__
,
837 /* Need to flush out buffered drawing commands so that they don't
838 * get counted in the query results.
840 svga_hwtnl_flush_retry(svga
);
843 case PIPE_QUERY_OCCLUSION_COUNTER
:
844 if (svga_have_vgpu10(svga
)) {
845 ret
= begin_query_vgpu10(svga
, sq
);
846 /* also need to start the associated occlusion predicate query */
848 enum pipe_error status
;
849 status
= begin_query_vgpu10(svga
, svga_query(sq
->predicate
));
850 assert(status
== PIPE_OK
);
854 ret
= begin_query_vgpu9(svga
, sq
);
856 assert(ret
== PIPE_OK
);
859 case PIPE_QUERY_OCCLUSION_PREDICATE
:
860 assert(svga_have_vgpu10(svga
));
861 ret
= begin_query_vgpu10(svga
, sq
);
862 assert(ret
== PIPE_OK
);
864 case PIPE_QUERY_PRIMITIVES_GENERATED
:
865 case PIPE_QUERY_PRIMITIVES_EMITTED
:
866 case PIPE_QUERY_SO_STATISTICS
:
867 case PIPE_QUERY_TIMESTAMP
:
868 assert(svga_have_vgpu10(svga
));
869 ret
= begin_query_vgpu10(svga
, sq
);
870 assert(ret
== PIPE_OK
);
872 case SVGA_QUERY_NUM_DRAW_CALLS
:
873 sq
->begin_count
= svga
->hud
.num_draw_calls
;
875 case SVGA_QUERY_NUM_FALLBACKS
:
876 sq
->begin_count
= svga
->hud
.num_fallbacks
;
878 case SVGA_QUERY_NUM_FLUSHES
:
879 sq
->begin_count
= svga
->hud
.num_flushes
;
881 case SVGA_QUERY_NUM_VALIDATIONS
:
882 sq
->begin_count
= svga
->hud
.num_validations
;
884 case SVGA_QUERY_MAP_BUFFER_TIME
:
885 sq
->begin_count
= svga
->hud
.map_buffer_time
;
887 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
888 sq
->begin_count
= svga
->hud
.num_resources_mapped
;
890 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
891 sq
->begin_count
= svga
->hud
.num_bytes_uploaded
;
893 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
894 sq
->begin_count
= svga
->hud
.command_buffer_size
;
896 case SVGA_QUERY_FLUSH_TIME
:
897 sq
->begin_count
= svga
->hud
.flush_time
;
899 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
900 sq
->begin_count
= svga
->hud
.surface_write_flushes
;
902 case SVGA_QUERY_MEMORY_USED
:
903 case SVGA_QUERY_NUM_SHADERS
:
904 case SVGA_QUERY_NUM_RESOURCES
:
905 case SVGA_QUERY_NUM_STATE_OBJECTS
:
906 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
907 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
911 assert(!"unexpected query type in svga_begin_query()");
914 svga
->sq
[sq
->type
] = sq
;
921 svga_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
923 struct svga_context
*svga
= svga_context(pipe
);
924 struct svga_query
*sq
= svga_query(q
);
928 assert(sq
->type
< SVGA_QUERY_MAX
);
930 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d\n", __FUNCTION__
,
933 if (sq
->type
== PIPE_QUERY_TIMESTAMP
&& svga
->sq
[sq
->type
] != sq
)
934 svga_begin_query(pipe
, q
);
936 svga_hwtnl_flush_retry(svga
);
938 assert(svga
->sq
[sq
->type
] == sq
);
941 case PIPE_QUERY_OCCLUSION_COUNTER
:
942 if (svga_have_vgpu10(svga
)) {
943 ret
= end_query_vgpu10(svga
, sq
);
944 /* also need to end the associated occlusion predicate query */
946 enum pipe_error status
;
947 status
= end_query_vgpu10(svga
, svga_query(sq
->predicate
));
948 assert(status
== PIPE_OK
);
952 ret
= end_query_vgpu9(svga
, sq
);
954 assert(ret
== PIPE_OK
);
956 /* TODO: Delay flushing. We don't really need to flush here, just ensure
957 * that there is one flush before svga_get_query_result attempts to get
960 svga_context_flush(svga
, NULL
);
962 case PIPE_QUERY_OCCLUSION_PREDICATE
:
963 assert(svga_have_vgpu10(svga
));
964 ret
= end_query_vgpu10(svga
, sq
);
965 assert(ret
== PIPE_OK
);
967 case PIPE_QUERY_PRIMITIVES_GENERATED
:
968 case PIPE_QUERY_PRIMITIVES_EMITTED
:
969 case PIPE_QUERY_SO_STATISTICS
:
970 case PIPE_QUERY_TIMESTAMP
:
971 assert(svga_have_vgpu10(svga
));
972 ret
= end_query_vgpu10(svga
, sq
);
973 assert(ret
== PIPE_OK
);
975 case SVGA_QUERY_NUM_DRAW_CALLS
:
976 sq
->end_count
= svga
->hud
.num_draw_calls
;
978 case SVGA_QUERY_NUM_FALLBACKS
:
979 sq
->end_count
= svga
->hud
.num_fallbacks
;
981 case SVGA_QUERY_NUM_FLUSHES
:
982 sq
->end_count
= svga
->hud
.num_flushes
;
984 case SVGA_QUERY_NUM_VALIDATIONS
:
985 sq
->end_count
= svga
->hud
.num_validations
;
987 case SVGA_QUERY_MAP_BUFFER_TIME
:
988 sq
->end_count
= svga
->hud
.map_buffer_time
;
990 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
991 sq
->end_count
= svga
->hud
.num_resources_mapped
;
993 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
994 sq
->end_count
= svga
->hud
.num_bytes_uploaded
;
996 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
997 sq
->end_count
= svga
->hud
.command_buffer_size
;
999 case SVGA_QUERY_FLUSH_TIME
:
1000 sq
->end_count
= svga
->hud
.flush_time
;
1002 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
1003 sq
->end_count
= svga
->hud
.surface_write_flushes
;
1005 case SVGA_QUERY_MEMORY_USED
:
1006 case SVGA_QUERY_NUM_SHADERS
:
1007 case SVGA_QUERY_NUM_RESOURCES
:
1008 case SVGA_QUERY_NUM_STATE_OBJECTS
:
1009 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
1010 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
1014 assert(!"unexpected query type in svga_end_query()");
1016 svga
->sq
[sq
->type
] = NULL
;
1021 svga_get_query_result(struct pipe_context
*pipe
,
1022 struct pipe_query
*q
,
1024 union pipe_query_result
*vresult
)
1026 struct svga_screen
*svgascreen
= svga_screen(pipe
->screen
);
1027 struct svga_context
*svga
= svga_context(pipe
);
1028 struct svga_query
*sq
= svga_query(q
);
1029 uint64_t *result
= (uint64_t *)vresult
;
1034 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d wait: %d\n",
1035 __FUNCTION__
, sq
, sq
->id
, wait
);
1038 case PIPE_QUERY_OCCLUSION_COUNTER
:
1039 if (svga_have_vgpu10(svga
)) {
1040 SVGADXOcclusionQueryResult occResult
;
1041 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1042 (void *)&occResult
, sizeof(occResult
));
1043 *result
= (uint64_t)occResult
.samplesRendered
;
1045 ret
= get_query_result_vgpu9(svga
, sq
, wait
, (uint64_t *)result
);
1048 case PIPE_QUERY_OCCLUSION_PREDICATE
: {
1049 SVGADXOcclusionPredicateQueryResult occResult
;
1050 assert(svga_have_vgpu10(svga
));
1051 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1052 (void *)&occResult
, sizeof(occResult
));
1053 vresult
->b
= occResult
.anySamplesRendered
!= 0;
1056 case PIPE_QUERY_SO_STATISTICS
: {
1057 SVGADXStreamOutStatisticsQueryResult sResult
;
1058 struct pipe_query_data_so_statistics
*pResult
=
1059 (struct pipe_query_data_so_statistics
*)vresult
;
1061 assert(svga_have_vgpu10(svga
));
1062 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1063 (void *)&sResult
, sizeof(sResult
));
1064 pResult
->num_primitives_written
= sResult
.numPrimitivesWritten
;
1065 pResult
->primitives_storage_needed
= sResult
.numPrimitivesRequired
;
1068 case PIPE_QUERY_TIMESTAMP
: {
1069 SVGADXTimestampQueryResult sResult
;
1071 assert(svga_have_vgpu10(svga
));
1072 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1073 (void *)&sResult
, sizeof(sResult
));
1074 *result
= (uint64_t)sResult
.timestamp
;
1077 case PIPE_QUERY_PRIMITIVES_GENERATED
: {
1078 SVGADXStreamOutStatisticsQueryResult sResult
;
1080 assert(svga_have_vgpu10(svga
));
1081 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1082 (void *)&sResult
, sizeof sResult
);
1083 *result
= (uint64_t)sResult
.numPrimitivesRequired
;
1086 case PIPE_QUERY_PRIMITIVES_EMITTED
: {
1087 SVGADXStreamOutStatisticsQueryResult sResult
;
1089 assert(svga_have_vgpu10(svga
));
1090 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1091 (void *)&sResult
, sizeof sResult
);
1092 *result
= (uint64_t)sResult
.numPrimitivesWritten
;
1095 /* These are per-frame counters */
1096 case SVGA_QUERY_NUM_DRAW_CALLS
:
1097 case SVGA_QUERY_NUM_FALLBACKS
:
1098 case SVGA_QUERY_NUM_FLUSHES
:
1099 case SVGA_QUERY_NUM_VALIDATIONS
:
1100 case SVGA_QUERY_MAP_BUFFER_TIME
:
1101 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
1102 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
1103 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
1104 case SVGA_QUERY_FLUSH_TIME
:
1105 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
1106 vresult
->u64
= sq
->end_count
- sq
->begin_count
;
1108 /* These are running total counters */
1109 case SVGA_QUERY_MEMORY_USED
:
1110 vresult
->u64
= svgascreen
->hud
.total_resource_bytes
;
1112 case SVGA_QUERY_NUM_SHADERS
:
1113 vresult
->u64
= svga
->hud
.num_shaders
;
1115 case SVGA_QUERY_NUM_RESOURCES
:
1116 vresult
->u64
= svgascreen
->hud
.num_resources
;
1118 case SVGA_QUERY_NUM_STATE_OBJECTS
:
1119 vresult
->u64
= svga
->hud
.num_state_objects
;
1121 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
1122 vresult
->u64
= svga
->hud
.num_surface_views
;
1124 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
1125 vresult
->u64
= svga
->hud
.num_generate_mipmap
;
1128 assert(!"unexpected query type in svga_get_query_result");
1131 SVGA_DBG(DEBUG_QUERY
, "%s result %d\n", __FUNCTION__
, *((uint64_t *)vresult
));
1137 svga_render_condition(struct pipe_context
*pipe
, struct pipe_query
*q
,
1138 boolean condition
, uint mode
)
1140 struct svga_context
*svga
= svga_context(pipe
);
1141 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
1142 struct svga_query
*sq
= svga_query(q
);
1143 SVGA3dQueryId queryId
;
1144 enum pipe_error ret
;
1146 SVGA_DBG(DEBUG_QUERY
, "%s\n", __FUNCTION__
);
1148 assert(svga_have_vgpu10(svga
));
1150 queryId
= SVGA3D_INVALID_ID
;
1153 assert(sq
->svga_type
== SVGA3D_QUERYTYPE_OCCLUSION
||
1154 sq
->svga_type
== SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE
);
1156 if (sq
->svga_type
== SVGA3D_QUERYTYPE_OCCLUSION
) {
1157 assert(sq
->predicate
);
1159 * For conditional rendering, make sure to use the associated
1162 sq
= svga_query(sq
->predicate
);
1166 if ((mode
== PIPE_RENDER_COND_WAIT
||
1167 mode
== PIPE_RENDER_COND_BY_REGION_WAIT
) && sq
->fence
) {
1168 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
1172 ret
= SVGA3D_vgpu10_SetPredication(svga
->swc
, queryId
,
1173 (uint32
) condition
);
1174 if (ret
!= PIPE_OK
) {
1175 svga_context_flush(svga
, NULL
);
1176 ret
= SVGA3D_vgpu10_SetPredication(svga
->swc
, queryId
,
1177 (uint32
) condition
);
1183 * This function is a workaround because we lack the ability to query
1184 * renderer's time synchornously.
1187 svga_get_timestamp(struct pipe_context
*pipe
)
1189 struct pipe_query
*q
= svga_create_query(pipe
, PIPE_QUERY_TIMESTAMP
, 0);
1190 union pipe_query_result result
;
1192 svga_begin_query(pipe
, q
);
1193 svga_end_query(pipe
,q
);
1194 svga_get_query_result(pipe
, q
, TRUE
, &result
);
1195 svga_destroy_query(pipe
, q
);
1202 svga_init_query_functions(struct svga_context
*svga
)
1204 svga
->pipe
.create_query
= svga_create_query
;
1205 svga
->pipe
.destroy_query
= svga_destroy_query
;
1206 svga
->pipe
.begin_query
= svga_begin_query
;
1207 svga
->pipe
.end_query
= svga_end_query
;
1208 svga
->pipe
.get_query_result
= svga_get_query_result
;
1209 svga
->pipe
.render_condition
= svga_render_condition
;
1210 svga
->pipe
.get_timestamp
= svga_get_timestamp
;