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
;
85 svga_get_query_result(struct pipe_context
*pipe
,
88 union pipe_query_result
*result
);
90 static enum pipe_error
91 define_query_vgpu9(struct svga_context
*svga
,
92 struct svga_query
*sq
)
94 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
96 sq
->hwbuf
= svga_winsys_buffer_create(svga
, 1,
97 SVGA_BUFFER_USAGE_PINNED
,
98 sizeof *sq
->queryResult
);
100 return PIPE_ERROR_OUT_OF_MEMORY
;
102 sq
->queryResult
= (SVGA3dQueryResult
*)
103 sws
->buffer_map(sws
, sq
->hwbuf
, PIPE_TRANSFER_WRITE
);
104 if (!sq
->queryResult
) {
105 sws
->buffer_destroy(sws
, sq
->hwbuf
);
106 return PIPE_ERROR_OUT_OF_MEMORY
;
109 sq
->queryResult
->totalSize
= sizeof *sq
->queryResult
;
110 sq
->queryResult
->state
= SVGA3D_QUERYSTATE_NEW
;
112 /* We request the buffer to be pinned and assume it is always mapped.
113 * The reason is that we don't want to wait for fences when checking the
116 sws
->buffer_unmap(sws
, sq
->hwbuf
);
121 static enum pipe_error
122 begin_query_vgpu9(struct svga_context
*svga
, struct svga_query
*sq
)
124 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
125 enum pipe_error ret
= PIPE_OK
;
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.
136 svga_get_query_result(&svga
->pipe
, &sq
->base
, TRUE
, (void*)&result
);
137 assert(sq
->queryResult
->state
!= SVGA3D_QUERYSTATE_PENDING
);
140 sq
->queryResult
->state
= SVGA3D_QUERYSTATE_NEW
;
141 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
143 ret
= SVGA3D_BeginQuery(svga
->swc
, sq
->svga_type
);
144 if (ret
!= PIPE_OK
) {
145 svga_context_flush(svga
, NULL
);
146 ret
= SVGA3D_BeginQuery(svga
->swc
, sq
->svga_type
);
151 static enum pipe_error
152 end_query_vgpu9(struct svga_context
*svga
, struct svga_query
*sq
)
154 enum pipe_error ret
= PIPE_OK
;
156 /* Set to PENDING before sending EndQuery. */
157 sq
->queryResult
->state
= SVGA3D_QUERYSTATE_PENDING
;
159 ret
= SVGA3D_EndQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
160 if (ret
!= PIPE_OK
) {
161 svga_context_flush(svga
, NULL
);
162 ret
= SVGA3D_EndQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
168 get_query_result_vgpu9(struct svga_context
*svga
, struct svga_query
*sq
,
169 boolean wait
, uint64_t *result
)
171 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
173 SVGA3dQueryState state
;
176 /* The query status won't be updated by the host unless
177 * SVGA_3D_CMD_WAIT_FOR_QUERY is emitted. Unfortunately this will cause
178 * a synchronous wait on the host.
180 ret
= SVGA3D_WaitForQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
181 if (ret
!= PIPE_OK
) {
182 svga_context_flush(svga
, NULL
);
183 ret
= SVGA3D_WaitForQuery(svga
->swc
, sq
->svga_type
, sq
->hwbuf
);
185 assert (ret
== PIPE_OK
);
186 svga_context_flush(svga
, &sq
->fence
);
190 state
= sq
->queryResult
->state
;
191 if (state
== SVGA3D_QUERYSTATE_PENDING
) {
194 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
195 state
= sq
->queryResult
->state
;
198 assert(state
== SVGA3D_QUERYSTATE_SUCCEEDED
||
199 state
== SVGA3D_QUERYSTATE_FAILED
);
201 *result
= (uint64_t)sq
->queryResult
->result32
;
209 * There is one query mob allocated for each context to be shared by all
210 * query types. The mob is used to hold queries's state and result. Since
211 * each query result type is of different length, to ease the query allocation
212 * management, the mob is divided into memory blocks. Each memory block
213 * will hold queries of the same type. Multiple memory blocks can be allocated
214 * for a particular query type.
216 * Currently each memory block is of 184 bytes. We support up to 128
217 * memory blocks. The query memory size is arbitrary right now.
218 * Each occlusion query takes about 8 bytes. One memory block can accomodate
219 * 23 occlusion queries. 128 of those blocks can support up to 2944 occlusion
220 * queries. That seems reasonable for now. If we think this limit is
221 * not enough, we can increase the limit or try to grow the mob in runtime.
222 * Note, SVGA device does not impose one mob per context for queries,
223 * we could allocate multiple mobs for queries; however, wddm KMD does not
224 * currently support that.
226 * Also note that the GL guest driver does not issue any of the
227 * following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
229 #define SVGA_QUERY_MEM_BLOCK_SIZE (sizeof(SVGADXQueryResultUnion) * 2)
230 #define SVGA_QUERY_MEM_SIZE (128 * SVGA_QUERY_MEM_BLOCK_SIZE)
232 struct svga_qmem_alloc_entry
234 unsigned start_offset
; /* start offset of the memory block */
235 unsigned block_index
; /* block index of the memory block */
236 unsigned query_size
; /* query size in this memory block */
237 unsigned nquery
; /* number of queries allocated */
238 struct util_bitmask
*alloc_mask
; /* allocation mask */
239 struct svga_qmem_alloc_entry
*next
; /* next memory block */
244 * Allocate a memory block from the query object memory
245 * \return -1 if out of memory, else index of the query memory block
248 allocate_query_block(struct svga_context
*svga
)
253 /* Find the next available query block */
254 index
= util_bitmask_add(svga
->gb_query_alloc_mask
);
256 if (index
== UTIL_BITMASK_INVALID_INDEX
)
259 offset
= index
* SVGA_QUERY_MEM_BLOCK_SIZE
;
260 if (offset
>= svga
->gb_query_len
) {
264 * All the memory blocks are allocated, lets see if there is
265 * any empty memory block around that can be freed up.
268 for (i
= 0; i
< SVGA_QUERY_MAX
&& index
== -1; i
++) {
269 struct svga_qmem_alloc_entry
*alloc_entry
;
270 struct svga_qmem_alloc_entry
*prev_alloc_entry
= NULL
;
272 alloc_entry
= svga
->gb_query_map
[i
];
273 while (alloc_entry
&& index
== -1) {
274 if (alloc_entry
->nquery
== 0) {
275 /* This memory block is empty, it can be recycled. */
276 if (prev_alloc_entry
) {
277 prev_alloc_entry
->next
= alloc_entry
->next
;
279 svga
->gb_query_map
[i
] = alloc_entry
->next
;
281 index
= alloc_entry
->block_index
;
283 prev_alloc_entry
= alloc_entry
;
284 alloc_entry
= alloc_entry
->next
;
294 * Allocate a slot in the specified memory block.
295 * All slots in this memory block are of the same size.
297 * \return -1 if out of memory, else index of the query slot
300 allocate_query_slot(struct svga_context
*svga
,
301 struct svga_qmem_alloc_entry
*alloc
)
306 /* Find the next available slot */
307 index
= util_bitmask_add(alloc
->alloc_mask
);
309 if (index
== UTIL_BITMASK_INVALID_INDEX
)
312 offset
= index
* alloc
->query_size
;
313 if (offset
>= SVGA_QUERY_MEM_BLOCK_SIZE
)
322 * Deallocate the specified slot in the memory block.
323 * If all slots are freed up, then deallocate the memory block
324 * as well, so it can be allocated for other query type
327 deallocate_query_slot(struct svga_context
*svga
,
328 struct svga_qmem_alloc_entry
*alloc
,
331 assert(index
!= UTIL_BITMASK_INVALID_INDEX
);
333 util_bitmask_clear(alloc
->alloc_mask
, index
);
337 * Don't worry about deallocating the empty memory block here.
338 * The empty memory block will be recycled when no more memory block
343 static struct svga_qmem_alloc_entry
*
344 allocate_query_block_entry(struct svga_context
*svga
,
347 struct svga_qmem_alloc_entry
*alloc_entry
;
348 int block_index
= -1;
350 block_index
= allocate_query_block(svga
);
351 if (block_index
== -1)
353 alloc_entry
= CALLOC_STRUCT(svga_qmem_alloc_entry
);
357 alloc_entry
->block_index
= block_index
;
358 alloc_entry
->start_offset
= block_index
* SVGA_QUERY_MEM_BLOCK_SIZE
;
359 alloc_entry
->nquery
= 0;
360 alloc_entry
->alloc_mask
= util_bitmask_create();
361 alloc_entry
->next
= NULL
;
362 alloc_entry
->query_size
= len
;
368 * Allocate a memory slot for a query of the specified type.
369 * It will first search through the memory blocks that are allocated
370 * for the query type. If no memory slot is available, it will try
371 * to allocate another memory block within the query object memory for
375 allocate_query(struct svga_context
*svga
,
376 SVGA3dQueryType type
,
379 struct svga_qmem_alloc_entry
*alloc_entry
;
383 assert(type
< SVGA_QUERY_MAX
);
385 alloc_entry
= svga
->gb_query_map
[type
];
389 * No query memory block has been allocated for this query type,
392 alloc_entry
= allocate_query_block_entry(svga
, len
);
395 svga
->gb_query_map
[type
] = alloc_entry
;
398 /* Allocate a slot within the memory block allocated for this query type */
399 slot_index
= allocate_query_slot(svga
, alloc_entry
);
401 if (slot_index
== -1) {
402 /* This query memory block is full, allocate another one */
403 alloc_entry
= allocate_query_block_entry(svga
, len
);
406 alloc_entry
->next
= svga
->gb_query_map
[type
];
407 svga
->gb_query_map
[type
] = alloc_entry
;
408 slot_index
= allocate_query_slot(svga
, alloc_entry
);
411 assert(slot_index
!= -1);
412 offset
= slot_index
* len
+ alloc_entry
->start_offset
;
419 * Deallocate memory slot allocated for the specified query
422 deallocate_query(struct svga_context
*svga
,
423 struct svga_query
*sq
)
425 struct svga_qmem_alloc_entry
*alloc_entry
;
427 unsigned offset
= sq
->offset
;
429 alloc_entry
= svga
->gb_query_map
[sq
->svga_type
];
431 while (alloc_entry
) {
432 if (offset
>= alloc_entry
->start_offset
&&
433 offset
< alloc_entry
->start_offset
+ SVGA_QUERY_MEM_BLOCK_SIZE
) {
435 /* The slot belongs to this memory block, deallocate it */
436 slot_index
= (offset
- alloc_entry
->start_offset
) /
437 alloc_entry
->query_size
;
438 deallocate_query_slot(svga
, alloc_entry
, slot_index
);
441 alloc_entry
= alloc_entry
->next
;
448 * Destroy the gb query object and all the related query structures
451 destroy_gb_query_obj(struct svga_context
*svga
)
453 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
456 for (i
= 0; i
< SVGA_QUERY_MAX
; i
++) {
457 struct svga_qmem_alloc_entry
*alloc_entry
, *next
;
458 alloc_entry
= svga
->gb_query_map
[i
];
459 while (alloc_entry
) {
460 next
= alloc_entry
->next
;
461 util_bitmask_destroy(alloc_entry
->alloc_mask
);
465 svga
->gb_query_map
[i
] = NULL
;
469 sws
->query_destroy(sws
, svga
->gb_query
);
470 svga
->gb_query
= NULL
;
472 util_bitmask_destroy(svga
->gb_query_alloc_mask
);
476 * Define query and create the gb query object if it is not already created.
477 * There is only one gb query object per context which will be shared by
478 * queries of all types.
480 static enum pipe_error
481 define_query_vgpu10(struct svga_context
*svga
,
482 struct svga_query
*sq
, int resultLen
)
484 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
486 enum pipe_error ret
= PIPE_OK
;
488 SVGA_DBG(DEBUG_QUERY
, "%s\n", __FUNCTION__
);
490 if (svga
->gb_query
== NULL
) {
491 /* Create a gb query object */
492 svga
->gb_query
= sws
->query_create(sws
, SVGA_QUERY_MEM_SIZE
);
494 return PIPE_ERROR_OUT_OF_MEMORY
;
495 svga
->gb_query_len
= SVGA_QUERY_MEM_SIZE
;
496 memset (svga
->gb_query_map
, 0, sizeof(svga
->gb_query_map
));
497 svga
->gb_query_alloc_mask
= util_bitmask_create();
499 /* Bind the query object to the context */
500 if (svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
501 SVGA_QUERY_FLAG_SET
) != PIPE_OK
) {
502 svga_context_flush(svga
, NULL
);
503 svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
504 SVGA_QUERY_FLAG_SET
);
508 sq
->gb_query
= svga
->gb_query
;
510 /* Allocate an integer ID for this query */
511 sq
->id
= util_bitmask_add(svga
->query_id_bm
);
512 if (sq
->id
== UTIL_BITMASK_INVALID_INDEX
)
513 return PIPE_ERROR_OUT_OF_MEMORY
;
515 /* Find a slot for this query in the gb object */
516 qlen
= resultLen
+ sizeof(SVGA3dQueryState
);
517 sq
->offset
= allocate_query(svga
, sq
->svga_type
, qlen
);
518 if (sq
->offset
== -1)
519 return PIPE_ERROR_OUT_OF_MEMORY
;
521 SVGA_DBG(DEBUG_QUERY
, " query type=%d qid=0x%x offset=%d\n",
522 sq
->svga_type
, sq
->id
, sq
->offset
);
525 * Send SVGA3D commands to define the query
527 ret
= SVGA3D_vgpu10_DefineQuery(svga
->swc
, sq
->id
, sq
->svga_type
, sq
->flags
);
528 if (ret
!= PIPE_OK
) {
529 svga_context_flush(svga
, NULL
);
530 ret
= SVGA3D_vgpu10_DefineQuery(svga
->swc
, sq
->id
, sq
->svga_type
, sq
->flags
);
533 return PIPE_ERROR_OUT_OF_MEMORY
;
535 ret
= SVGA3D_vgpu10_BindQuery(svga
->swc
, sq
->gb_query
, sq
->id
);
536 if (ret
!= PIPE_OK
) {
537 svga_context_flush(svga
, NULL
);
538 ret
= SVGA3D_vgpu10_BindQuery(svga
->swc
, sq
->gb_query
, sq
->id
);
540 assert(ret
== PIPE_OK
);
542 ret
= SVGA3D_vgpu10_SetQueryOffset(svga
->swc
, sq
->id
, sq
->offset
);
543 if (ret
!= PIPE_OK
) {
544 svga_context_flush(svga
, NULL
);
545 ret
= SVGA3D_vgpu10_SetQueryOffset(svga
->swc
, sq
->id
, sq
->offset
);
547 assert(ret
== PIPE_OK
);
552 static enum pipe_error
553 destroy_query_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
)
557 ret
= SVGA3D_vgpu10_DestroyQuery(svga
->swc
, sq
->id
);
559 /* Deallocate the memory slot allocated for this query */
560 deallocate_query(svga
, sq
);
567 * Rebind queryies to the context.
570 rebind_vgpu10_query(struct svga_context
*svga
)
572 if (svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
573 SVGA_QUERY_FLAG_REF
) != PIPE_OK
) {
574 svga_context_flush(svga
, NULL
);
575 svga
->swc
->query_bind(svga
->swc
, svga
->gb_query
,
576 SVGA_QUERY_FLAG_REF
);
579 svga
->rebind
.flags
.query
= FALSE
;
583 static enum pipe_error
584 begin_query_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
)
586 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
587 enum pipe_error ret
= PIPE_OK
;
590 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
592 /* Initialize the query state to NEW */
593 status
= sws
->query_init(sws
, sq
->gb_query
, sq
->offset
, SVGA3D_QUERYSTATE_NEW
);
597 if (svga
->rebind
.flags
.query
) {
598 rebind_vgpu10_query(svga
);
601 /* Send the BeginQuery command to the device */
602 ret
= SVGA3D_vgpu10_BeginQuery(svga
->swc
, sq
->id
);
603 if (ret
!= PIPE_OK
) {
604 svga_context_flush(svga
, NULL
);
605 ret
= SVGA3D_vgpu10_BeginQuery(svga
->swc
, sq
->id
);
610 static enum pipe_error
611 end_query_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
)
613 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
614 enum pipe_error ret
= PIPE_OK
;
616 if (svga
->rebind
.flags
.query
) {
617 rebind_vgpu10_query(svga
);
620 ret
= SVGA3D_vgpu10_EndQuery(svga
->swc
, sq
->id
);
621 if (ret
!= PIPE_OK
) {
622 svga_context_flush(svga
, NULL
);
623 ret
= SVGA3D_vgpu10_EndQuery(svga
->swc
, sq
->id
);
626 /* Finish fence is copied here from get_query_result_vgpu10. This helps
627 * with cases where svga_begin_query might be called again before
628 * svga_get_query_result, such as GL_TIME_ELAPSED.
631 svga_context_flush(svga
, &sq
->fence
);
633 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
639 get_query_result_vgpu10(struct svga_context
*svga
, struct svga_query
*sq
,
640 boolean wait
, void *result
, int resultLen
)
642 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
643 SVGA3dQueryState queryState
;
645 if (svga
->rebind
.flags
.query
) {
646 rebind_vgpu10_query(svga
);
649 sws
->query_get_result(sws
, sq
->gb_query
, sq
->offset
, &queryState
, result
, resultLen
);
651 if (queryState
== SVGA3D_QUERYSTATE_PENDING
) {
654 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
655 sws
->query_get_result(sws
, sq
->gb_query
, sq
->offset
, &queryState
, result
, resultLen
);
658 assert(queryState
== SVGA3D_QUERYSTATE_SUCCEEDED
||
659 queryState
== SVGA3D_QUERYSTATE_FAILED
);
664 static struct pipe_query
*
665 svga_create_query(struct pipe_context
*pipe
,
669 struct svga_context
*svga
= svga_context(pipe
);
670 struct svga_query
*sq
;
672 assert(query_type
< SVGA_QUERY_MAX
);
674 sq
= CALLOC_STRUCT(svga_query
);
678 /* Allocate an integer ID for the query */
679 sq
->id
= util_bitmask_add(svga
->query_id_bm
);
680 if (sq
->id
== UTIL_BITMASK_INVALID_INDEX
)
683 SVGA_DBG(DEBUG_QUERY
, "%s type=%d sq=0x%x id=%d\n", __FUNCTION__
,
684 query_type
, sq
, sq
->id
);
686 switch (query_type
) {
687 case PIPE_QUERY_OCCLUSION_COUNTER
:
688 sq
->svga_type
= SVGA3D_QUERYTYPE_OCCLUSION
;
689 if (svga_have_vgpu10(svga
)) {
690 define_query_vgpu10(svga
, sq
, sizeof(SVGADXOcclusionQueryResult
));
693 * In OpenGL, occlusion counter query can be used in conditional
694 * rendering; however, in DX10, only OCCLUSION_PREDICATE query can
695 * be used for predication. Hence, we need to create an occlusion
696 * predicate query along with the occlusion counter query. So when
697 * the occlusion counter query is used for predication, the associated
698 * query of occlusion predicate type will be used
699 * in the SetPredication command.
701 sq
->predicate
= svga_create_query(pipe
, PIPE_QUERY_OCCLUSION_PREDICATE
, index
);
704 define_query_vgpu9(svga
, sq
);
707 case PIPE_QUERY_OCCLUSION_PREDICATE
:
708 if (svga_have_vgpu10(svga
)) {
709 sq
->svga_type
= SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE
;
710 define_query_vgpu10(svga
, sq
, sizeof(SVGADXOcclusionPredicateQueryResult
));
712 sq
->svga_type
= SVGA3D_QUERYTYPE_OCCLUSION
;
713 define_query_vgpu9(svga
, sq
);
716 case PIPE_QUERY_PRIMITIVES_GENERATED
:
717 case PIPE_QUERY_PRIMITIVES_EMITTED
:
718 case PIPE_QUERY_SO_STATISTICS
:
719 assert(svga_have_vgpu10(svga
));
720 sq
->svga_type
= SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS
;
721 define_query_vgpu10(svga
, sq
,
722 sizeof(SVGADXStreamOutStatisticsQueryResult
));
724 case PIPE_QUERY_TIMESTAMP
:
725 assert(svga_have_vgpu10(svga
));
726 sq
->svga_type
= SVGA3D_QUERYTYPE_TIMESTAMP
;
727 define_query_vgpu10(svga
, sq
,
728 sizeof(SVGADXTimestampQueryResult
));
730 case SVGA_QUERY_NUM_DRAW_CALLS
:
731 case SVGA_QUERY_NUM_FALLBACKS
:
732 case SVGA_QUERY_NUM_FLUSHES
:
733 case SVGA_QUERY_NUM_VALIDATIONS
:
734 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
735 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
736 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
737 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
738 case SVGA_QUERY_MEMORY_USED
:
739 case SVGA_QUERY_NUM_SHADERS
:
740 case SVGA_QUERY_NUM_RESOURCES
:
741 case SVGA_QUERY_NUM_STATE_OBJECTS
:
742 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
743 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
744 case SVGA_QUERY_NUM_READBACKS
:
745 case SVGA_QUERY_NUM_RESOURCE_UPDATES
:
746 case SVGA_QUERY_NUM_BUFFER_UPLOADS
:
747 case SVGA_QUERY_NUM_CONST_BUF_UPDATES
:
748 case SVGA_QUERY_NUM_CONST_UPDATES
:
750 case SVGA_QUERY_FLUSH_TIME
:
751 case SVGA_QUERY_MAP_BUFFER_TIME
:
752 /* These queries need os_time_get() */
753 svga
->hud
.uses_time
= TRUE
;
756 assert(!"unexpected query type in svga_create_query()");
759 sq
->type
= query_type
;
769 svga_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
771 struct svga_context
*svga
= svga_context(pipe
);
772 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
773 struct svga_query
*sq
;
776 destroy_gb_query_obj(svga
);
782 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d\n", __FUNCTION__
,
786 case PIPE_QUERY_OCCLUSION_COUNTER
:
787 case PIPE_QUERY_OCCLUSION_PREDICATE
:
788 if (svga_have_vgpu10(svga
)) {
789 /* make sure to also destroy any associated predicate query */
791 svga_destroy_query(pipe
, sq
->predicate
);
792 destroy_query_vgpu10(svga
, sq
);
794 sws
->buffer_destroy(sws
, sq
->hwbuf
);
796 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
798 case PIPE_QUERY_PRIMITIVES_GENERATED
:
799 case PIPE_QUERY_PRIMITIVES_EMITTED
:
800 case PIPE_QUERY_SO_STATISTICS
:
801 case PIPE_QUERY_TIMESTAMP
:
802 assert(svga_have_vgpu10(svga
));
803 destroy_query_vgpu10(svga
, sq
);
804 sws
->fence_reference(sws
, &sq
->fence
, NULL
);
806 case SVGA_QUERY_NUM_DRAW_CALLS
:
807 case SVGA_QUERY_NUM_FALLBACKS
:
808 case SVGA_QUERY_NUM_FLUSHES
:
809 case SVGA_QUERY_NUM_VALIDATIONS
:
810 case SVGA_QUERY_MAP_BUFFER_TIME
:
811 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
812 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
813 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
814 case SVGA_QUERY_FLUSH_TIME
:
815 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
816 case SVGA_QUERY_MEMORY_USED
:
817 case SVGA_QUERY_NUM_SHADERS
:
818 case SVGA_QUERY_NUM_RESOURCES
:
819 case SVGA_QUERY_NUM_STATE_OBJECTS
:
820 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
821 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
822 case SVGA_QUERY_NUM_READBACKS
:
823 case SVGA_QUERY_NUM_RESOURCE_UPDATES
:
824 case SVGA_QUERY_NUM_BUFFER_UPLOADS
:
825 case SVGA_QUERY_NUM_CONST_BUF_UPDATES
:
826 case SVGA_QUERY_NUM_CONST_UPDATES
:
830 assert(!"svga: unexpected query type in svga_destroy_query()");
833 /* Free the query id */
834 util_bitmask_clear(svga
->query_id_bm
, sq
->id
);
841 svga_begin_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
843 struct svga_context
*svga
= svga_context(pipe
);
844 struct svga_query
*sq
= svga_query(q
);
848 assert(sq
->type
< SVGA_QUERY_MAX
);
850 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d\n", __FUNCTION__
,
853 /* Need to flush out buffered drawing commands so that they don't
854 * get counted in the query results.
856 svga_hwtnl_flush_retry(svga
);
859 case PIPE_QUERY_OCCLUSION_COUNTER
:
860 case PIPE_QUERY_OCCLUSION_PREDICATE
:
861 if (svga_have_vgpu10(svga
)) {
862 ret
= begin_query_vgpu10(svga
, sq
);
863 /* also need to start the associated occlusion predicate query */
865 enum pipe_error status
;
866 status
= begin_query_vgpu10(svga
, svga_query(sq
->predicate
));
867 assert(status
== PIPE_OK
);
871 ret
= begin_query_vgpu9(svga
, sq
);
873 assert(ret
== PIPE_OK
);
876 case PIPE_QUERY_PRIMITIVES_GENERATED
:
877 case PIPE_QUERY_PRIMITIVES_EMITTED
:
878 case PIPE_QUERY_SO_STATISTICS
:
879 case PIPE_QUERY_TIMESTAMP
:
880 assert(svga_have_vgpu10(svga
));
881 ret
= begin_query_vgpu10(svga
, sq
);
882 assert(ret
== PIPE_OK
);
884 case SVGA_QUERY_NUM_DRAW_CALLS
:
885 sq
->begin_count
= svga
->hud
.num_draw_calls
;
887 case SVGA_QUERY_NUM_FALLBACKS
:
888 sq
->begin_count
= svga
->hud
.num_fallbacks
;
890 case SVGA_QUERY_NUM_FLUSHES
:
891 sq
->begin_count
= svga
->hud
.num_flushes
;
893 case SVGA_QUERY_NUM_VALIDATIONS
:
894 sq
->begin_count
= svga
->hud
.num_validations
;
896 case SVGA_QUERY_MAP_BUFFER_TIME
:
897 sq
->begin_count
= svga
->hud
.map_buffer_time
;
899 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
900 sq
->begin_count
= svga
->hud
.num_resources_mapped
;
902 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
903 sq
->begin_count
= svga
->hud
.num_bytes_uploaded
;
905 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
906 sq
->begin_count
= svga
->hud
.command_buffer_size
;
908 case SVGA_QUERY_FLUSH_TIME
:
909 sq
->begin_count
= svga
->hud
.flush_time
;
911 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
912 sq
->begin_count
= svga
->hud
.surface_write_flushes
;
914 case SVGA_QUERY_NUM_READBACKS
:
915 sq
->begin_count
= svga
->hud
.num_readbacks
;
917 case SVGA_QUERY_NUM_RESOURCE_UPDATES
:
918 sq
->begin_count
= svga
->hud
.num_resource_updates
;
920 case SVGA_QUERY_NUM_BUFFER_UPLOADS
:
921 sq
->begin_count
= svga
->hud
.num_buffer_uploads
;
923 case SVGA_QUERY_NUM_CONST_BUF_UPDATES
:
924 sq
->begin_count
= svga
->hud
.num_const_buf_updates
;
926 case SVGA_QUERY_NUM_CONST_UPDATES
:
927 sq
->begin_count
= svga
->hud
.num_const_updates
;
929 case SVGA_QUERY_MEMORY_USED
:
930 case SVGA_QUERY_NUM_SHADERS
:
931 case SVGA_QUERY_NUM_RESOURCES
:
932 case SVGA_QUERY_NUM_STATE_OBJECTS
:
933 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
934 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
938 assert(!"unexpected query type in svga_begin_query()");
941 svga
->sq
[sq
->type
] = sq
;
948 svga_end_query(struct pipe_context
*pipe
, struct pipe_query
*q
)
950 struct svga_context
*svga
= svga_context(pipe
);
951 struct svga_query
*sq
= svga_query(q
);
955 assert(sq
->type
< SVGA_QUERY_MAX
);
957 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d\n", __FUNCTION__
,
960 if (sq
->type
== PIPE_QUERY_TIMESTAMP
&& svga
->sq
[sq
->type
] != sq
)
961 svga_begin_query(pipe
, q
);
963 svga_hwtnl_flush_retry(svga
);
965 assert(svga
->sq
[sq
->type
] == sq
);
968 case PIPE_QUERY_OCCLUSION_COUNTER
:
969 case PIPE_QUERY_OCCLUSION_PREDICATE
:
970 if (svga_have_vgpu10(svga
)) {
971 ret
= end_query_vgpu10(svga
, sq
);
972 /* also need to end the associated occlusion predicate query */
974 enum pipe_error status
;
975 status
= end_query_vgpu10(svga
, svga_query(sq
->predicate
));
976 assert(status
== PIPE_OK
);
980 ret
= end_query_vgpu9(svga
, sq
);
982 assert(ret
== PIPE_OK
);
984 /* TODO: Delay flushing. We don't really need to flush here, just ensure
985 * that there is one flush before svga_get_query_result attempts to get
988 svga_context_flush(svga
, NULL
);
990 case PIPE_QUERY_PRIMITIVES_GENERATED
:
991 case PIPE_QUERY_PRIMITIVES_EMITTED
:
992 case PIPE_QUERY_SO_STATISTICS
:
993 case PIPE_QUERY_TIMESTAMP
:
994 assert(svga_have_vgpu10(svga
));
995 ret
= end_query_vgpu10(svga
, sq
);
996 assert(ret
== PIPE_OK
);
998 case SVGA_QUERY_NUM_DRAW_CALLS
:
999 sq
->end_count
= svga
->hud
.num_draw_calls
;
1001 case SVGA_QUERY_NUM_FALLBACKS
:
1002 sq
->end_count
= svga
->hud
.num_fallbacks
;
1004 case SVGA_QUERY_NUM_FLUSHES
:
1005 sq
->end_count
= svga
->hud
.num_flushes
;
1007 case SVGA_QUERY_NUM_VALIDATIONS
:
1008 sq
->end_count
= svga
->hud
.num_validations
;
1010 case SVGA_QUERY_MAP_BUFFER_TIME
:
1011 sq
->end_count
= svga
->hud
.map_buffer_time
;
1013 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
1014 sq
->end_count
= svga
->hud
.num_resources_mapped
;
1016 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
1017 sq
->end_count
= svga
->hud
.num_bytes_uploaded
;
1019 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
1020 sq
->end_count
= svga
->hud
.command_buffer_size
;
1022 case SVGA_QUERY_FLUSH_TIME
:
1023 sq
->end_count
= svga
->hud
.flush_time
;
1025 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
1026 sq
->end_count
= svga
->hud
.surface_write_flushes
;
1028 case SVGA_QUERY_NUM_READBACKS
:
1029 sq
->end_count
= svga
->hud
.num_readbacks
;
1031 case SVGA_QUERY_NUM_RESOURCE_UPDATES
:
1032 sq
->end_count
= svga
->hud
.num_resource_updates
;
1034 case SVGA_QUERY_NUM_BUFFER_UPLOADS
:
1035 sq
->end_count
= svga
->hud
.num_buffer_uploads
;
1037 case SVGA_QUERY_NUM_CONST_BUF_UPDATES
:
1038 sq
->end_count
= svga
->hud
.num_const_buf_updates
;
1040 case SVGA_QUERY_NUM_CONST_UPDATES
:
1041 sq
->end_count
= svga
->hud
.num_const_updates
;
1043 case SVGA_QUERY_MEMORY_USED
:
1044 case SVGA_QUERY_NUM_SHADERS
:
1045 case SVGA_QUERY_NUM_RESOURCES
:
1046 case SVGA_QUERY_NUM_STATE_OBJECTS
:
1047 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
1048 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
1052 assert(!"unexpected query type in svga_end_query()");
1054 svga
->sq
[sq
->type
] = NULL
;
1060 svga_get_query_result(struct pipe_context
*pipe
,
1061 struct pipe_query
*q
,
1063 union pipe_query_result
*vresult
)
1065 struct svga_screen
*svgascreen
= svga_screen(pipe
->screen
);
1066 struct svga_context
*svga
= svga_context(pipe
);
1067 struct svga_query
*sq
= svga_query(q
);
1068 uint64_t *result
= (uint64_t *)vresult
;
1073 SVGA_DBG(DEBUG_QUERY
, "%s sq=0x%x id=%d wait: %d\n",
1074 __FUNCTION__
, sq
, sq
->id
, wait
);
1077 case PIPE_QUERY_OCCLUSION_COUNTER
:
1078 if (svga_have_vgpu10(svga
)) {
1079 SVGADXOcclusionQueryResult occResult
;
1080 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1081 (void *)&occResult
, sizeof(occResult
));
1082 *result
= (uint64_t)occResult
.samplesRendered
;
1084 ret
= get_query_result_vgpu9(svga
, sq
, wait
, result
);
1087 case PIPE_QUERY_OCCLUSION_PREDICATE
: {
1088 if (svga_have_vgpu10(svga
)) {
1089 SVGADXOcclusionPredicateQueryResult occResult
;
1090 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1091 (void *)&occResult
, sizeof(occResult
));
1092 vresult
->b
= occResult
.anySamplesRendered
!= 0;
1095 ret
= get_query_result_vgpu9(svga
, sq
, wait
, &count
);
1096 vresult
->b
= count
!= 0;
1100 case PIPE_QUERY_SO_STATISTICS
: {
1101 SVGADXStreamOutStatisticsQueryResult sResult
;
1102 struct pipe_query_data_so_statistics
*pResult
=
1103 (struct pipe_query_data_so_statistics
*)vresult
;
1105 assert(svga_have_vgpu10(svga
));
1106 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1107 (void *)&sResult
, sizeof(sResult
));
1108 pResult
->num_primitives_written
= sResult
.numPrimitivesWritten
;
1109 pResult
->primitives_storage_needed
= sResult
.numPrimitivesRequired
;
1112 case PIPE_QUERY_TIMESTAMP
: {
1113 SVGADXTimestampQueryResult sResult
;
1115 assert(svga_have_vgpu10(svga
));
1116 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1117 (void *)&sResult
, sizeof(sResult
));
1118 *result
= (uint64_t)sResult
.timestamp
;
1121 case PIPE_QUERY_PRIMITIVES_GENERATED
: {
1122 SVGADXStreamOutStatisticsQueryResult sResult
;
1124 assert(svga_have_vgpu10(svga
));
1125 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1126 (void *)&sResult
, sizeof sResult
);
1127 *result
= (uint64_t)sResult
.numPrimitivesRequired
;
1130 case PIPE_QUERY_PRIMITIVES_EMITTED
: {
1131 SVGADXStreamOutStatisticsQueryResult sResult
;
1133 assert(svga_have_vgpu10(svga
));
1134 ret
= get_query_result_vgpu10(svga
, sq
, wait
,
1135 (void *)&sResult
, sizeof sResult
);
1136 *result
= (uint64_t)sResult
.numPrimitivesWritten
;
1139 /* These are per-frame counters */
1140 case SVGA_QUERY_NUM_DRAW_CALLS
:
1141 case SVGA_QUERY_NUM_FALLBACKS
:
1142 case SVGA_QUERY_NUM_FLUSHES
:
1143 case SVGA_QUERY_NUM_VALIDATIONS
:
1144 case SVGA_QUERY_MAP_BUFFER_TIME
:
1145 case SVGA_QUERY_NUM_RESOURCES_MAPPED
:
1146 case SVGA_QUERY_NUM_BYTES_UPLOADED
:
1147 case SVGA_QUERY_COMMAND_BUFFER_SIZE
:
1148 case SVGA_QUERY_FLUSH_TIME
:
1149 case SVGA_QUERY_SURFACE_WRITE_FLUSHES
:
1150 case SVGA_QUERY_NUM_READBACKS
:
1151 case SVGA_QUERY_NUM_RESOURCE_UPDATES
:
1152 case SVGA_QUERY_NUM_BUFFER_UPLOADS
:
1153 case SVGA_QUERY_NUM_CONST_BUF_UPDATES
:
1154 case SVGA_QUERY_NUM_CONST_UPDATES
:
1155 vresult
->u64
= sq
->end_count
- sq
->begin_count
;
1157 /* These are running total counters */
1158 case SVGA_QUERY_MEMORY_USED
:
1159 vresult
->u64
= svgascreen
->hud
.total_resource_bytes
;
1161 case SVGA_QUERY_NUM_SHADERS
:
1162 vresult
->u64
= svga
->hud
.num_shaders
;
1164 case SVGA_QUERY_NUM_RESOURCES
:
1165 vresult
->u64
= svgascreen
->hud
.num_resources
;
1167 case SVGA_QUERY_NUM_STATE_OBJECTS
:
1168 vresult
->u64
= (svga
->hud
.num_blend_objects
+
1169 svga
->hud
.num_depthstencil_objects
+
1170 svga
->hud
.num_rasterizer_objects
+
1171 svga
->hud
.num_sampler_objects
+
1172 svga
->hud
.num_samplerview_objects
+
1173 svga
->hud
.num_vertexelement_objects
);
1175 case SVGA_QUERY_NUM_SURFACE_VIEWS
:
1176 vresult
->u64
= svga
->hud
.num_surface_views
;
1178 case SVGA_QUERY_NUM_GENERATE_MIPMAP
:
1179 vresult
->u64
= svga
->hud
.num_generate_mipmap
;
1182 assert(!"unexpected query type in svga_get_query_result");
1185 SVGA_DBG(DEBUG_QUERY
, "%s result %d\n", __FUNCTION__
, *((uint64_t *)vresult
));
1191 svga_render_condition(struct pipe_context
*pipe
, struct pipe_query
*q
,
1192 boolean condition
, uint mode
)
1194 struct svga_context
*svga
= svga_context(pipe
);
1195 struct svga_winsys_screen
*sws
= svga_screen(svga
->pipe
.screen
)->sws
;
1196 struct svga_query
*sq
= svga_query(q
);
1197 SVGA3dQueryId queryId
;
1198 enum pipe_error ret
;
1200 SVGA_DBG(DEBUG_QUERY
, "%s\n", __FUNCTION__
);
1202 assert(svga_have_vgpu10(svga
));
1204 queryId
= SVGA3D_INVALID_ID
;
1207 assert(sq
->svga_type
== SVGA3D_QUERYTYPE_OCCLUSION
||
1208 sq
->svga_type
== SVGA3D_QUERYTYPE_OCCLUSIONPREDICATE
);
1210 if (sq
->svga_type
== SVGA3D_QUERYTYPE_OCCLUSION
) {
1211 assert(sq
->predicate
);
1213 * For conditional rendering, make sure to use the associated
1216 sq
= svga_query(sq
->predicate
);
1220 if ((mode
== PIPE_RENDER_COND_WAIT
||
1221 mode
== PIPE_RENDER_COND_BY_REGION_WAIT
) && sq
->fence
) {
1222 sws
->fence_finish(sws
, sq
->fence
, SVGA_FENCE_FLAG_QUERY
);
1226 * if the kernel module doesn't support the predication command,
1227 * we'll just render unconditionally.
1228 * This is probably acceptable for the typical case of occlusion culling.
1230 if (sws
->have_set_predication_cmd
) {
1231 ret
= SVGA3D_vgpu10_SetPredication(svga
->swc
, queryId
,
1232 (uint32
) condition
);
1233 if (ret
!= PIPE_OK
) {
1234 svga_context_flush(svga
, NULL
);
1235 ret
= SVGA3D_vgpu10_SetPredication(svga
->swc
, queryId
,
1236 (uint32
) condition
);
1243 * This function is a workaround because we lack the ability to query
1244 * renderer's time synchornously.
1247 svga_get_timestamp(struct pipe_context
*pipe
)
1249 struct pipe_query
*q
= svga_create_query(pipe
, PIPE_QUERY_TIMESTAMP
, 0);
1250 union pipe_query_result result
;
1252 svga_begin_query(pipe
, q
);
1253 svga_end_query(pipe
,q
);
1254 svga_get_query_result(pipe
, q
, TRUE
, &result
);
1255 svga_destroy_query(pipe
, q
);
1262 svga_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
1268 svga_init_query_functions(struct svga_context
*svga
)
1270 svga
->pipe
.create_query
= svga_create_query
;
1271 svga
->pipe
.destroy_query
= svga_destroy_query
;
1272 svga
->pipe
.begin_query
= svga_begin_query
;
1273 svga
->pipe
.end_query
= svga_end_query
;
1274 svga
->pipe
.get_query_result
= svga_get_query_result
;
1275 svga
->pipe
.set_active_query_state
= svga_set_active_query_state
;
1276 svga
->pipe
.render_condition
= svga_render_condition
;
1277 svga
->pipe
.get_timestamp
= svga_get_timestamp
;