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