xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_query.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
5*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
6*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
7*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
9*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  *
23*61046927SAndroid Build Coastguard Worker  * 'pvr_write_query_to_buffer()' and 'pvr_wait_for_available()' based on anv:
24*61046927SAndroid Build Coastguard Worker  * Copyright © 2015 Intel Corporation
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include <assert.h>
28*61046927SAndroid Build Coastguard Worker #include <stddef.h>
29*61046927SAndroid Build Coastguard Worker #include <stdint.h>
30*61046927SAndroid Build Coastguard Worker #include <string.h>
31*61046927SAndroid Build Coastguard Worker #include <vulkan/vulkan.h>
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "pvr_bo.h"
34*61046927SAndroid Build Coastguard Worker #include "pvr_csb.h"
35*61046927SAndroid Build Coastguard Worker #include "pvr_device_info.h"
36*61046927SAndroid Build Coastguard Worker #include "pvr_private.h"
37*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
38*61046927SAndroid Build Coastguard Worker #include "util/os_time.h"
39*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
40*61046927SAndroid Build Coastguard Worker #include "vk_object.h"
41*61046927SAndroid Build Coastguard Worker 
pvr_CreateQueryPool(VkDevice _device,const VkQueryPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkQueryPool * pQueryPool)42*61046927SAndroid Build Coastguard Worker VkResult pvr_CreateQueryPool(VkDevice _device,
43*61046927SAndroid Build Coastguard Worker                              const VkQueryPoolCreateInfo *pCreateInfo,
44*61046927SAndroid Build Coastguard Worker                              const VkAllocationCallbacks *pAllocator,
45*61046927SAndroid Build Coastguard Worker                              VkQueryPool *pQueryPool)
46*61046927SAndroid Build Coastguard Worker {
47*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
48*61046927SAndroid Build Coastguard Worker    const uint32_t core_count = device->pdevice->dev_runtime_info.core_count;
49*61046927SAndroid Build Coastguard Worker    const uint32_t query_size = pCreateInfo->queryCount * sizeof(uint32_t);
50*61046927SAndroid Build Coastguard Worker    struct pvr_query_pool *pool;
51*61046927SAndroid Build Coastguard Worker    uint64_t alloc_size;
52*61046927SAndroid Build Coastguard Worker    VkResult result;
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker    /* Vulkan 1.0 supports only occlusion, timestamp, and pipeline statistics
55*61046927SAndroid Build Coastguard Worker     * query.
56*61046927SAndroid Build Coastguard Worker     * We don't currently support timestamp queries.
57*61046927SAndroid Build Coastguard Worker     * VkQueueFamilyProperties->timestampValidBits = 0.
58*61046927SAndroid Build Coastguard Worker     * We don't currently support pipeline statistics queries.
59*61046927SAndroid Build Coastguard Worker     * VkPhysicalDeviceFeatures->pipelineStatisticsQuery = false.
60*61046927SAndroid Build Coastguard Worker     */
61*61046927SAndroid Build Coastguard Worker    assert(!device->vk.enabled_features.pipelineStatisticsQuery);
62*61046927SAndroid Build Coastguard Worker    assert(pCreateInfo->queryType == VK_QUERY_TYPE_OCCLUSION);
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker    pool = vk_object_alloc(&device->vk,
65*61046927SAndroid Build Coastguard Worker                           pAllocator,
66*61046927SAndroid Build Coastguard Worker                           sizeof(*pool),
67*61046927SAndroid Build Coastguard Worker                           VK_OBJECT_TYPE_QUERY_POOL);
68*61046927SAndroid Build Coastguard Worker    if (!pool)
69*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker    pool->result_stride =
72*61046927SAndroid Build Coastguard Worker       ALIGN_POT(query_size, PVRX(CR_ISP_OCLQRY_BASE_ADDR_ALIGNMENT));
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    pool->query_count = pCreateInfo->queryCount;
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker    /* Each Phantom writes to a separate offset within the vis test heap so
77*61046927SAndroid Build Coastguard Worker     * allocate space for the total number of Phantoms.
78*61046927SAndroid Build Coastguard Worker     */
79*61046927SAndroid Build Coastguard Worker    alloc_size = (uint64_t)pool->result_stride * core_count;
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker    result = pvr_bo_suballoc(&device->suballoc_vis_test,
82*61046927SAndroid Build Coastguard Worker                             alloc_size,
83*61046927SAndroid Build Coastguard Worker                             PVRX(CR_ISP_OCLQRY_BASE_ADDR_ALIGNMENT),
84*61046927SAndroid Build Coastguard Worker                             false,
85*61046927SAndroid Build Coastguard Worker                             &pool->result_buffer);
86*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
87*61046927SAndroid Build Coastguard Worker       goto err_free_pool;
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    result = pvr_bo_suballoc(&device->suballoc_general,
90*61046927SAndroid Build Coastguard Worker                             query_size,
91*61046927SAndroid Build Coastguard Worker                             sizeof(uint32_t),
92*61046927SAndroid Build Coastguard Worker                             false,
93*61046927SAndroid Build Coastguard Worker                             &pool->availability_buffer);
94*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
95*61046927SAndroid Build Coastguard Worker       goto err_free_result_buffer;
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    *pQueryPool = pvr_query_pool_to_handle(pool);
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker err_free_result_buffer:
102*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(pool->result_buffer);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker err_free_pool:
105*61046927SAndroid Build Coastguard Worker    vk_object_free(&device->vk, pAllocator, pool);
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    return result;
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker 
pvr_DestroyQueryPool(VkDevice _device,VkQueryPool queryPool,const VkAllocationCallbacks * pAllocator)110*61046927SAndroid Build Coastguard Worker void pvr_DestroyQueryPool(VkDevice _device,
111*61046927SAndroid Build Coastguard Worker                           VkQueryPool queryPool,
112*61046927SAndroid Build Coastguard Worker                           const VkAllocationCallbacks *pAllocator)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_query_pool, pool, queryPool);
115*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    if (!pool)
118*61046927SAndroid Build Coastguard Worker       return;
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(pool->availability_buffer);
121*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(pool->result_buffer);
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker    vk_object_free(&device->vk, pAllocator, pool);
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker /* Note: make sure to make the availability buffer's memory defined in
127*61046927SAndroid Build Coastguard Worker  * accordance to how the device is expected to fill it. We don't make it defined
128*61046927SAndroid Build Coastguard Worker  * here since that would cover up usage of this function while the underlying
129*61046927SAndroid Build Coastguard Worker  * buffer region being accessed wasn't expect to have been written by the
130*61046927SAndroid Build Coastguard Worker  * device.
131*61046927SAndroid Build Coastguard Worker  */
pvr_query_is_available(const struct pvr_query_pool * pool,uint32_t query_idx)132*61046927SAndroid Build Coastguard Worker static inline bool pvr_query_is_available(const struct pvr_query_pool *pool,
133*61046927SAndroid Build Coastguard Worker                                           uint32_t query_idx)
134*61046927SAndroid Build Coastguard Worker {
135*61046927SAndroid Build Coastguard Worker    volatile uint32_t *available =
136*61046927SAndroid Build Coastguard Worker       pvr_bo_suballoc_get_map_addr(pool->availability_buffer);
137*61046927SAndroid Build Coastguard Worker    return !!available[query_idx];
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker #define NSEC_PER_SEC UINT64_C(1000000000)
141*61046927SAndroid Build Coastguard Worker #define PVR_WAIT_TIMEOUT UINT64_C(5)
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker /* Note: make sure to make the availability buffer's memory defined in
144*61046927SAndroid Build Coastguard Worker  * accordance to how the device is expected to fill it. We don't make it defined
145*61046927SAndroid Build Coastguard Worker  * here since that would cover up usage of this function while the underlying
146*61046927SAndroid Build Coastguard Worker  * buffer region being accessed wasn't expect to have been written by the
147*61046927SAndroid Build Coastguard Worker  * device.
148*61046927SAndroid Build Coastguard Worker  */
149*61046927SAndroid Build Coastguard Worker /* TODO: Handle device loss scenario properly. */
pvr_wait_for_available(struct pvr_device * device,const struct pvr_query_pool * pool,uint32_t query_idx)150*61046927SAndroid Build Coastguard Worker static VkResult pvr_wait_for_available(struct pvr_device *device,
151*61046927SAndroid Build Coastguard Worker                                        const struct pvr_query_pool *pool,
152*61046927SAndroid Build Coastguard Worker                                        uint32_t query_idx)
153*61046927SAndroid Build Coastguard Worker {
154*61046927SAndroid Build Coastguard Worker    const uint64_t abs_timeout =
155*61046927SAndroid Build Coastguard Worker       os_time_get_absolute_timeout(PVR_WAIT_TIMEOUT * NSEC_PER_SEC);
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.0 spec:
158*61046927SAndroid Build Coastguard Worker     *
159*61046927SAndroid Build Coastguard Worker     *    Commands that wait indefinitely for device execution (namely
160*61046927SAndroid Build Coastguard Worker     *    vkDeviceWaitIdle, vkQueueWaitIdle, vkWaitForFences or
161*61046927SAndroid Build Coastguard Worker     *    vkAcquireNextImageKHR with a maximum timeout, and
162*61046927SAndroid Build Coastguard Worker     *    vkGetQueryPoolResults with the VK_QUERY_RESULT_WAIT_BIT bit set in
163*61046927SAndroid Build Coastguard Worker     *    flags) must return in finite time even in the case of a lost device,
164*61046927SAndroid Build Coastguard Worker     *    and return either VK_SUCCESS or VK_ERROR_DEVICE_LOST.
165*61046927SAndroid Build Coastguard Worker     */
166*61046927SAndroid Build Coastguard Worker    while (os_time_get_nano() < abs_timeout) {
167*61046927SAndroid Build Coastguard Worker       if (pvr_query_is_available(pool, query_idx) != 0)
168*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    return vk_error(device, VK_ERROR_DEVICE_LOST);
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker #undef NSEC_PER_SEC
175*61046927SAndroid Build Coastguard Worker #undef PVR_WAIT_TIMEOUT
176*61046927SAndroid Build Coastguard Worker 
pvr_write_query_to_buffer(uint8_t * buffer,VkQueryResultFlags flags,uint32_t idx,uint64_t value)177*61046927SAndroid Build Coastguard Worker static inline void pvr_write_query_to_buffer(uint8_t *buffer,
178*61046927SAndroid Build Coastguard Worker                                              VkQueryResultFlags flags,
179*61046927SAndroid Build Coastguard Worker                                              uint32_t idx,
180*61046927SAndroid Build Coastguard Worker                                              uint64_t value)
181*61046927SAndroid Build Coastguard Worker {
182*61046927SAndroid Build Coastguard Worker    if (flags & VK_QUERY_RESULT_64_BIT) {
183*61046927SAndroid Build Coastguard Worker       uint64_t *query_data = (uint64_t *)buffer;
184*61046927SAndroid Build Coastguard Worker       query_data[idx] = value;
185*61046927SAndroid Build Coastguard Worker    } else {
186*61046927SAndroid Build Coastguard Worker       uint32_t *query_data = (uint32_t *)buffer;
187*61046927SAndroid Build Coastguard Worker       query_data[idx] = value;
188*61046927SAndroid Build Coastguard Worker    }
189*61046927SAndroid Build Coastguard Worker }
190*61046927SAndroid Build Coastguard Worker 
pvr_GetQueryPoolResults(VkDevice _device,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount,size_t dataSize,void * pData,VkDeviceSize stride,VkQueryResultFlags flags)191*61046927SAndroid Build Coastguard Worker VkResult pvr_GetQueryPoolResults(VkDevice _device,
192*61046927SAndroid Build Coastguard Worker                                  VkQueryPool queryPool,
193*61046927SAndroid Build Coastguard Worker                                  uint32_t firstQuery,
194*61046927SAndroid Build Coastguard Worker                                  uint32_t queryCount,
195*61046927SAndroid Build Coastguard Worker                                  size_t dataSize,
196*61046927SAndroid Build Coastguard Worker                                  void *pData,
197*61046927SAndroid Build Coastguard Worker                                  VkDeviceSize stride,
198*61046927SAndroid Build Coastguard Worker                                  VkQueryResultFlags flags)
199*61046927SAndroid Build Coastguard Worker {
200*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_query_pool, pool, queryPool);
201*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
202*61046927SAndroid Build Coastguard Worker    VG(volatile uint32_t *available =
203*61046927SAndroid Build Coastguard Worker          pvr_bo_suballoc_get_map_addr(pool->availability_buffer));
204*61046927SAndroid Build Coastguard Worker    volatile uint32_t *query_results =
205*61046927SAndroid Build Coastguard Worker       pvr_bo_suballoc_get_map_addr(pool->result_buffer);
206*61046927SAndroid Build Coastguard Worker    const uint32_t core_count = device->pdevice->dev_runtime_info.core_count;
207*61046927SAndroid Build Coastguard Worker    uint8_t *data = (uint8_t *)pData;
208*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    /* TODO: Instead of making the memory defined here for valgrind, to better
211*61046927SAndroid Build Coastguard Worker     * catch out of bounds access and other memory errors we should move them
212*61046927SAndroid Build Coastguard Worker     * where where the query buffers are changed by the driver or device (e.g.
213*61046927SAndroid Build Coastguard Worker     * "vkCmdResetQueryPool()", "vkGetQueryPoolResults()", etc.).
214*61046927SAndroid Build Coastguard Worker     */
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    VG(VALGRIND_MAKE_MEM_DEFINED(&available[firstQuery],
217*61046927SAndroid Build Coastguard Worker                                 queryCount * sizeof(uint32_t)));
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < core_count; i++) {
220*61046927SAndroid Build Coastguard Worker       VG(VALGRIND_MAKE_MEM_DEFINED(
221*61046927SAndroid Build Coastguard Worker          &query_results[firstQuery + i * pool->result_stride],
222*61046927SAndroid Build Coastguard Worker          queryCount * sizeof(uint32_t)));
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < queryCount; i++) {
226*61046927SAndroid Build Coastguard Worker       bool is_available = pvr_query_is_available(pool, firstQuery + i);
227*61046927SAndroid Build Coastguard Worker       uint64_t count = 0;
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker       if (flags & VK_QUERY_RESULT_WAIT_BIT && !is_available) {
230*61046927SAndroid Build Coastguard Worker          result = pvr_wait_for_available(device, pool, firstQuery + i);
231*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
232*61046927SAndroid Build Coastguard Worker             return result;
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker          is_available = true;
235*61046927SAndroid Build Coastguard Worker       }
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < core_count; j++)
238*61046927SAndroid Build Coastguard Worker          count += query_results[pool->result_stride * j + firstQuery + i];
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker       if (is_available || (flags & VK_QUERY_RESULT_PARTIAL_BIT))
241*61046927SAndroid Build Coastguard Worker          pvr_write_query_to_buffer(data, flags, 0, count);
242*61046927SAndroid Build Coastguard Worker       else
243*61046927SAndroid Build Coastguard Worker          result = VK_NOT_READY;
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker       if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
246*61046927SAndroid Build Coastguard Worker          pvr_write_query_to_buffer(data, flags, 1, is_available);
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker       data += stride;
249*61046927SAndroid Build Coastguard Worker    }
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    VG(VALGRIND_MAKE_MEM_UNDEFINED(&available[firstQuery],
252*61046927SAndroid Build Coastguard Worker                                   queryCount * sizeof(uint32_t)));
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < core_count; i++) {
255*61046927SAndroid Build Coastguard Worker       VG(VALGRIND_MAKE_MEM_UNDEFINED(
256*61046927SAndroid Build Coastguard Worker          &query_results[firstQuery + i * pool->result_stride],
257*61046927SAndroid Build Coastguard Worker          queryCount * sizeof(uint32_t)));
258*61046927SAndroid Build Coastguard Worker    }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    return result;
261*61046927SAndroid Build Coastguard Worker }
262*61046927SAndroid Build Coastguard Worker 
pvr_CmdResetQueryPool(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount)263*61046927SAndroid Build Coastguard Worker void pvr_CmdResetQueryPool(VkCommandBuffer commandBuffer,
264*61046927SAndroid Build Coastguard Worker                            VkQueryPool queryPool,
265*61046927SAndroid Build Coastguard Worker                            uint32_t firstQuery,
266*61046927SAndroid Build Coastguard Worker                            uint32_t queryCount)
267*61046927SAndroid Build Coastguard Worker {
268*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer);
269*61046927SAndroid Build Coastguard Worker    struct pvr_query_info query_info;
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker    PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer);
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    query_info.type = PVR_QUERY_TYPE_RESET_QUERY_POOL;
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    query_info.reset_query_pool.query_pool = queryPool;
276*61046927SAndroid Build Coastguard Worker    query_info.reset_query_pool.first_query = firstQuery;
277*61046927SAndroid Build Coastguard Worker    query_info.reset_query_pool.query_count = queryCount;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    pvr_add_query_program(cmd_buffer, &query_info);
280*61046927SAndroid Build Coastguard Worker }
281*61046927SAndroid Build Coastguard Worker 
pvr_ResetQueryPool(VkDevice _device,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount)282*61046927SAndroid Build Coastguard Worker void pvr_ResetQueryPool(VkDevice _device,
283*61046927SAndroid Build Coastguard Worker                         VkQueryPool queryPool,
284*61046927SAndroid Build Coastguard Worker                         uint32_t firstQuery,
285*61046927SAndroid Build Coastguard Worker                         uint32_t queryCount)
286*61046927SAndroid Build Coastguard Worker {
287*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_query_pool, pool, queryPool);
288*61046927SAndroid Build Coastguard Worker    uint32_t *availability =
289*61046927SAndroid Build Coastguard Worker       pvr_bo_suballoc_get_map_addr(pool->availability_buffer);
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    memset(availability + firstQuery, 0, sizeof(uint32_t) * queryCount);
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker 
pvr_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)294*61046927SAndroid Build Coastguard Worker void pvr_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
295*61046927SAndroid Build Coastguard Worker                                  VkQueryPool queryPool,
296*61046927SAndroid Build Coastguard Worker                                  uint32_t firstQuery,
297*61046927SAndroid Build Coastguard Worker                                  uint32_t queryCount,
298*61046927SAndroid Build Coastguard Worker                                  VkBuffer dstBuffer,
299*61046927SAndroid Build Coastguard Worker                                  VkDeviceSize dstOffset,
300*61046927SAndroid Build Coastguard Worker                                  VkDeviceSize stride,
301*61046927SAndroid Build Coastguard Worker                                  VkQueryResultFlags flags)
302*61046927SAndroid Build Coastguard Worker {
303*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer);
304*61046927SAndroid Build Coastguard Worker    struct pvr_query_info query_info;
305*61046927SAndroid Build Coastguard Worker    VkResult result;
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer);
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker    query_info.type = PVR_QUERY_TYPE_COPY_QUERY_RESULTS;
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.query_pool = queryPool;
312*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.first_query = firstQuery;
313*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.query_count = queryCount;
314*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.dst_buffer = dstBuffer;
315*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.dst_offset = dstOffset;
316*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.stride = stride;
317*61046927SAndroid Build Coastguard Worker    query_info.copy_query_results.flags = flags;
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    result = pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_EVENT);
320*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
321*61046927SAndroid Build Coastguard Worker       return;
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    /* The Vulkan 1.3.231 spec says:
324*61046927SAndroid Build Coastguard Worker     *
325*61046927SAndroid Build Coastguard Worker     *    "vkCmdCopyQueryPoolResults is considered to be a transfer operation,
326*61046927SAndroid Build Coastguard Worker     *    and its writes to buffer memory must be synchronized using
327*61046927SAndroid Build Coastguard Worker     *    VK_PIPELINE_STAGE_TRANSFER_BIT and VK_ACCESS_TRANSFER_WRITE_BIT before
328*61046927SAndroid Build Coastguard Worker     *    using the results."
329*61046927SAndroid Build Coastguard Worker     *
330*61046927SAndroid Build Coastguard Worker     */
331*61046927SAndroid Build Coastguard Worker    /* We record barrier event sub commands to sync the compute job used for the
332*61046927SAndroid Build Coastguard Worker     * copy query results program with transfer jobs to prevent an overlapping
333*61046927SAndroid Build Coastguard Worker     * transfer job with the compute job.
334*61046927SAndroid Build Coastguard Worker     */
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker    cmd_buffer->state.current_sub_cmd->event = (struct pvr_sub_cmd_event){
337*61046927SAndroid Build Coastguard Worker       .type = PVR_EVENT_TYPE_BARRIER,
338*61046927SAndroid Build Coastguard Worker       .barrier = {
339*61046927SAndroid Build Coastguard Worker          .wait_for_stage_mask = PVR_PIPELINE_STAGE_TRANSFER_BIT,
340*61046927SAndroid Build Coastguard Worker          .wait_at_stage_mask = PVR_PIPELINE_STAGE_OCCLUSION_QUERY_BIT,
341*61046927SAndroid Build Coastguard Worker       },
342*61046927SAndroid Build Coastguard Worker    };
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker    result = pvr_cmd_buffer_end_sub_cmd(cmd_buffer);
345*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
346*61046927SAndroid Build Coastguard Worker       return;
347*61046927SAndroid Build Coastguard Worker 
348*61046927SAndroid Build Coastguard Worker    pvr_add_query_program(cmd_buffer, &query_info);
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker    result = pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_EVENT);
351*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
352*61046927SAndroid Build Coastguard Worker       return;
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker    cmd_buffer->state.current_sub_cmd->event = (struct pvr_sub_cmd_event){
355*61046927SAndroid Build Coastguard Worker       .type = PVR_EVENT_TYPE_BARRIER,
356*61046927SAndroid Build Coastguard Worker       .barrier = {
357*61046927SAndroid Build Coastguard Worker          .wait_for_stage_mask = PVR_PIPELINE_STAGE_OCCLUSION_QUERY_BIT,
358*61046927SAndroid Build Coastguard Worker          .wait_at_stage_mask = PVR_PIPELINE_STAGE_TRANSFER_BIT,
359*61046927SAndroid Build Coastguard Worker       },
360*61046927SAndroid Build Coastguard Worker    };
361*61046927SAndroid Build Coastguard Worker }
362*61046927SAndroid Build Coastguard Worker 
pvr_CmdBeginQuery(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query,VkQueryControlFlags flags)363*61046927SAndroid Build Coastguard Worker void pvr_CmdBeginQuery(VkCommandBuffer commandBuffer,
364*61046927SAndroid Build Coastguard Worker                        VkQueryPool queryPool,
365*61046927SAndroid Build Coastguard Worker                        uint32_t query,
366*61046927SAndroid Build Coastguard Worker                        VkQueryControlFlags flags)
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer);
369*61046927SAndroid Build Coastguard Worker    struct pvr_cmd_buffer_state *state = &cmd_buffer->state;
370*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_query_pool, pool, queryPool);
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker    PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer);
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    /* Occlusion queries can't be nested. */
375*61046927SAndroid Build Coastguard Worker    assert(!state->vis_test_enabled);
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker    if (state->current_sub_cmd) {
378*61046927SAndroid Build Coastguard Worker       assert(state->current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS);
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker       if (!state->current_sub_cmd->gfx.query_pool) {
381*61046927SAndroid Build Coastguard Worker          state->current_sub_cmd->gfx.query_pool = pool;
382*61046927SAndroid Build Coastguard Worker       } else if (state->current_sub_cmd->gfx.query_pool != pool) {
383*61046927SAndroid Build Coastguard Worker          VkResult result;
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker          /* Kick render. */
386*61046927SAndroid Build Coastguard Worker          state->current_sub_cmd->gfx.barrier_store = true;
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker          result = pvr_cmd_buffer_end_sub_cmd(cmd_buffer);
389*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
390*61046927SAndroid Build Coastguard Worker             return;
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker          result =
393*61046927SAndroid Build Coastguard Worker             pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_GRAPHICS);
394*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
395*61046927SAndroid Build Coastguard Worker             return;
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker          /* Use existing render setup, but load color attachments from HW
398*61046927SAndroid Build Coastguard Worker           * BGOBJ.
399*61046927SAndroid Build Coastguard Worker           */
400*61046927SAndroid Build Coastguard Worker          state->current_sub_cmd->gfx.barrier_load = true;
401*61046927SAndroid Build Coastguard Worker          state->current_sub_cmd->gfx.barrier_store = false;
402*61046927SAndroid Build Coastguard Worker          state->current_sub_cmd->gfx.query_pool = pool;
403*61046927SAndroid Build Coastguard Worker       }
404*61046927SAndroid Build Coastguard Worker    }
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    state->query_pool = pool;
407*61046927SAndroid Build Coastguard Worker    state->vis_test_enabled = true;
408*61046927SAndroid Build Coastguard Worker    state->vis_reg = query;
409*61046927SAndroid Build Coastguard Worker    state->dirty.vis_test = true;
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker    /* Add the index to the list for this render. */
412*61046927SAndroid Build Coastguard Worker    util_dynarray_append(&state->query_indices, __typeof__(query), query);
413*61046927SAndroid Build Coastguard Worker }
414*61046927SAndroid Build Coastguard Worker 
pvr_CmdEndQuery(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query)415*61046927SAndroid Build Coastguard Worker void pvr_CmdEndQuery(VkCommandBuffer commandBuffer,
416*61046927SAndroid Build Coastguard Worker                      VkQueryPool queryPool,
417*61046927SAndroid Build Coastguard Worker                      uint32_t query)
418*61046927SAndroid Build Coastguard Worker {
419*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer);
420*61046927SAndroid Build Coastguard Worker    struct pvr_cmd_buffer_state *state = &cmd_buffer->state;
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker    PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer);
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker    state->vis_test_enabled = false;
425*61046927SAndroid Build Coastguard Worker    state->dirty.vis_test = true;
426*61046927SAndroid Build Coastguard Worker }
427