• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 synchronously.
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