xref: /aosp_15_r20/external/mesa3d/src/broadcom/vulkan/v3dv_query.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Raspberry Pi Ltd
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is 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
18*61046927SAndroid Build Coastguard Worker  * THE 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
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "v3dv_private.h"
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include "util/timespec.h"
27*61046927SAndroid Build Coastguard Worker #include "compiler/nir/nir_builder.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker static void
kperfmon_create(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query)30*61046927SAndroid Build Coastguard Worker kperfmon_create(struct v3dv_device *device,
31*61046927SAndroid Build Coastguard Worker                 struct v3dv_query_pool *pool,
32*61046927SAndroid Build Coastguard Worker                 uint32_t query)
33*61046927SAndroid Build Coastguard Worker {
34*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pool->perfmon.nperfmons; i++) {
35*61046927SAndroid Build Coastguard Worker       assert(i * DRM_V3D_MAX_PERF_COUNTERS < pool->perfmon.ncounters);
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker       struct drm_v3d_perfmon_create req = {
38*61046927SAndroid Build Coastguard Worker          .ncounters = MIN2(pool->perfmon.ncounters -
39*61046927SAndroid Build Coastguard Worker                            i * DRM_V3D_MAX_PERF_COUNTERS,
40*61046927SAndroid Build Coastguard Worker                            DRM_V3D_MAX_PERF_COUNTERS),
41*61046927SAndroid Build Coastguard Worker       };
42*61046927SAndroid Build Coastguard Worker       memcpy(req.counters,
43*61046927SAndroid Build Coastguard Worker              &pool->perfmon.counters[i * DRM_V3D_MAX_PERF_COUNTERS],
44*61046927SAndroid Build Coastguard Worker              req.ncounters);
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker       int ret = v3dv_ioctl(device->pdevice->render_fd,
47*61046927SAndroid Build Coastguard Worker                            DRM_IOCTL_V3D_PERFMON_CREATE,
48*61046927SAndroid Build Coastguard Worker                            &req);
49*61046927SAndroid Build Coastguard Worker       if (ret)
50*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Failed to create perfmon for query %d: %s\n", query,
51*61046927SAndroid Build Coastguard Worker                  strerror(errno));
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker       pool->queries[query].perf.kperfmon_ids[i] = req.id;
54*61046927SAndroid Build Coastguard Worker    }
55*61046927SAndroid Build Coastguard Worker }
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker static void
kperfmon_destroy(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query)58*61046927SAndroid Build Coastguard Worker kperfmon_destroy(struct v3dv_device *device,
59*61046927SAndroid Build Coastguard Worker                  struct v3dv_query_pool *pool,
60*61046927SAndroid Build Coastguard Worker                  uint32_t query)
61*61046927SAndroid Build Coastguard Worker {
62*61046927SAndroid Build Coastguard Worker    /* Skip destroying if never created */
63*61046927SAndroid Build Coastguard Worker    if (!pool->queries[query].perf.kperfmon_ids[0])
64*61046927SAndroid Build Coastguard Worker       return;
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pool->perfmon.nperfmons; i++) {
67*61046927SAndroid Build Coastguard Worker       struct drm_v3d_perfmon_destroy req = {
68*61046927SAndroid Build Coastguard Worker          .id = pool->queries[query].perf.kperfmon_ids[i]
69*61046927SAndroid Build Coastguard Worker       };
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker       int ret = v3dv_ioctl(device->pdevice->render_fd,
72*61046927SAndroid Build Coastguard Worker                            DRM_IOCTL_V3D_PERFMON_DESTROY,
73*61046927SAndroid Build Coastguard Worker                            &req);
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker       if (ret) {
76*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Failed to destroy perfmon %u: %s\n",
77*61046927SAndroid Build Coastguard Worker                  req.id, strerror(errno));
78*61046927SAndroid Build Coastguard Worker       }
79*61046927SAndroid Build Coastguard Worker    }
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker /**
83*61046927SAndroid Build Coastguard Worker  * Creates a VkBuffer (and VkDeviceMemory) to access a BO.
84*61046927SAndroid Build Coastguard Worker  */
85*61046927SAndroid Build Coastguard Worker static VkResult
create_vk_storage_buffer(struct v3dv_device * device,struct v3dv_bo * bo,VkBuffer * vk_buf,VkDeviceMemory * vk_mem)86*61046927SAndroid Build Coastguard Worker create_vk_storage_buffer(struct v3dv_device *device,
87*61046927SAndroid Build Coastguard Worker                          struct v3dv_bo *bo,
88*61046927SAndroid Build Coastguard Worker                          VkBuffer *vk_buf,
89*61046927SAndroid Build Coastguard Worker                          VkDeviceMemory *vk_mem)
90*61046927SAndroid Build Coastguard Worker {
91*61046927SAndroid Build Coastguard Worker    VkDevice vk_device = v3dv_device_to_handle(device);
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    VkBufferCreateInfo buf_info = {
94*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
95*61046927SAndroid Build Coastguard Worker       .size = bo->size,
96*61046927SAndroid Build Coastguard Worker       .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
97*61046927SAndroid Build Coastguard Worker    };
98*61046927SAndroid Build Coastguard Worker    VkResult result = v3dv_CreateBuffer(vk_device, &buf_info, NULL, vk_buf);
99*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
100*61046927SAndroid Build Coastguard Worker       return result;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    struct v3dv_device_memory *mem =
103*61046927SAndroid Build Coastguard Worker       vk_object_zalloc(&device->vk, NULL, sizeof(*mem),
104*61046927SAndroid Build Coastguard Worker                        VK_OBJECT_TYPE_DEVICE_MEMORY);
105*61046927SAndroid Build Coastguard Worker    if (!mem)
106*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    mem->bo = bo;
109*61046927SAndroid Build Coastguard Worker    mem->type = &device->pdevice->memory.memoryTypes[0];
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    *vk_mem = v3dv_device_memory_to_handle(mem);
112*61046927SAndroid Build Coastguard Worker    VkBindBufferMemoryInfo bind_info = {
113*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
114*61046927SAndroid Build Coastguard Worker       .buffer = *vk_buf,
115*61046927SAndroid Build Coastguard Worker       .memory = *vk_mem,
116*61046927SAndroid Build Coastguard Worker       .memoryOffset = 0,
117*61046927SAndroid Build Coastguard Worker    };
118*61046927SAndroid Build Coastguard Worker    v3dv_BindBufferMemory2(vk_device, 1, &bind_info);
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
121*61046927SAndroid Build Coastguard Worker }
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker static void
destroy_vk_storage_buffer(struct v3dv_device * device,VkBuffer * vk_buf,VkDeviceMemory * vk_mem)124*61046927SAndroid Build Coastguard Worker destroy_vk_storage_buffer(struct v3dv_device *device,
125*61046927SAndroid Build Coastguard Worker                           VkBuffer *vk_buf,
126*61046927SAndroid Build Coastguard Worker                           VkDeviceMemory *vk_mem)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker    if (*vk_mem) {
129*61046927SAndroid Build Coastguard Worker       vk_object_free(&device->vk, NULL, v3dv_device_memory_from_handle(*vk_mem));
130*61046927SAndroid Build Coastguard Worker       *vk_mem = VK_NULL_HANDLE;
131*61046927SAndroid Build Coastguard Worker    }
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    v3dv_DestroyBuffer(v3dv_device_to_handle(device), *vk_buf, NULL);
134*61046927SAndroid Build Coastguard Worker    *vk_buf = VK_NULL_HANDLE;
135*61046927SAndroid Build Coastguard Worker }
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker /**
138*61046927SAndroid Build Coastguard Worker  * Allocates descriptor sets to access query pool BO (availability and
139*61046927SAndroid Build Coastguard Worker  * occlusion query results) from Vulkan pipelines.
140*61046927SAndroid Build Coastguard Worker  */
141*61046927SAndroid Build Coastguard Worker static VkResult
create_pool_descriptors(struct v3dv_device * device,struct v3dv_query_pool * pool)142*61046927SAndroid Build Coastguard Worker create_pool_descriptors(struct v3dv_device *device,
143*61046927SAndroid Build Coastguard Worker                         struct v3dv_query_pool *pool)
144*61046927SAndroid Build Coastguard Worker {
145*61046927SAndroid Build Coastguard Worker    assert(pool->query_type == VK_QUERY_TYPE_OCCLUSION);
146*61046927SAndroid Build Coastguard Worker    VkDevice vk_device = v3dv_device_to_handle(device);
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    VkDescriptorPoolSize pool_size = {
149*61046927SAndroid Build Coastguard Worker       .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
150*61046927SAndroid Build Coastguard Worker       .descriptorCount = 1,
151*61046927SAndroid Build Coastguard Worker    };
152*61046927SAndroid Build Coastguard Worker    VkDescriptorPoolCreateInfo pool_info = {
153*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
154*61046927SAndroid Build Coastguard Worker       .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
155*61046927SAndroid Build Coastguard Worker       .maxSets = 1,
156*61046927SAndroid Build Coastguard Worker       .poolSizeCount = 1,
157*61046927SAndroid Build Coastguard Worker       .pPoolSizes = &pool_size,
158*61046927SAndroid Build Coastguard Worker    };
159*61046927SAndroid Build Coastguard Worker    VkResult result =
160*61046927SAndroid Build Coastguard Worker       v3dv_CreateDescriptorPool(vk_device, &pool_info, NULL,
161*61046927SAndroid Build Coastguard Worker                                 &pool->meta.descriptor_pool);
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
164*61046927SAndroid Build Coastguard Worker       return result;
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    VkDescriptorSetAllocateInfo alloc_info = {
167*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
168*61046927SAndroid Build Coastguard Worker       .descriptorPool = pool->meta.descriptor_pool,
169*61046927SAndroid Build Coastguard Worker       .descriptorSetCount = 1,
170*61046927SAndroid Build Coastguard Worker       .pSetLayouts = &device->queries.buf_descriptor_set_layout,
171*61046927SAndroid Build Coastguard Worker    };
172*61046927SAndroid Build Coastguard Worker    result = v3dv_AllocateDescriptorSets(vk_device, &alloc_info,
173*61046927SAndroid Build Coastguard Worker                                         &pool->meta.descriptor_set);
174*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
175*61046927SAndroid Build Coastguard Worker       return result;
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    VkDescriptorBufferInfo desc_buf_info = {
178*61046927SAndroid Build Coastguard Worker       .buffer = pool->meta.buf,
179*61046927SAndroid Build Coastguard Worker       .offset = 0,
180*61046927SAndroid Build Coastguard Worker       .range = VK_WHOLE_SIZE,
181*61046927SAndroid Build Coastguard Worker    };
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    VkWriteDescriptorSet write = {
184*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
185*61046927SAndroid Build Coastguard Worker       .dstSet = pool->meta.descriptor_set,
186*61046927SAndroid Build Coastguard Worker       .dstBinding = 0,
187*61046927SAndroid Build Coastguard Worker       .dstArrayElement = 0,
188*61046927SAndroid Build Coastguard Worker       .descriptorCount = 1,
189*61046927SAndroid Build Coastguard Worker       .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
190*61046927SAndroid Build Coastguard Worker       .pBufferInfo = &desc_buf_info,
191*61046927SAndroid Build Coastguard Worker    };
192*61046927SAndroid Build Coastguard Worker    v3dv_UpdateDescriptorSets(vk_device, 1, &write, 0, NULL);
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
195*61046927SAndroid Build Coastguard Worker }
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker static void
destroy_pool_descriptors(struct v3dv_device * device,struct v3dv_query_pool * pool)198*61046927SAndroid Build Coastguard Worker destroy_pool_descriptors(struct v3dv_device *device,
199*61046927SAndroid Build Coastguard Worker                          struct v3dv_query_pool *pool)
200*61046927SAndroid Build Coastguard Worker {
201*61046927SAndroid Build Coastguard Worker    assert(pool->query_type == VK_QUERY_TYPE_OCCLUSION);
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    v3dv_FreeDescriptorSets(v3dv_device_to_handle(device),
204*61046927SAndroid Build Coastguard Worker                            pool->meta.descriptor_pool,
205*61046927SAndroid Build Coastguard Worker                            1, &pool->meta.descriptor_set);
206*61046927SAndroid Build Coastguard Worker    pool->meta.descriptor_set = VK_NULL_HANDLE;
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker    v3dv_DestroyDescriptorPool(v3dv_device_to_handle(device),
209*61046927SAndroid Build Coastguard Worker                               pool->meta.descriptor_pool, NULL);
210*61046927SAndroid Build Coastguard Worker    pool->meta.descriptor_pool = VK_NULL_HANDLE;
211*61046927SAndroid Build Coastguard Worker }
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker static VkResult
pool_create_meta_resources(struct v3dv_device * device,struct v3dv_query_pool * pool)214*61046927SAndroid Build Coastguard Worker pool_create_meta_resources(struct v3dv_device *device,
215*61046927SAndroid Build Coastguard Worker                            struct v3dv_query_pool *pool)
216*61046927SAndroid Build Coastguard Worker {
217*61046927SAndroid Build Coastguard Worker    VkResult result;
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    if (pool->query_type != VK_QUERY_TYPE_OCCLUSION)
220*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker    result = create_vk_storage_buffer(device, pool->occlusion.bo,
223*61046927SAndroid Build Coastguard Worker                                      &pool->meta.buf, &pool->meta.mem);
224*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
225*61046927SAndroid Build Coastguard Worker       return result;
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker    result = create_pool_descriptors(device, pool);
228*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
229*61046927SAndroid Build Coastguard Worker        return result;
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
232*61046927SAndroid Build Coastguard Worker }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker static void
pool_destroy_meta_resources(struct v3dv_device * device,struct v3dv_query_pool * pool)235*61046927SAndroid Build Coastguard Worker pool_destroy_meta_resources(struct v3dv_device *device,
236*61046927SAndroid Build Coastguard Worker                             struct v3dv_query_pool *pool)
237*61046927SAndroid Build Coastguard Worker {
238*61046927SAndroid Build Coastguard Worker    if (pool->query_type != VK_QUERY_TYPE_OCCLUSION)
239*61046927SAndroid Build Coastguard Worker       return;
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker    destroy_pool_descriptors(device, pool);
242*61046927SAndroid Build Coastguard Worker    destroy_vk_storage_buffer(device, &pool->meta.buf, &pool->meta.mem);
243*61046927SAndroid Build Coastguard Worker }
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateQueryPool(VkDevice _device,const VkQueryPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkQueryPool * pQueryPool)246*61046927SAndroid Build Coastguard Worker v3dv_CreateQueryPool(VkDevice _device,
247*61046927SAndroid Build Coastguard Worker                      const VkQueryPoolCreateInfo *pCreateInfo,
248*61046927SAndroid Build Coastguard Worker                      const VkAllocationCallbacks *pAllocator,
249*61046927SAndroid Build Coastguard Worker                      VkQueryPool *pQueryPool)
250*61046927SAndroid Build Coastguard Worker {
251*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_device, device, _device);
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker    assert(pCreateInfo->queryType == VK_QUERY_TYPE_OCCLUSION ||
254*61046927SAndroid Build Coastguard Worker           pCreateInfo->queryType == VK_QUERY_TYPE_TIMESTAMP ||
255*61046927SAndroid Build Coastguard Worker           pCreateInfo->queryType == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
256*61046927SAndroid Build Coastguard Worker    assert(pCreateInfo->queryCount > 0);
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker    struct v3dv_query_pool *pool =
259*61046927SAndroid Build Coastguard Worker       vk_object_zalloc(&device->vk, pAllocator, sizeof(*pool),
260*61046927SAndroid Build Coastguard Worker                        VK_OBJECT_TYPE_QUERY_POOL);
261*61046927SAndroid Build Coastguard Worker    if (pool == NULL)
262*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker    pool->query_type = pCreateInfo->queryType;
265*61046927SAndroid Build Coastguard Worker    pool->query_count = pCreateInfo->queryCount;
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker    uint32_t query_idx = 0;
268*61046927SAndroid Build Coastguard Worker    VkResult result;
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    const uint32_t pool_bytes = sizeof(struct v3dv_query) * pool->query_count;
271*61046927SAndroid Build Coastguard Worker    pool->queries = vk_alloc2(&device->vk.alloc, pAllocator, pool_bytes, 8,
272*61046927SAndroid Build Coastguard Worker                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
273*61046927SAndroid Build Coastguard Worker    if (pool->queries == NULL) {
274*61046927SAndroid Build Coastguard Worker       result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
275*61046927SAndroid Build Coastguard Worker       goto fail;
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    switch (pool->query_type) {
279*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_OCCLUSION: {
280*61046927SAndroid Build Coastguard Worker       /* The hardware allows us to setup groups of 16 queries in consecutive
281*61046927SAndroid Build Coastguard Worker        * 4-byte addresses, requiring only that each group of 16 queries is
282*61046927SAndroid Build Coastguard Worker        * aligned to a 1024 byte boundary.
283*61046927SAndroid Build Coastguard Worker        */
284*61046927SAndroid Build Coastguard Worker       const uint32_t query_groups = DIV_ROUND_UP(pool->query_count, 16);
285*61046927SAndroid Build Coastguard Worker       uint32_t bo_size = query_groups * 1024;
286*61046927SAndroid Build Coastguard Worker       /* After the counters we store avalability data, 1 byte/query */
287*61046927SAndroid Build Coastguard Worker       pool->occlusion.avail_offset = bo_size;
288*61046927SAndroid Build Coastguard Worker       bo_size += pool->query_count;
289*61046927SAndroid Build Coastguard Worker       pool->occlusion.bo = v3dv_bo_alloc(device, bo_size, "query:o", true);
290*61046927SAndroid Build Coastguard Worker       if (!pool->occlusion.bo) {
291*61046927SAndroid Build Coastguard Worker          result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
292*61046927SAndroid Build Coastguard Worker          goto fail;
293*61046927SAndroid Build Coastguard Worker       }
294*61046927SAndroid Build Coastguard Worker       if (!v3dv_bo_map(device, pool->occlusion.bo, bo_size)) {
295*61046927SAndroid Build Coastguard Worker          result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
296*61046927SAndroid Build Coastguard Worker          goto fail;
297*61046927SAndroid Build Coastguard Worker       }
298*61046927SAndroid Build Coastguard Worker       break;
299*61046927SAndroid Build Coastguard Worker    }
300*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: {
301*61046927SAndroid Build Coastguard Worker       const VkQueryPoolPerformanceCreateInfoKHR *pq_info =
302*61046927SAndroid Build Coastguard Worker          vk_find_struct_const(pCreateInfo->pNext,
303*61046927SAndroid Build Coastguard Worker                               QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR);
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker       assert(pq_info);
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker       pool->perfmon.ncounters = pq_info->counterIndexCount;
308*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pq_info->counterIndexCount; i++)
309*61046927SAndroid Build Coastguard Worker          pool->perfmon.counters[i] = pq_info->pCounterIndices[i];
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker       pool->perfmon.nperfmons = DIV_ROUND_UP(pool->perfmon.ncounters,
312*61046927SAndroid Build Coastguard Worker                                              DRM_V3D_MAX_PERF_COUNTERS);
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker       assert(pool->perfmon.nperfmons <= V3DV_MAX_PERFMONS);
315*61046927SAndroid Build Coastguard Worker       break;
316*61046927SAndroid Build Coastguard Worker    }
317*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_TIMESTAMP: {
318*61046927SAndroid Build Coastguard Worker       /* 8 bytes per query used for the timestamp value. We have all
319*61046927SAndroid Build Coastguard Worker        * timestamps tightly packed first in the buffer.
320*61046927SAndroid Build Coastguard Worker        */
321*61046927SAndroid Build Coastguard Worker       const uint32_t bo_size = pool->query_count * 8;
322*61046927SAndroid Build Coastguard Worker       pool->timestamp.bo = v3dv_bo_alloc(device, bo_size, "query:t", true);
323*61046927SAndroid Build Coastguard Worker       if (!pool->timestamp.bo) {
324*61046927SAndroid Build Coastguard Worker          result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
325*61046927SAndroid Build Coastguard Worker          goto fail;
326*61046927SAndroid Build Coastguard Worker       }
327*61046927SAndroid Build Coastguard Worker       if (!v3dv_bo_map(device, pool->timestamp.bo, bo_size)) {
328*61046927SAndroid Build Coastguard Worker          result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
329*61046927SAndroid Build Coastguard Worker          goto fail;
330*61046927SAndroid Build Coastguard Worker       }
331*61046927SAndroid Build Coastguard Worker       break;
332*61046927SAndroid Build Coastguard Worker    }
333*61046927SAndroid Build Coastguard Worker    default:
334*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported query type");
335*61046927SAndroid Build Coastguard Worker    }
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker    /* Initialize queries in the pool */
338*61046927SAndroid Build Coastguard Worker    for (; query_idx < pool->query_count; query_idx++) {
339*61046927SAndroid Build Coastguard Worker       pool->queries[query_idx].maybe_available = false;
340*61046927SAndroid Build Coastguard Worker       switch (pool->query_type) {
341*61046927SAndroid Build Coastguard Worker       case VK_QUERY_TYPE_OCCLUSION: {
342*61046927SAndroid Build Coastguard Worker          const uint32_t query_group = query_idx / 16;
343*61046927SAndroid Build Coastguard Worker          const uint32_t query_offset = query_group * 1024 + (query_idx % 16) * 4;
344*61046927SAndroid Build Coastguard Worker          pool->queries[query_idx].occlusion.offset = query_offset;
345*61046927SAndroid Build Coastguard Worker          break;
346*61046927SAndroid Build Coastguard Worker          }
347*61046927SAndroid Build Coastguard Worker       case VK_QUERY_TYPE_TIMESTAMP:
348*61046927SAndroid Build Coastguard Worker          pool->queries[query_idx].timestamp.offset = query_idx * 8;
349*61046927SAndroid Build Coastguard Worker          result = vk_sync_create(&device->vk,
350*61046927SAndroid Build Coastguard Worker                                  &device->pdevice->drm_syncobj_type, 0, 0,
351*61046927SAndroid Build Coastguard Worker                                  &pool->queries[query_idx].timestamp.sync);
352*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
353*61046927SAndroid Build Coastguard Worker             goto fail;
354*61046927SAndroid Build Coastguard Worker          break;
355*61046927SAndroid Build Coastguard Worker       case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: {
356*61046927SAndroid Build Coastguard Worker          result = vk_sync_create(&device->vk,
357*61046927SAndroid Build Coastguard Worker                                  &device->pdevice->drm_syncobj_type, 0, 0,
358*61046927SAndroid Build Coastguard Worker                                  &pool->queries[query_idx].perf.last_job_sync);
359*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
360*61046927SAndroid Build Coastguard Worker             goto fail;
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker          kperfmon_create(device, pool, query_idx);
363*61046927SAndroid Build Coastguard Worker          break;
364*61046927SAndroid Build Coastguard Worker          }
365*61046927SAndroid Build Coastguard Worker       default:
366*61046927SAndroid Build Coastguard Worker          unreachable("Unsupported query type");
367*61046927SAndroid Build Coastguard Worker       }
368*61046927SAndroid Build Coastguard Worker    }
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker    /* Create meta resources */
371*61046927SAndroid Build Coastguard Worker    result = pool_create_meta_resources(device, pool);
372*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
373*61046927SAndroid Build Coastguard Worker       goto fail;
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    *pQueryPool = v3dv_query_pool_to_handle(pool);
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker fail:
380*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
381*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < query_idx; j++)
382*61046927SAndroid Build Coastguard Worker          vk_sync_destroy(&device->vk, pool->queries[j].timestamp.sync);
383*61046927SAndroid Build Coastguard Worker    }
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
386*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < query_idx; j++)
387*61046927SAndroid Build Coastguard Worker          vk_sync_destroy(&device->vk, pool->queries[j].perf.last_job_sync);
388*61046927SAndroid Build Coastguard Worker    }
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker    if (pool->occlusion.bo)
391*61046927SAndroid Build Coastguard Worker       v3dv_bo_free(device, pool->occlusion.bo);
392*61046927SAndroid Build Coastguard Worker    if (pool->timestamp.bo)
393*61046927SAndroid Build Coastguard Worker       v3dv_bo_free(device, pool->timestamp.bo);
394*61046927SAndroid Build Coastguard Worker    if (pool->queries)
395*61046927SAndroid Build Coastguard Worker       vk_free2(&device->vk.alloc, pAllocator, pool->queries);
396*61046927SAndroid Build Coastguard Worker    pool_destroy_meta_resources(device, pool);
397*61046927SAndroid Build Coastguard Worker    vk_object_free(&device->vk, pAllocator, pool);
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker    return result;
400*61046927SAndroid Build Coastguard Worker }
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyQueryPool(VkDevice _device,VkQueryPool queryPool,const VkAllocationCallbacks * pAllocator)403*61046927SAndroid Build Coastguard Worker v3dv_DestroyQueryPool(VkDevice _device,
404*61046927SAndroid Build Coastguard Worker                       VkQueryPool queryPool,
405*61046927SAndroid Build Coastguard Worker                       const VkAllocationCallbacks *pAllocator)
406*61046927SAndroid Build Coastguard Worker {
407*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_device, device, _device);
408*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    if (!pool)
411*61046927SAndroid Build Coastguard Worker       return;
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    if (pool->occlusion.bo)
414*61046927SAndroid Build Coastguard Worker       v3dv_bo_free(device, pool->occlusion.bo);
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    if (pool->timestamp.bo)
417*61046927SAndroid Build Coastguard Worker       v3dv_bo_free(device, pool->timestamp.bo);
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
420*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pool->query_count; i++)
421*61046927SAndroid Build Coastguard Worker          vk_sync_destroy(&device->vk, pool->queries[i].timestamp.sync);
422*61046927SAndroid Build Coastguard Worker    }
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
425*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < pool->query_count; i++) {
426*61046927SAndroid Build Coastguard Worker          kperfmon_destroy(device, pool, i);
427*61046927SAndroid Build Coastguard Worker          vk_sync_destroy(&device->vk, pool->queries[i].perf.last_job_sync);
428*61046927SAndroid Build Coastguard Worker       }
429*61046927SAndroid Build Coastguard Worker    }
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    if (pool->queries)
432*61046927SAndroid Build Coastguard Worker       vk_free2(&device->vk.alloc, pAllocator, pool->queries);
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker    pool_destroy_meta_resources(device, pool);
435*61046927SAndroid Build Coastguard Worker 
436*61046927SAndroid Build Coastguard Worker    vk_object_free(&device->vk, pAllocator, pool);
437*61046927SAndroid Build Coastguard Worker }
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker static void
write_to_buffer(void * dst,uint32_t idx,bool do_64bit,uint64_t value)440*61046927SAndroid Build Coastguard Worker write_to_buffer(void *dst, uint32_t idx, bool do_64bit, uint64_t value)
441*61046927SAndroid Build Coastguard Worker {
442*61046927SAndroid Build Coastguard Worker    if (do_64bit) {
443*61046927SAndroid Build Coastguard Worker       uint64_t *dst64 = (uint64_t *) dst;
444*61046927SAndroid Build Coastguard Worker       dst64[idx] = value;
445*61046927SAndroid Build Coastguard Worker    } else {
446*61046927SAndroid Build Coastguard Worker       uint32_t *dst32 = (uint32_t *) dst;
447*61046927SAndroid Build Coastguard Worker       dst32[idx] = (uint32_t) value;
448*61046927SAndroid Build Coastguard Worker    }
449*61046927SAndroid Build Coastguard Worker }
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker static VkResult
query_wait_available(struct v3dv_device * device,struct v3dv_query_pool * pool,struct v3dv_query * q,uint32_t query_idx)452*61046927SAndroid Build Coastguard Worker query_wait_available(struct v3dv_device *device,
453*61046927SAndroid Build Coastguard Worker                      struct v3dv_query_pool *pool,
454*61046927SAndroid Build Coastguard Worker                      struct v3dv_query *q,
455*61046927SAndroid Build Coastguard Worker                      uint32_t query_idx)
456*61046927SAndroid Build Coastguard Worker {
457*61046927SAndroid Build Coastguard Worker    /* For occlusion queries we prefer to poll the availability BO in a loop
458*61046927SAndroid Build Coastguard Worker     * to waiting on the query results BO, because the latter would
459*61046927SAndroid Build Coastguard Worker     * make us wait for any job running queries from the pool, even if those
460*61046927SAndroid Build Coastguard Worker     * queries do not involve the one we want to wait on.
461*61046927SAndroid Build Coastguard Worker     */
462*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_OCCLUSION) {
463*61046927SAndroid Build Coastguard Worker       uint8_t *q_addr = ((uint8_t *) pool->occlusion.bo->map) +
464*61046927SAndroid Build Coastguard Worker                         pool->occlusion.avail_offset + query_idx;
465*61046927SAndroid Build Coastguard Worker       while (*q_addr == 0)
466*61046927SAndroid Build Coastguard Worker          usleep(250);
467*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
468*61046927SAndroid Build Coastguard Worker    }
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
471*61046927SAndroid Build Coastguard Worker       if (vk_sync_wait(&device->vk, q->timestamp.sync,
472*61046927SAndroid Build Coastguard Worker                        0, VK_SYNC_WAIT_COMPLETE, UINT64_MAX) != VK_SUCCESS) {
473*61046927SAndroid Build Coastguard Worker          return vk_device_set_lost(&device->vk, "Query job wait failed");
474*61046927SAndroid Build Coastguard Worker       }
475*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
476*61046927SAndroid Build Coastguard Worker    }
477*61046927SAndroid Build Coastguard Worker 
478*61046927SAndroid Build Coastguard Worker    assert(pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
479*61046927SAndroid Build Coastguard Worker 
480*61046927SAndroid Build Coastguard Worker    /* For performance queries we need to wait for the queue to signal that
481*61046927SAndroid Build Coastguard Worker     * the query has been submitted for execution before anything else.
482*61046927SAndroid Build Coastguard Worker     */
483*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
484*61046927SAndroid Build Coastguard Worker    if (!q->maybe_available) {
485*61046927SAndroid Build Coastguard Worker       struct timespec timeout;
486*61046927SAndroid Build Coastguard Worker       timespec_get(&timeout, TIME_UTC);
487*61046927SAndroid Build Coastguard Worker       timespec_add_msec(&timeout, &timeout, 2000);
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker       mtx_lock(&device->query_mutex);
490*61046927SAndroid Build Coastguard Worker       while (!q->maybe_available) {
491*61046927SAndroid Build Coastguard Worker          if (vk_device_is_lost(&device->vk)) {
492*61046927SAndroid Build Coastguard Worker             result = VK_ERROR_DEVICE_LOST;
493*61046927SAndroid Build Coastguard Worker             break;
494*61046927SAndroid Build Coastguard Worker          }
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker          int ret = cnd_timedwait(&device->query_ended,
497*61046927SAndroid Build Coastguard Worker                                  &device->query_mutex,
498*61046927SAndroid Build Coastguard Worker                                  &timeout);
499*61046927SAndroid Build Coastguard Worker          if (ret != thrd_success) {
500*61046927SAndroid Build Coastguard Worker             mtx_unlock(&device->query_mutex);
501*61046927SAndroid Build Coastguard Worker             result = vk_device_set_lost(&device->vk, "Query wait failed");
502*61046927SAndroid Build Coastguard Worker             break;
503*61046927SAndroid Build Coastguard Worker          }
504*61046927SAndroid Build Coastguard Worker       }
505*61046927SAndroid Build Coastguard Worker       mtx_unlock(&device->query_mutex);
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
508*61046927SAndroid Build Coastguard Worker          return result;
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker       /* For performance queries, we also need to wait for the relevant syncobj
511*61046927SAndroid Build Coastguard Worker        * to be signaled to ensure completion of the GPU work.
512*61046927SAndroid Build Coastguard Worker        */
513*61046927SAndroid Build Coastguard Worker       if (pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR &&
514*61046927SAndroid Build Coastguard Worker           vk_sync_wait(&device->vk, q->perf.last_job_sync,
515*61046927SAndroid Build Coastguard Worker                        0, VK_SYNC_WAIT_COMPLETE, UINT64_MAX) != VK_SUCCESS) {
516*61046927SAndroid Build Coastguard Worker         return vk_device_set_lost(&device->vk, "Query job wait failed");
517*61046927SAndroid Build Coastguard Worker       }
518*61046927SAndroid Build Coastguard Worker    }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker    return result;
521*61046927SAndroid Build Coastguard Worker }
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker static VkResult
query_check_available(struct v3dv_device * device,struct v3dv_query_pool * pool,struct v3dv_query * q,uint32_t query_idx)524*61046927SAndroid Build Coastguard Worker query_check_available(struct v3dv_device *device,
525*61046927SAndroid Build Coastguard Worker                       struct v3dv_query_pool *pool,
526*61046927SAndroid Build Coastguard Worker                       struct v3dv_query *q,
527*61046927SAndroid Build Coastguard Worker                       uint32_t query_idx)
528*61046927SAndroid Build Coastguard Worker {
529*61046927SAndroid Build Coastguard Worker    /* For occlusion we check the availability BO */
530*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_OCCLUSION) {
531*61046927SAndroid Build Coastguard Worker       const uint8_t *q_addr = ((uint8_t *) pool->occlusion.bo->map) +
532*61046927SAndroid Build Coastguard Worker                               pool->occlusion.avail_offset + query_idx;
533*61046927SAndroid Build Coastguard Worker       return (*q_addr != 0) ? VK_SUCCESS : VK_NOT_READY;
534*61046927SAndroid Build Coastguard Worker    }
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker    /* For timestamp queries, we need to check if the relevant job
537*61046927SAndroid Build Coastguard Worker     * has completed.
538*61046927SAndroid Build Coastguard Worker     */
539*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
540*61046927SAndroid Build Coastguard Worker       if (vk_sync_wait(&device->vk, q->timestamp.sync,
541*61046927SAndroid Build Coastguard Worker                        0, VK_SYNC_WAIT_COMPLETE, 0) != VK_SUCCESS) {
542*61046927SAndroid Build Coastguard Worker          return VK_NOT_READY;
543*61046927SAndroid Build Coastguard Worker       }
544*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
545*61046927SAndroid Build Coastguard Worker    }
546*61046927SAndroid Build Coastguard Worker 
547*61046927SAndroid Build Coastguard Worker    /* For other queries we need to check if the queue has submitted the query
548*61046927SAndroid Build Coastguard Worker     * for execution at all.
549*61046927SAndroid Build Coastguard Worker     */
550*61046927SAndroid Build Coastguard Worker    assert(pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
551*61046927SAndroid Build Coastguard Worker    if (!q->maybe_available)
552*61046927SAndroid Build Coastguard Worker       return VK_NOT_READY;
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    /* For performance queries, we also need to check if the relevant GPU job
555*61046927SAndroid Build Coastguard Worker     * has completed.
556*61046927SAndroid Build Coastguard Worker     */
557*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR &&
558*61046927SAndroid Build Coastguard Worker        vk_sync_wait(&device->vk, q->perf.last_job_sync,
559*61046927SAndroid Build Coastguard Worker                     0, VK_SYNC_WAIT_COMPLETE, 0) != VK_SUCCESS) {
560*61046927SAndroid Build Coastguard Worker          return VK_NOT_READY;
561*61046927SAndroid Build Coastguard Worker    }
562*61046927SAndroid Build Coastguard Worker 
563*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
564*61046927SAndroid Build Coastguard Worker }
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker static VkResult
query_is_available(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query,bool do_wait,bool * available)567*61046927SAndroid Build Coastguard Worker query_is_available(struct v3dv_device *device,
568*61046927SAndroid Build Coastguard Worker                    struct v3dv_query_pool *pool,
569*61046927SAndroid Build Coastguard Worker                    uint32_t query,
570*61046927SAndroid Build Coastguard Worker                    bool do_wait,
571*61046927SAndroid Build Coastguard Worker                    bool *available)
572*61046927SAndroid Build Coastguard Worker {
573*61046927SAndroid Build Coastguard Worker    struct v3dv_query *q = &pool->queries[query];
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker    if (do_wait) {
576*61046927SAndroid Build Coastguard Worker       VkResult result = query_wait_available(device, pool, q, query);
577*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
578*61046927SAndroid Build Coastguard Worker          *available = false;
579*61046927SAndroid Build Coastguard Worker          return result;
580*61046927SAndroid Build Coastguard Worker       }
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker       *available = true;
583*61046927SAndroid Build Coastguard Worker    } else {
584*61046927SAndroid Build Coastguard Worker       VkResult result = query_check_available(device, pool, q, query);
585*61046927SAndroid Build Coastguard Worker       assert(result == VK_SUCCESS || result == VK_NOT_READY);
586*61046927SAndroid Build Coastguard Worker       *available = (result == VK_SUCCESS);
587*61046927SAndroid Build Coastguard Worker    }
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
590*61046927SAndroid Build Coastguard Worker }
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker static VkResult
write_occlusion_query_result(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query,bool do_64bit,void * data,uint32_t slot)593*61046927SAndroid Build Coastguard Worker write_occlusion_query_result(struct v3dv_device *device,
594*61046927SAndroid Build Coastguard Worker                              struct v3dv_query_pool *pool,
595*61046927SAndroid Build Coastguard Worker                              uint32_t query,
596*61046927SAndroid Build Coastguard Worker                              bool do_64bit,
597*61046927SAndroid Build Coastguard Worker                              void *data,
598*61046927SAndroid Build Coastguard Worker                              uint32_t slot)
599*61046927SAndroid Build Coastguard Worker {
600*61046927SAndroid Build Coastguard Worker    assert(pool && pool->query_type == VK_QUERY_TYPE_OCCLUSION);
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker    if (vk_device_is_lost(&device->vk))
603*61046927SAndroid Build Coastguard Worker       return VK_ERROR_DEVICE_LOST;
604*61046927SAndroid Build Coastguard Worker 
605*61046927SAndroid Build Coastguard Worker    struct v3dv_query *q = &pool->queries[query];
606*61046927SAndroid Build Coastguard Worker    assert(pool->occlusion.bo && pool->occlusion.bo->map);
607*61046927SAndroid Build Coastguard Worker 
608*61046927SAndroid Build Coastguard Worker    const uint8_t *query_addr =
609*61046927SAndroid Build Coastguard Worker       ((uint8_t *) pool->occlusion.bo->map) + q->occlusion.offset;
610*61046927SAndroid Build Coastguard Worker    write_to_buffer(data, slot, do_64bit, (uint64_t) *((uint32_t *)query_addr));
611*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
612*61046927SAndroid Build Coastguard Worker }
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker static VkResult
write_timestamp_query_result(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query,bool do_64bit,void * data,uint32_t slot)615*61046927SAndroid Build Coastguard Worker write_timestamp_query_result(struct v3dv_device *device,
616*61046927SAndroid Build Coastguard Worker                              struct v3dv_query_pool *pool,
617*61046927SAndroid Build Coastguard Worker                              uint32_t query,
618*61046927SAndroid Build Coastguard Worker                              bool do_64bit,
619*61046927SAndroid Build Coastguard Worker                              void *data,
620*61046927SAndroid Build Coastguard Worker                              uint32_t slot)
621*61046927SAndroid Build Coastguard Worker {
622*61046927SAndroid Build Coastguard Worker    assert(pool && pool->query_type == VK_QUERY_TYPE_TIMESTAMP);
623*61046927SAndroid Build Coastguard Worker 
624*61046927SAndroid Build Coastguard Worker    struct v3dv_query *q = &pool->queries[query];
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker    const uint8_t *query_addr =
627*61046927SAndroid Build Coastguard Worker       ((uint8_t *) pool->timestamp.bo->map) + q->timestamp.offset;
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker    write_to_buffer(data, slot, do_64bit, *((uint64_t *)query_addr));
630*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
631*61046927SAndroid Build Coastguard Worker }
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker static VkResult
write_performance_query_result(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query,bool do_64bit,void * data,uint32_t slot)634*61046927SAndroid Build Coastguard Worker write_performance_query_result(struct v3dv_device *device,
635*61046927SAndroid Build Coastguard Worker                                struct v3dv_query_pool *pool,
636*61046927SAndroid Build Coastguard Worker                                uint32_t query,
637*61046927SAndroid Build Coastguard Worker                                bool do_64bit,
638*61046927SAndroid Build Coastguard Worker                                void *data,
639*61046927SAndroid Build Coastguard Worker                                uint32_t slot)
640*61046927SAndroid Build Coastguard Worker {
641*61046927SAndroid Build Coastguard Worker    assert(pool && pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker    struct v3dv_query *q = &pool->queries[query];
644*61046927SAndroid Build Coastguard Worker    uint64_t counter_values[V3D_MAX_PERFCNT];
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pool->perfmon.nperfmons; i++) {
647*61046927SAndroid Build Coastguard Worker       struct drm_v3d_perfmon_get_values req = {
648*61046927SAndroid Build Coastguard Worker          .id = q->perf.kperfmon_ids[i],
649*61046927SAndroid Build Coastguard Worker          .values_ptr = (uintptr_t)(&counter_values[i *
650*61046927SAndroid Build Coastguard Worker                                    DRM_V3D_MAX_PERF_COUNTERS])
651*61046927SAndroid Build Coastguard Worker       };
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker       int ret = v3dv_ioctl(device->pdevice->render_fd,
654*61046927SAndroid Build Coastguard Worker                            DRM_IOCTL_V3D_PERFMON_GET_VALUES,
655*61046927SAndroid Build Coastguard Worker                            &req);
656*61046927SAndroid Build Coastguard Worker 
657*61046927SAndroid Build Coastguard Worker       if (ret) {
658*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "failed to get perfmon values: %s\n", strerror(errno));
659*61046927SAndroid Build Coastguard Worker          return vk_error(device, VK_ERROR_DEVICE_LOST);
660*61046927SAndroid Build Coastguard Worker       }
661*61046927SAndroid Build Coastguard Worker    }
662*61046927SAndroid Build Coastguard Worker 
663*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pool->perfmon.ncounters; i++)
664*61046927SAndroid Build Coastguard Worker       write_to_buffer(data, slot + i, do_64bit, counter_values[i]);
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
667*61046927SAndroid Build Coastguard Worker }
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker static VkResult
write_query_result(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t query,bool do_64bit,void * data,uint32_t slot)670*61046927SAndroid Build Coastguard Worker write_query_result(struct v3dv_device *device,
671*61046927SAndroid Build Coastguard Worker                    struct v3dv_query_pool *pool,
672*61046927SAndroid Build Coastguard Worker                    uint32_t query,
673*61046927SAndroid Build Coastguard Worker                    bool do_64bit,
674*61046927SAndroid Build Coastguard Worker                    void *data,
675*61046927SAndroid Build Coastguard Worker                    uint32_t slot)
676*61046927SAndroid Build Coastguard Worker {
677*61046927SAndroid Build Coastguard Worker    switch (pool->query_type) {
678*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_OCCLUSION:
679*61046927SAndroid Build Coastguard Worker       return write_occlusion_query_result(device, pool, query, do_64bit,
680*61046927SAndroid Build Coastguard Worker                                           data, slot);
681*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_TIMESTAMP:
682*61046927SAndroid Build Coastguard Worker       return write_timestamp_query_result(device, pool, query, do_64bit,
683*61046927SAndroid Build Coastguard Worker                                           data, slot);
684*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
685*61046927SAndroid Build Coastguard Worker       return write_performance_query_result(device, pool, query, do_64bit,
686*61046927SAndroid Build Coastguard Worker                                             data, slot);
687*61046927SAndroid Build Coastguard Worker    default:
688*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported query type");
689*61046927SAndroid Build Coastguard Worker    }
690*61046927SAndroid Build Coastguard Worker }
691*61046927SAndroid Build Coastguard Worker 
692*61046927SAndroid Build Coastguard Worker static uint32_t
get_query_result_count(struct v3dv_query_pool * pool)693*61046927SAndroid Build Coastguard Worker get_query_result_count(struct v3dv_query_pool *pool)
694*61046927SAndroid Build Coastguard Worker {
695*61046927SAndroid Build Coastguard Worker    switch (pool->query_type) {
696*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_OCCLUSION:
697*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_TIMESTAMP:
698*61046927SAndroid Build Coastguard Worker       return 1;
699*61046927SAndroid Build Coastguard Worker    case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
700*61046927SAndroid Build Coastguard Worker       return pool->perfmon.ncounters;
701*61046927SAndroid Build Coastguard Worker    default:
702*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported query type");
703*61046927SAndroid Build Coastguard Worker    }
704*61046927SAndroid Build Coastguard Worker }
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker VkResult
v3dv_get_query_pool_results_cpu(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t first,uint32_t count,void * data,VkDeviceSize stride,VkQueryResultFlags flags)707*61046927SAndroid Build Coastguard Worker v3dv_get_query_pool_results_cpu(struct v3dv_device *device,
708*61046927SAndroid Build Coastguard Worker                                 struct v3dv_query_pool *pool,
709*61046927SAndroid Build Coastguard Worker                                 uint32_t first,
710*61046927SAndroid Build Coastguard Worker                                 uint32_t count,
711*61046927SAndroid Build Coastguard Worker                                 void *data,
712*61046927SAndroid Build Coastguard Worker                                 VkDeviceSize stride,
713*61046927SAndroid Build Coastguard Worker                                 VkQueryResultFlags flags)
714*61046927SAndroid Build Coastguard Worker {
715*61046927SAndroid Build Coastguard Worker    assert(first < pool->query_count);
716*61046927SAndroid Build Coastguard Worker    assert(first + count <= pool->query_count);
717*61046927SAndroid Build Coastguard Worker    assert(data);
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker    const bool do_64bit = flags & VK_QUERY_RESULT_64_BIT ||
720*61046927SAndroid Build Coastguard Worker       pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR;
721*61046927SAndroid Build Coastguard Worker    const bool do_wait = flags & VK_QUERY_RESULT_WAIT_BIT;
722*61046927SAndroid Build Coastguard Worker    const bool do_partial = flags & VK_QUERY_RESULT_PARTIAL_BIT;
723*61046927SAndroid Build Coastguard Worker 
724*61046927SAndroid Build Coastguard Worker    uint32_t result_count = get_query_result_count(pool);
725*61046927SAndroid Build Coastguard Worker 
726*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
727*61046927SAndroid Build Coastguard Worker    for (uint32_t i = first; i < first + count; i++) {
728*61046927SAndroid Build Coastguard Worker       bool available = false;
729*61046927SAndroid Build Coastguard Worker       VkResult query_result =
730*61046927SAndroid Build Coastguard Worker          query_is_available(device, pool, i, do_wait, &available);
731*61046927SAndroid Build Coastguard Worker       if (query_result == VK_ERROR_DEVICE_LOST)
732*61046927SAndroid Build Coastguard Worker          result = VK_ERROR_DEVICE_LOST;
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker       /**
735*61046927SAndroid Build Coastguard Worker        * From the Vulkan 1.0 spec:
736*61046927SAndroid Build Coastguard Worker        *
737*61046927SAndroid Build Coastguard Worker        *    "If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are
738*61046927SAndroid Build Coastguard Worker        *     both not set then no result values are written to pData for queries
739*61046927SAndroid Build Coastguard Worker        *     that are in the unavailable state at the time of the call, and
740*61046927SAndroid Build Coastguard Worker        *     vkGetQueryPoolResults returns VK_NOT_READY. However, availability
741*61046927SAndroid Build Coastguard Worker        *     state is still written to pData for those queries if
742*61046927SAndroid Build Coastguard Worker        *     VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set."
743*61046927SAndroid Build Coastguard Worker        */
744*61046927SAndroid Build Coastguard Worker       uint32_t slot = 0;
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker       const bool write_result = available || do_partial;
747*61046927SAndroid Build Coastguard Worker       if (write_result)
748*61046927SAndroid Build Coastguard Worker          write_query_result(device, pool, i, do_64bit, data, slot);
749*61046927SAndroid Build Coastguard Worker       slot += result_count;
750*61046927SAndroid Build Coastguard Worker 
751*61046927SAndroid Build Coastguard Worker       if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
752*61046927SAndroid Build Coastguard Worker          write_to_buffer(data, slot++, do_64bit, available ? 1u : 0u);
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker       if (!write_result && result != VK_ERROR_DEVICE_LOST)
755*61046927SAndroid Build Coastguard Worker          result = VK_NOT_READY;
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker       data += stride;
758*61046927SAndroid Build Coastguard Worker    }
759*61046927SAndroid Build Coastguard Worker 
760*61046927SAndroid Build Coastguard Worker    return result;
761*61046927SAndroid Build Coastguard Worker }
762*61046927SAndroid Build Coastguard Worker 
763*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetQueryPoolResults(VkDevice _device,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount,size_t dataSize,void * pData,VkDeviceSize stride,VkQueryResultFlags flags)764*61046927SAndroid Build Coastguard Worker v3dv_GetQueryPoolResults(VkDevice _device,
765*61046927SAndroid Build Coastguard Worker                          VkQueryPool queryPool,
766*61046927SAndroid Build Coastguard Worker                          uint32_t firstQuery,
767*61046927SAndroid Build Coastguard Worker                          uint32_t queryCount,
768*61046927SAndroid Build Coastguard Worker                          size_t dataSize,
769*61046927SAndroid Build Coastguard Worker                          void *pData,
770*61046927SAndroid Build Coastguard Worker                          VkDeviceSize stride,
771*61046927SAndroid Build Coastguard Worker                          VkQueryResultFlags flags)
772*61046927SAndroid Build Coastguard Worker {
773*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_device, device, _device);
774*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
775*61046927SAndroid Build Coastguard Worker 
776*61046927SAndroid Build Coastguard Worker    if (vk_device_is_lost(&device->vk))
777*61046927SAndroid Build Coastguard Worker       return VK_ERROR_DEVICE_LOST;
778*61046927SAndroid Build Coastguard Worker 
779*61046927SAndroid Build Coastguard Worker    return v3dv_get_query_pool_results_cpu(device, pool, firstQuery, queryCount,
780*61046927SAndroid Build Coastguard Worker                                           pData, stride, flags);
781*61046927SAndroid Build Coastguard Worker }
782*61046927SAndroid Build Coastguard Worker 
783*61046927SAndroid Build Coastguard Worker /* Emits a series of vkCmdDispatchBase calls to execute all the workgroups
784*61046927SAndroid Build Coastguard Worker  * required to handle a number of queries considering per-dispatch limits.
785*61046927SAndroid Build Coastguard Worker  */
786*61046927SAndroid Build Coastguard Worker static void
cmd_buffer_emit_dispatch_queries(struct v3dv_cmd_buffer * cmd_buffer,uint32_t query_count)787*61046927SAndroid Build Coastguard Worker cmd_buffer_emit_dispatch_queries(struct v3dv_cmd_buffer *cmd_buffer,
788*61046927SAndroid Build Coastguard Worker                                  uint32_t query_count)
789*61046927SAndroid Build Coastguard Worker {
790*61046927SAndroid Build Coastguard Worker    VkCommandBuffer vk_cmd_buffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
791*61046927SAndroid Build Coastguard Worker 
792*61046927SAndroid Build Coastguard Worker    uint32_t dispatched = 0;
793*61046927SAndroid Build Coastguard Worker    const uint32_t max_batch_size = 65535;
794*61046927SAndroid Build Coastguard Worker    while (dispatched < query_count) {
795*61046927SAndroid Build Coastguard Worker       uint32_t batch_size = MIN2(query_count - dispatched, max_batch_size);
796*61046927SAndroid Build Coastguard Worker       v3dv_CmdDispatchBase(vk_cmd_buffer, dispatched, 0, 0, batch_size, 1, 1);
797*61046927SAndroid Build Coastguard Worker       dispatched += batch_size;
798*61046927SAndroid Build Coastguard Worker    }
799*61046927SAndroid Build Coastguard Worker }
800*61046927SAndroid Build Coastguard Worker 
801*61046927SAndroid Build Coastguard Worker void
v3dv_cmd_buffer_emit_set_query_availability(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_query_pool * pool,uint32_t query,uint32_t count,uint8_t availability)802*61046927SAndroid Build Coastguard Worker v3dv_cmd_buffer_emit_set_query_availability(struct v3dv_cmd_buffer *cmd_buffer,
803*61046927SAndroid Build Coastguard Worker                                             struct v3dv_query_pool *pool,
804*61046927SAndroid Build Coastguard Worker                                             uint32_t query, uint32_t count,
805*61046927SAndroid Build Coastguard Worker                                             uint8_t availability)
806*61046927SAndroid Build Coastguard Worker {
807*61046927SAndroid Build Coastguard Worker    assert(pool->query_type == VK_QUERY_TYPE_OCCLUSION ||
808*61046927SAndroid Build Coastguard Worker           pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
809*61046927SAndroid Build Coastguard Worker 
810*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = cmd_buffer->device;
811*61046927SAndroid Build Coastguard Worker    VkCommandBuffer vk_cmd_buffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
812*61046927SAndroid Build Coastguard Worker 
813*61046927SAndroid Build Coastguard Worker    /* We are about to emit a compute job to set query availability and we need
814*61046927SAndroid Build Coastguard Worker     * to ensure this executes after the graphics work using the queries has
815*61046927SAndroid Build Coastguard Worker     * completed.
816*61046927SAndroid Build Coastguard Worker     */
817*61046927SAndroid Build Coastguard Worker    VkMemoryBarrier2 barrier = {
818*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
819*61046927SAndroid Build Coastguard Worker       .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
820*61046927SAndroid Build Coastguard Worker       .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
821*61046927SAndroid Build Coastguard Worker    };
822*61046927SAndroid Build Coastguard Worker    VkDependencyInfo barrier_info = {
823*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
824*61046927SAndroid Build Coastguard Worker       .memoryBarrierCount = 1,
825*61046927SAndroid Build Coastguard Worker       .pMemoryBarriers = &barrier,
826*61046927SAndroid Build Coastguard Worker    };
827*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &barrier_info);
828*61046927SAndroid Build Coastguard Worker 
829*61046927SAndroid Build Coastguard Worker    /* Dispatch queries */
830*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
831*61046927SAndroid Build Coastguard Worker 
832*61046927SAndroid Build Coastguard Worker    v3dv_CmdBindPipeline(vk_cmd_buffer,
833*61046927SAndroid Build Coastguard Worker                         VK_PIPELINE_BIND_POINT_COMPUTE,
834*61046927SAndroid Build Coastguard Worker                         device->queries.avail_pipeline);
835*61046927SAndroid Build Coastguard Worker 
836*61046927SAndroid Build Coastguard Worker    v3dv_CmdBindDescriptorSets(vk_cmd_buffer,
837*61046927SAndroid Build Coastguard Worker                               VK_PIPELINE_BIND_POINT_COMPUTE,
838*61046927SAndroid Build Coastguard Worker                               device->queries.avail_pipeline_layout,
839*61046927SAndroid Build Coastguard Worker                               0, 1, &pool->meta.descriptor_set,
840*61046927SAndroid Build Coastguard Worker                               0, NULL);
841*61046927SAndroid Build Coastguard Worker 
842*61046927SAndroid Build Coastguard Worker    struct {
843*61046927SAndroid Build Coastguard Worker       uint32_t offset;
844*61046927SAndroid Build Coastguard Worker       uint32_t query;
845*61046927SAndroid Build Coastguard Worker       uint8_t availability;
846*61046927SAndroid Build Coastguard Worker    } push_data = { pool->occlusion.avail_offset, query, availability };
847*61046927SAndroid Build Coastguard Worker    v3dv_CmdPushConstants(vk_cmd_buffer,
848*61046927SAndroid Build Coastguard Worker                          device->queries.avail_pipeline_layout,
849*61046927SAndroid Build Coastguard Worker                          VK_SHADER_STAGE_COMPUTE_BIT,
850*61046927SAndroid Build Coastguard Worker                          0, sizeof(push_data), &push_data);
851*61046927SAndroid Build Coastguard Worker    cmd_buffer_emit_dispatch_queries(cmd_buffer, count);
852*61046927SAndroid Build Coastguard Worker 
853*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_meta_state_pop(cmd_buffer, false);
854*61046927SAndroid Build Coastguard Worker }
855*61046927SAndroid Build Coastguard Worker 
856*61046927SAndroid Build Coastguard Worker static void
cmd_buffer_emit_reset_occlusion_query_pool(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_query_pool * pool,uint32_t query,uint32_t count)857*61046927SAndroid Build Coastguard Worker cmd_buffer_emit_reset_occlusion_query_pool(struct v3dv_cmd_buffer *cmd_buffer,
858*61046927SAndroid Build Coastguard Worker                                            struct v3dv_query_pool *pool,
859*61046927SAndroid Build Coastguard Worker                                            uint32_t query, uint32_t count)
860*61046927SAndroid Build Coastguard Worker {
861*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = cmd_buffer->device;
862*61046927SAndroid Build Coastguard Worker    VkCommandBuffer vk_cmd_buffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
863*61046927SAndroid Build Coastguard Worker 
864*61046927SAndroid Build Coastguard Worker    /* Ensure the GPU is done with the queries in the graphics queue before
865*61046927SAndroid Build Coastguard Worker     * we reset in the compute queue.
866*61046927SAndroid Build Coastguard Worker     */
867*61046927SAndroid Build Coastguard Worker    VkMemoryBarrier2 barrier = {
868*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
869*61046927SAndroid Build Coastguard Worker       .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
870*61046927SAndroid Build Coastguard Worker       .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
871*61046927SAndroid Build Coastguard Worker    };
872*61046927SAndroid Build Coastguard Worker    VkDependencyInfo barrier_info = {
873*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
874*61046927SAndroid Build Coastguard Worker       .memoryBarrierCount = 1,
875*61046927SAndroid Build Coastguard Worker       .pMemoryBarriers = &barrier,
876*61046927SAndroid Build Coastguard Worker    };
877*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &barrier_info);
878*61046927SAndroid Build Coastguard Worker 
879*61046927SAndroid Build Coastguard Worker    /* Emit compute reset */
880*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
881*61046927SAndroid Build Coastguard Worker 
882*61046927SAndroid Build Coastguard Worker    v3dv_CmdBindPipeline(vk_cmd_buffer,
883*61046927SAndroid Build Coastguard Worker                         VK_PIPELINE_BIND_POINT_COMPUTE,
884*61046927SAndroid Build Coastguard Worker                         device->queries.reset_occlusion_pipeline);
885*61046927SAndroid Build Coastguard Worker 
886*61046927SAndroid Build Coastguard Worker    v3dv_CmdBindDescriptorSets(vk_cmd_buffer,
887*61046927SAndroid Build Coastguard Worker                               VK_PIPELINE_BIND_POINT_COMPUTE,
888*61046927SAndroid Build Coastguard Worker                               device->queries.reset_occlusion_pipeline_layout,
889*61046927SAndroid Build Coastguard Worker                               0, 1, &pool->meta.descriptor_set,
890*61046927SAndroid Build Coastguard Worker                               0, NULL);
891*61046927SAndroid Build Coastguard Worker    struct {
892*61046927SAndroid Build Coastguard Worker       uint32_t offset;
893*61046927SAndroid Build Coastguard Worker       uint32_t query;
894*61046927SAndroid Build Coastguard Worker    } push_data = { pool->occlusion.avail_offset, query };
895*61046927SAndroid Build Coastguard Worker    v3dv_CmdPushConstants(vk_cmd_buffer,
896*61046927SAndroid Build Coastguard Worker                          device->queries.reset_occlusion_pipeline_layout,
897*61046927SAndroid Build Coastguard Worker                          VK_SHADER_STAGE_COMPUTE_BIT,
898*61046927SAndroid Build Coastguard Worker                          0, sizeof(push_data), &push_data);
899*61046927SAndroid Build Coastguard Worker 
900*61046927SAndroid Build Coastguard Worker    cmd_buffer_emit_dispatch_queries(cmd_buffer, count);
901*61046927SAndroid Build Coastguard Worker 
902*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_meta_state_pop(cmd_buffer, false);
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker    /* Ensure future work in the graphics queue using the queries doesn't start
905*61046927SAndroid Build Coastguard Worker     * before the reset completed.
906*61046927SAndroid Build Coastguard Worker     */
907*61046927SAndroid Build Coastguard Worker    barrier = (VkMemoryBarrier2) {
908*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
909*61046927SAndroid Build Coastguard Worker       .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
910*61046927SAndroid Build Coastguard Worker       .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
911*61046927SAndroid Build Coastguard Worker    };
912*61046927SAndroid Build Coastguard Worker    barrier_info = (VkDependencyInfo) {
913*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
914*61046927SAndroid Build Coastguard Worker       .memoryBarrierCount = 1,
915*61046927SAndroid Build Coastguard Worker       .pMemoryBarriers = &barrier,
916*61046927SAndroid Build Coastguard Worker    };
917*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &barrier_info);
918*61046927SAndroid Build Coastguard Worker }
919*61046927SAndroid Build Coastguard Worker 
920*61046927SAndroid Build Coastguard Worker static void
cmd_buffer_emit_reset_query_pool(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_query_pool * pool,uint32_t first,uint32_t count)921*61046927SAndroid Build Coastguard Worker cmd_buffer_emit_reset_query_pool(struct v3dv_cmd_buffer *cmd_buffer,
922*61046927SAndroid Build Coastguard Worker                                  struct v3dv_query_pool *pool,
923*61046927SAndroid Build Coastguard Worker                                  uint32_t first, uint32_t count)
924*61046927SAndroid Build Coastguard Worker {
925*61046927SAndroid Build Coastguard Worker    assert(pool->query_type == VK_QUERY_TYPE_OCCLUSION);
926*61046927SAndroid Build Coastguard Worker    cmd_buffer_emit_reset_occlusion_query_pool(cmd_buffer, pool, first, count);
927*61046927SAndroid Build Coastguard Worker }
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker static void
cmd_buffer_emit_reset_query_pool_cpu(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_query_pool * pool,uint32_t first,uint32_t count)930*61046927SAndroid Build Coastguard Worker cmd_buffer_emit_reset_query_pool_cpu(struct v3dv_cmd_buffer *cmd_buffer,
931*61046927SAndroid Build Coastguard Worker                                      struct v3dv_query_pool *pool,
932*61046927SAndroid Build Coastguard Worker                                      uint32_t first, uint32_t count)
933*61046927SAndroid Build Coastguard Worker {
934*61046927SAndroid Build Coastguard Worker    assert(pool->query_type != VK_QUERY_TYPE_OCCLUSION);
935*61046927SAndroid Build Coastguard Worker 
936*61046927SAndroid Build Coastguard Worker    struct v3dv_job *job =
937*61046927SAndroid Build Coastguard Worker       v3dv_cmd_buffer_create_cpu_job(cmd_buffer->device,
938*61046927SAndroid Build Coastguard Worker                                      V3DV_JOB_TYPE_CPU_RESET_QUERIES,
939*61046927SAndroid Build Coastguard Worker                                      cmd_buffer, -1);
940*61046927SAndroid Build Coastguard Worker    v3dv_return_if_oom(cmd_buffer, NULL);
941*61046927SAndroid Build Coastguard Worker    job->cpu.query_reset.pool = pool;
942*61046927SAndroid Build Coastguard Worker    job->cpu.query_reset.first = first;
943*61046927SAndroid Build Coastguard Worker    job->cpu.query_reset.count = count;
944*61046927SAndroid Build Coastguard Worker    list_addtail(&job->list_link, &cmd_buffer->jobs);
945*61046927SAndroid Build Coastguard Worker }
946*61046927SAndroid Build Coastguard Worker 
947*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_CmdResetQueryPool(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount)948*61046927SAndroid Build Coastguard Worker v3dv_CmdResetQueryPool(VkCommandBuffer commandBuffer,
949*61046927SAndroid Build Coastguard Worker                        VkQueryPool queryPool,
950*61046927SAndroid Build Coastguard Worker                        uint32_t firstQuery,
951*61046927SAndroid Build Coastguard Worker                        uint32_t queryCount)
952*61046927SAndroid Build Coastguard Worker {
953*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
954*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
955*61046927SAndroid Build Coastguard Worker 
956*61046927SAndroid Build Coastguard Worker    /* Resets can only happen outside a render pass instance so we should not
957*61046927SAndroid Build Coastguard Worker     * be in the middle of job recording.
958*61046927SAndroid Build Coastguard Worker     */
959*61046927SAndroid Build Coastguard Worker    assert(cmd_buffer->state.pass == NULL);
960*61046927SAndroid Build Coastguard Worker    assert(cmd_buffer->state.job == NULL);
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker    assert(firstQuery < pool->query_count);
963*61046927SAndroid Build Coastguard Worker    assert(firstQuery + queryCount <= pool->query_count);
964*61046927SAndroid Build Coastguard Worker 
965*61046927SAndroid Build Coastguard Worker    /* We can reset occlusion queries in the GPU, but for other query types
966*61046927SAndroid Build Coastguard Worker     * we emit a CPU job that will call v3dv_reset_query_pool_cpu when executed
967*61046927SAndroid Build Coastguard Worker     * in the queue.
968*61046927SAndroid Build Coastguard Worker     */
969*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_OCCLUSION) {
970*61046927SAndroid Build Coastguard Worker       cmd_buffer_emit_reset_query_pool(cmd_buffer, pool, firstQuery, queryCount);
971*61046927SAndroid Build Coastguard Worker    } else {
972*61046927SAndroid Build Coastguard Worker       cmd_buffer_emit_reset_query_pool_cpu(cmd_buffer, pool,
973*61046927SAndroid Build Coastguard Worker                                            firstQuery, queryCount);
974*61046927SAndroid Build Coastguard Worker    }
975*61046927SAndroid Build Coastguard Worker }
976*61046927SAndroid Build Coastguard Worker 
977*61046927SAndroid Build Coastguard Worker /**
978*61046927SAndroid Build Coastguard Worker  * Creates a descriptor pool so we can create a descriptors for the destination
979*61046927SAndroid Build Coastguard Worker  * buffers of vkCmdCopyQueryResults for queries where this is implemented in
980*61046927SAndroid Build Coastguard Worker  * the GPU.
981*61046927SAndroid Build Coastguard Worker  */
982*61046927SAndroid Build Coastguard Worker static VkResult
create_storage_buffer_descriptor_pool(struct v3dv_cmd_buffer * cmd_buffer)983*61046927SAndroid Build Coastguard Worker create_storage_buffer_descriptor_pool(struct v3dv_cmd_buffer *cmd_buffer)
984*61046927SAndroid Build Coastguard Worker {
985*61046927SAndroid Build Coastguard Worker    /* If this is not the first pool we create one for this command buffer
986*61046927SAndroid Build Coastguard Worker     * size it based on the size of the currently exhausted pool.
987*61046927SAndroid Build Coastguard Worker     */
988*61046927SAndroid Build Coastguard Worker    uint32_t descriptor_count = 32;
989*61046927SAndroid Build Coastguard Worker    if (cmd_buffer->meta.query.dspool != VK_NULL_HANDLE) {
990*61046927SAndroid Build Coastguard Worker       struct v3dv_descriptor_pool *exhausted_pool =
991*61046927SAndroid Build Coastguard Worker          v3dv_descriptor_pool_from_handle(cmd_buffer->meta.query.dspool);
992*61046927SAndroid Build Coastguard Worker       descriptor_count = MIN2(exhausted_pool->max_entry_count * 2, 1024);
993*61046927SAndroid Build Coastguard Worker    }
994*61046927SAndroid Build Coastguard Worker 
995*61046927SAndroid Build Coastguard Worker    /* Create the descriptor pool */
996*61046927SAndroid Build Coastguard Worker    cmd_buffer->meta.query.dspool = VK_NULL_HANDLE;
997*61046927SAndroid Build Coastguard Worker    VkDescriptorPoolSize pool_size = {
998*61046927SAndroid Build Coastguard Worker       .type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
999*61046927SAndroid Build Coastguard Worker       .descriptorCount = descriptor_count,
1000*61046927SAndroid Build Coastguard Worker    };
1001*61046927SAndroid Build Coastguard Worker    VkDescriptorPoolCreateInfo info = {
1002*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1003*61046927SAndroid Build Coastguard Worker       .maxSets = descriptor_count,
1004*61046927SAndroid Build Coastguard Worker       .poolSizeCount = 1,
1005*61046927SAndroid Build Coastguard Worker       .pPoolSizes = &pool_size,
1006*61046927SAndroid Build Coastguard Worker       .flags = 0,
1007*61046927SAndroid Build Coastguard Worker    };
1008*61046927SAndroid Build Coastguard Worker    VkResult result =
1009*61046927SAndroid Build Coastguard Worker       v3dv_CreateDescriptorPool(v3dv_device_to_handle(cmd_buffer->device),
1010*61046927SAndroid Build Coastguard Worker                                 &info,
1011*61046927SAndroid Build Coastguard Worker                                 &cmd_buffer->device->vk.alloc,
1012*61046927SAndroid Build Coastguard Worker                                 &cmd_buffer->meta.query.dspool);
1013*61046927SAndroid Build Coastguard Worker 
1014*61046927SAndroid Build Coastguard Worker    if (result == VK_SUCCESS) {
1015*61046927SAndroid Build Coastguard Worker       assert(cmd_buffer->meta.query.dspool != VK_NULL_HANDLE);
1016*61046927SAndroid Build Coastguard Worker       const VkDescriptorPool vk_pool = cmd_buffer->meta.query.dspool;
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker       v3dv_cmd_buffer_add_private_obj(
1019*61046927SAndroid Build Coastguard Worker          cmd_buffer, (uintptr_t) vk_pool,
1020*61046927SAndroid Build Coastguard Worker          (v3dv_cmd_buffer_private_obj_destroy_cb)v3dv_DestroyDescriptorPool);
1021*61046927SAndroid Build Coastguard Worker 
1022*61046927SAndroid Build Coastguard Worker       struct v3dv_descriptor_pool *pool =
1023*61046927SAndroid Build Coastguard Worker          v3dv_descriptor_pool_from_handle(vk_pool);
1024*61046927SAndroid Build Coastguard Worker       pool->is_driver_internal = true;
1025*61046927SAndroid Build Coastguard Worker    }
1026*61046927SAndroid Build Coastguard Worker 
1027*61046927SAndroid Build Coastguard Worker    return result;
1028*61046927SAndroid Build Coastguard Worker }
1029*61046927SAndroid Build Coastguard Worker 
1030*61046927SAndroid Build Coastguard Worker static VkResult
allocate_storage_buffer_descriptor_set(struct v3dv_cmd_buffer * cmd_buffer,VkDescriptorSet * set)1031*61046927SAndroid Build Coastguard Worker allocate_storage_buffer_descriptor_set(struct v3dv_cmd_buffer *cmd_buffer,
1032*61046927SAndroid Build Coastguard Worker                                        VkDescriptorSet *set)
1033*61046927SAndroid Build Coastguard Worker {
1034*61046927SAndroid Build Coastguard Worker    /* Make sure we have a descriptor pool */
1035*61046927SAndroid Build Coastguard Worker    VkResult result;
1036*61046927SAndroid Build Coastguard Worker    if (cmd_buffer->meta.query.dspool == VK_NULL_HANDLE) {
1037*61046927SAndroid Build Coastguard Worker       result = create_storage_buffer_descriptor_pool(cmd_buffer);
1038*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1039*61046927SAndroid Build Coastguard Worker          return result;
1040*61046927SAndroid Build Coastguard Worker    }
1041*61046927SAndroid Build Coastguard Worker    assert(cmd_buffer->meta.query.dspool != VK_NULL_HANDLE);
1042*61046927SAndroid Build Coastguard Worker 
1043*61046927SAndroid Build Coastguard Worker    /* Allocate descriptor set */
1044*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = cmd_buffer->device;
1045*61046927SAndroid Build Coastguard Worker    VkDevice vk_device = v3dv_device_to_handle(device);
1046*61046927SAndroid Build Coastguard Worker    VkDescriptorSetAllocateInfo info = {
1047*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1048*61046927SAndroid Build Coastguard Worker       .descriptorPool = cmd_buffer->meta.query.dspool,
1049*61046927SAndroid Build Coastguard Worker       .descriptorSetCount = 1,
1050*61046927SAndroid Build Coastguard Worker       .pSetLayouts = &device->queries.buf_descriptor_set_layout,
1051*61046927SAndroid Build Coastguard Worker    };
1052*61046927SAndroid Build Coastguard Worker    result = v3dv_AllocateDescriptorSets(vk_device, &info, set);
1053*61046927SAndroid Build Coastguard Worker 
1054*61046927SAndroid Build Coastguard Worker    /* If we ran out of pool space, grow the pool and try again */
1055*61046927SAndroid Build Coastguard Worker    if (result == VK_ERROR_OUT_OF_POOL_MEMORY) {
1056*61046927SAndroid Build Coastguard Worker       result = create_storage_buffer_descriptor_pool(cmd_buffer);
1057*61046927SAndroid Build Coastguard Worker       if (result == VK_SUCCESS) {
1058*61046927SAndroid Build Coastguard Worker          info.descriptorPool = cmd_buffer->meta.query.dspool;
1059*61046927SAndroid Build Coastguard Worker          result = v3dv_AllocateDescriptorSets(vk_device, &info, set);
1060*61046927SAndroid Build Coastguard Worker       }
1061*61046927SAndroid Build Coastguard Worker    }
1062*61046927SAndroid Build Coastguard Worker 
1063*61046927SAndroid Build Coastguard Worker    return result;
1064*61046927SAndroid Build Coastguard Worker }
1065*61046927SAndroid Build Coastguard Worker 
1066*61046927SAndroid Build Coastguard Worker static uint32_t
copy_pipeline_index_from_flags(VkQueryResultFlags flags)1067*61046927SAndroid Build Coastguard Worker copy_pipeline_index_from_flags(VkQueryResultFlags flags)
1068*61046927SAndroid Build Coastguard Worker {
1069*61046927SAndroid Build Coastguard Worker    uint32_t index = 0;
1070*61046927SAndroid Build Coastguard Worker    if (flags & VK_QUERY_RESULT_64_BIT)
1071*61046927SAndroid Build Coastguard Worker       index |= 1;
1072*61046927SAndroid Build Coastguard Worker    if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
1073*61046927SAndroid Build Coastguard Worker       index |= 2;
1074*61046927SAndroid Build Coastguard Worker    if (flags & VK_QUERY_RESULT_PARTIAL_BIT)
1075*61046927SAndroid Build Coastguard Worker       index |= 4;
1076*61046927SAndroid Build Coastguard Worker    assert(index < 8);
1077*61046927SAndroid Build Coastguard Worker    return index;
1078*61046927SAndroid Build Coastguard Worker }
1079*61046927SAndroid Build Coastguard Worker 
1080*61046927SAndroid Build Coastguard Worker static nir_shader *
1081*61046927SAndroid Build Coastguard Worker get_copy_query_results_cs(const nir_shader_compiler_options *compiler_options,
1082*61046927SAndroid Build Coastguard Worker                           VkQueryResultFlags flags);
1083*61046927SAndroid Build Coastguard Worker 
1084*61046927SAndroid Build Coastguard Worker static void
cmd_buffer_emit_copy_query_pool_results(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_query_pool * pool,uint32_t first,uint32_t count,struct v3dv_buffer * buf,uint32_t offset,uint32_t stride,VkQueryResultFlags flags)1085*61046927SAndroid Build Coastguard Worker cmd_buffer_emit_copy_query_pool_results(struct v3dv_cmd_buffer *cmd_buffer,
1086*61046927SAndroid Build Coastguard Worker                                         struct v3dv_query_pool *pool,
1087*61046927SAndroid Build Coastguard Worker                                         uint32_t first, uint32_t count,
1088*61046927SAndroid Build Coastguard Worker                                         struct v3dv_buffer *buf,
1089*61046927SAndroid Build Coastguard Worker                                         uint32_t offset, uint32_t stride,
1090*61046927SAndroid Build Coastguard Worker                                         VkQueryResultFlags flags)
1091*61046927SAndroid Build Coastguard Worker {
1092*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = cmd_buffer->device;
1093*61046927SAndroid Build Coastguard Worker    VkDevice vk_device = v3dv_device_to_handle(device);
1094*61046927SAndroid Build Coastguard Worker    VkCommandBuffer vk_cmd_buffer = v3dv_cmd_buffer_to_handle(cmd_buffer);
1095*61046927SAndroid Build Coastguard Worker 
1096*61046927SAndroid Build Coastguard Worker    /* Create the required copy pipeline if not yet created */
1097*61046927SAndroid Build Coastguard Worker    uint32_t pipeline_idx = copy_pipeline_index_from_flags(flags);
1098*61046927SAndroid Build Coastguard Worker    if (!device->queries.copy_pipeline[pipeline_idx]) {
1099*61046927SAndroid Build Coastguard Worker       const nir_shader_compiler_options *compiler_options =
1100*61046927SAndroid Build Coastguard Worker          v3dv_pipeline_get_nir_options(&device->devinfo);
1101*61046927SAndroid Build Coastguard Worker       nir_shader *copy_query_results_cs_nir =
1102*61046927SAndroid Build Coastguard Worker          get_copy_query_results_cs(compiler_options, flags);
1103*61046927SAndroid Build Coastguard Worker       VkResult result =
1104*61046927SAndroid Build Coastguard Worker          v3dv_create_compute_pipeline_from_nir(
1105*61046927SAndroid Build Coastguard Worker                device, copy_query_results_cs_nir,
1106*61046927SAndroid Build Coastguard Worker                device->queries.copy_pipeline_layout,
1107*61046927SAndroid Build Coastguard Worker                &device->queries.copy_pipeline[pipeline_idx]);
1108*61046927SAndroid Build Coastguard Worker       ralloc_free(copy_query_results_cs_nir);
1109*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
1110*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Failed to create copy query results pipeline\n");
1111*61046927SAndroid Build Coastguard Worker          return;
1112*61046927SAndroid Build Coastguard Worker       }
1113*61046927SAndroid Build Coastguard Worker    }
1114*61046927SAndroid Build Coastguard Worker 
1115*61046927SAndroid Build Coastguard Worker    /* FIXME: do we need this barrier? Since vkCmdEndQuery should've been called
1116*61046927SAndroid Build Coastguard Worker     * and that already waits maybe we don't (since this is serialized
1117*61046927SAndroid Build Coastguard Worker     * in the compute queue with EndQuery anyway).
1118*61046927SAndroid Build Coastguard Worker     */
1119*61046927SAndroid Build Coastguard Worker    if (flags & VK_QUERY_RESULT_WAIT_BIT) {
1120*61046927SAndroid Build Coastguard Worker       VkMemoryBarrier2 barrier = {
1121*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
1122*61046927SAndroid Build Coastguard Worker          .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
1123*61046927SAndroid Build Coastguard Worker          .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
1124*61046927SAndroid Build Coastguard Worker       };
1125*61046927SAndroid Build Coastguard Worker       VkDependencyInfo barrier_info = {
1126*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
1127*61046927SAndroid Build Coastguard Worker          .memoryBarrierCount = 1,
1128*61046927SAndroid Build Coastguard Worker          .pMemoryBarriers = &barrier,
1129*61046927SAndroid Build Coastguard Worker       };
1130*61046927SAndroid Build Coastguard Worker       v3dv_cmd_buffer_emit_pipeline_barrier(cmd_buffer, &barrier_info);
1131*61046927SAndroid Build Coastguard Worker    }
1132*61046927SAndroid Build Coastguard Worker 
1133*61046927SAndroid Build Coastguard Worker    /* Allocate and setup descriptor set for output buffer */
1134*61046927SAndroid Build Coastguard Worker    VkDescriptorSet out_buf_descriptor_set;
1135*61046927SAndroid Build Coastguard Worker    VkResult result =
1136*61046927SAndroid Build Coastguard Worker       allocate_storage_buffer_descriptor_set(cmd_buffer,
1137*61046927SAndroid Build Coastguard Worker                                              &out_buf_descriptor_set);
1138*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
1139*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "vkCmdCopyQueryPoolResults failed: "
1140*61046927SAndroid Build Coastguard Worker               "could not allocate descriptor.\n");
1141*61046927SAndroid Build Coastguard Worker       return;
1142*61046927SAndroid Build Coastguard Worker    }
1143*61046927SAndroid Build Coastguard Worker 
1144*61046927SAndroid Build Coastguard Worker    VkDescriptorBufferInfo desc_buf_info = {
1145*61046927SAndroid Build Coastguard Worker       .buffer = v3dv_buffer_to_handle(buf),
1146*61046927SAndroid Build Coastguard Worker       .offset = 0,
1147*61046927SAndroid Build Coastguard Worker       .range = VK_WHOLE_SIZE,
1148*61046927SAndroid Build Coastguard Worker    };
1149*61046927SAndroid Build Coastguard Worker    VkWriteDescriptorSet write = {
1150*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1151*61046927SAndroid Build Coastguard Worker       .dstSet = out_buf_descriptor_set,
1152*61046927SAndroid Build Coastguard Worker       .dstBinding = 0,
1153*61046927SAndroid Build Coastguard Worker       .dstArrayElement = 0,
1154*61046927SAndroid Build Coastguard Worker       .descriptorCount = 1,
1155*61046927SAndroid Build Coastguard Worker       .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1156*61046927SAndroid Build Coastguard Worker       .pBufferInfo = &desc_buf_info,
1157*61046927SAndroid Build Coastguard Worker    };
1158*61046927SAndroid Build Coastguard Worker    v3dv_UpdateDescriptorSets(vk_device, 1, &write, 0, NULL);
1159*61046927SAndroid Build Coastguard Worker 
1160*61046927SAndroid Build Coastguard Worker    /* Dispatch copy */
1161*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_meta_state_push(cmd_buffer, true);
1162*61046927SAndroid Build Coastguard Worker 
1163*61046927SAndroid Build Coastguard Worker    assert(device->queries.copy_pipeline[pipeline_idx]);
1164*61046927SAndroid Build Coastguard Worker    v3dv_CmdBindPipeline(vk_cmd_buffer,
1165*61046927SAndroid Build Coastguard Worker                         VK_PIPELINE_BIND_POINT_COMPUTE,
1166*61046927SAndroid Build Coastguard Worker                         device->queries.copy_pipeline[pipeline_idx]);
1167*61046927SAndroid Build Coastguard Worker 
1168*61046927SAndroid Build Coastguard Worker    VkDescriptorSet sets[2] = {
1169*61046927SAndroid Build Coastguard Worker       pool->meta.descriptor_set,
1170*61046927SAndroid Build Coastguard Worker       out_buf_descriptor_set,
1171*61046927SAndroid Build Coastguard Worker    };
1172*61046927SAndroid Build Coastguard Worker    v3dv_CmdBindDescriptorSets(vk_cmd_buffer,
1173*61046927SAndroid Build Coastguard Worker                               VK_PIPELINE_BIND_POINT_COMPUTE,
1174*61046927SAndroid Build Coastguard Worker                               device->queries.copy_pipeline_layout,
1175*61046927SAndroid Build Coastguard Worker                               0, 2, sets, 0, NULL);
1176*61046927SAndroid Build Coastguard Worker 
1177*61046927SAndroid Build Coastguard Worker    struct {
1178*61046927SAndroid Build Coastguard Worker       uint32_t avail_offset, first, offset, stride, flags;
1179*61046927SAndroid Build Coastguard Worker    } push_data = { pool->occlusion.avail_offset, first, offset, stride, flags };
1180*61046927SAndroid Build Coastguard Worker    v3dv_CmdPushConstants(vk_cmd_buffer,
1181*61046927SAndroid Build Coastguard Worker                          device->queries.copy_pipeline_layout,
1182*61046927SAndroid Build Coastguard Worker                          VK_SHADER_STAGE_COMPUTE_BIT,
1183*61046927SAndroid Build Coastguard Worker                          0, sizeof(push_data), &push_data);
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker    cmd_buffer_emit_dispatch_queries(cmd_buffer, count);
1186*61046927SAndroid Build Coastguard Worker 
1187*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_meta_state_pop(cmd_buffer, false);
1188*61046927SAndroid Build Coastguard Worker }
1189*61046927SAndroid Build Coastguard Worker 
1190*61046927SAndroid Build Coastguard Worker static void
cmd_buffer_emit_copy_query_pool_results_cpu(struct v3dv_cmd_buffer * cmd_buffer,struct v3dv_query_pool * pool,uint32_t first,uint32_t count,struct v3dv_buffer * dst,uint32_t offset,uint32_t stride,VkQueryResultFlags flags)1191*61046927SAndroid Build Coastguard Worker cmd_buffer_emit_copy_query_pool_results_cpu(struct v3dv_cmd_buffer *cmd_buffer,
1192*61046927SAndroid Build Coastguard Worker                                             struct v3dv_query_pool *pool,
1193*61046927SAndroid Build Coastguard Worker                                             uint32_t first,
1194*61046927SAndroid Build Coastguard Worker                                             uint32_t count,
1195*61046927SAndroid Build Coastguard Worker                                             struct v3dv_buffer *dst,
1196*61046927SAndroid Build Coastguard Worker                                             uint32_t offset,
1197*61046927SAndroid Build Coastguard Worker                                             uint32_t stride,
1198*61046927SAndroid Build Coastguard Worker                                             VkQueryResultFlags flags)
1199*61046927SAndroid Build Coastguard Worker {
1200*61046927SAndroid Build Coastguard Worker    struct v3dv_job *job =
1201*61046927SAndroid Build Coastguard Worker       v3dv_cmd_buffer_create_cpu_job(cmd_buffer->device,
1202*61046927SAndroid Build Coastguard Worker                                      V3DV_JOB_TYPE_CPU_COPY_QUERY_RESULTS,
1203*61046927SAndroid Build Coastguard Worker                                      cmd_buffer, -1);
1204*61046927SAndroid Build Coastguard Worker    v3dv_return_if_oom(cmd_buffer, NULL);
1205*61046927SAndroid Build Coastguard Worker 
1206*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.pool = pool;
1207*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.first = first;
1208*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.count = count;
1209*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.dst = dst;
1210*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.offset = offset;
1211*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.stride = stride;
1212*61046927SAndroid Build Coastguard Worker    job->cpu.query_copy_results.flags = flags;
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker    list_addtail(&job->list_link, &cmd_buffer->jobs);
1215*61046927SAndroid Build Coastguard Worker }
1216*61046927SAndroid Build Coastguard Worker 
1217*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount,VkBuffer dstBuffer,VkDeviceSize dstOffset,VkDeviceSize stride,VkQueryResultFlags flags)1218*61046927SAndroid Build Coastguard Worker v3dv_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
1219*61046927SAndroid Build Coastguard Worker                              VkQueryPool queryPool,
1220*61046927SAndroid Build Coastguard Worker                              uint32_t firstQuery,
1221*61046927SAndroid Build Coastguard Worker                              uint32_t queryCount,
1222*61046927SAndroid Build Coastguard Worker                              VkBuffer dstBuffer,
1223*61046927SAndroid Build Coastguard Worker                              VkDeviceSize dstOffset,
1224*61046927SAndroid Build Coastguard Worker                              VkDeviceSize stride,
1225*61046927SAndroid Build Coastguard Worker                              VkQueryResultFlags flags)
1226*61046927SAndroid Build Coastguard Worker {
1227*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
1228*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
1229*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_buffer, dst, dstBuffer);
1230*61046927SAndroid Build Coastguard Worker 
1231*61046927SAndroid Build Coastguard Worker    /* Copies can only happen outside a render pass instance so we should not
1232*61046927SAndroid Build Coastguard Worker     * be in the middle of job recording.
1233*61046927SAndroid Build Coastguard Worker     */
1234*61046927SAndroid Build Coastguard Worker    assert(cmd_buffer->state.pass == NULL);
1235*61046927SAndroid Build Coastguard Worker    assert(cmd_buffer->state.job == NULL);
1236*61046927SAndroid Build Coastguard Worker 
1237*61046927SAndroid Build Coastguard Worker    assert(firstQuery < pool->query_count);
1238*61046927SAndroid Build Coastguard Worker    assert(firstQuery + queryCount <= pool->query_count);
1239*61046927SAndroid Build Coastguard Worker 
1240*61046927SAndroid Build Coastguard Worker    /* For occlusion queries we implement the copy in the GPU but for other
1241*61046927SAndroid Build Coastguard Worker     * queries we emit a CPU job that will call v3dv_get_query_pool_results_cpu
1242*61046927SAndroid Build Coastguard Worker     * when executed in the queue.
1243*61046927SAndroid Build Coastguard Worker     */
1244*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_OCCLUSION) {
1245*61046927SAndroid Build Coastguard Worker       cmd_buffer_emit_copy_query_pool_results(cmd_buffer, pool,
1246*61046927SAndroid Build Coastguard Worker                                               firstQuery, queryCount,
1247*61046927SAndroid Build Coastguard Worker                                               dst, (uint32_t) dstOffset,
1248*61046927SAndroid Build Coastguard Worker                                               (uint32_t) stride, flags);
1249*61046927SAndroid Build Coastguard Worker    } else {
1250*61046927SAndroid Build Coastguard Worker       cmd_buffer_emit_copy_query_pool_results_cpu(cmd_buffer, pool,
1251*61046927SAndroid Build Coastguard Worker                                                   firstQuery, queryCount,
1252*61046927SAndroid Build Coastguard Worker                                                   dst, (uint32_t)dstOffset,
1253*61046927SAndroid Build Coastguard Worker                                                   (uint32_t) stride, flags);
1254*61046927SAndroid Build Coastguard Worker    }
1255*61046927SAndroid Build Coastguard Worker }
1256*61046927SAndroid Build Coastguard Worker 
1257*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_CmdBeginQuery(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query,VkQueryControlFlags flags)1258*61046927SAndroid Build Coastguard Worker v3dv_CmdBeginQuery(VkCommandBuffer commandBuffer,
1259*61046927SAndroid Build Coastguard Worker                    VkQueryPool queryPool,
1260*61046927SAndroid Build Coastguard Worker                    uint32_t query,
1261*61046927SAndroid Build Coastguard Worker                    VkQueryControlFlags flags)
1262*61046927SAndroid Build Coastguard Worker {
1263*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
1264*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
1265*61046927SAndroid Build Coastguard Worker 
1266*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_begin_query(cmd_buffer, pool, query, flags);
1267*61046927SAndroid Build Coastguard Worker }
1268*61046927SAndroid Build Coastguard Worker 
1269*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_CmdEndQuery(VkCommandBuffer commandBuffer,VkQueryPool queryPool,uint32_t query)1270*61046927SAndroid Build Coastguard Worker v3dv_CmdEndQuery(VkCommandBuffer commandBuffer,
1271*61046927SAndroid Build Coastguard Worker                  VkQueryPool queryPool,
1272*61046927SAndroid Build Coastguard Worker                  uint32_t query)
1273*61046927SAndroid Build Coastguard Worker {
1274*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
1275*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
1276*61046927SAndroid Build Coastguard Worker 
1277*61046927SAndroid Build Coastguard Worker    v3dv_cmd_buffer_end_query(cmd_buffer, pool, query);
1278*61046927SAndroid Build Coastguard Worker }
1279*61046927SAndroid Build Coastguard Worker 
1280*61046927SAndroid Build Coastguard Worker void
v3dv_reset_query_pool_cpu(struct v3dv_device * device,struct v3dv_query_pool * pool,uint32_t first,uint32_t count)1281*61046927SAndroid Build Coastguard Worker v3dv_reset_query_pool_cpu(struct v3dv_device *device,
1282*61046927SAndroid Build Coastguard Worker                           struct v3dv_query_pool *pool,
1283*61046927SAndroid Build Coastguard Worker                           uint32_t first,
1284*61046927SAndroid Build Coastguard Worker                           uint32_t count)
1285*61046927SAndroid Build Coastguard Worker {
1286*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->query_mutex);
1287*61046927SAndroid Build Coastguard Worker 
1288*61046927SAndroid Build Coastguard Worker    if (pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
1289*61046927SAndroid Build Coastguard Worker       assert(first + count <= pool->query_count);
1290*61046927SAndroid Build Coastguard Worker 
1291*61046927SAndroid Build Coastguard Worker       /* Reset timestamp */
1292*61046927SAndroid Build Coastguard Worker       uint8_t *base_addr;
1293*61046927SAndroid Build Coastguard Worker       base_addr  = ((uint8_t *) pool->timestamp.bo->map) +
1294*61046927SAndroid Build Coastguard Worker                     pool->queries[first].timestamp.offset;
1295*61046927SAndroid Build Coastguard Worker       memset(base_addr, 0, 8 * count);
1296*61046927SAndroid Build Coastguard Worker 
1297*61046927SAndroid Build Coastguard Worker       for (uint32_t i = first; i < first + count; i++) {
1298*61046927SAndroid Build Coastguard Worker          if (vk_sync_reset(&device->vk, pool->queries[i].timestamp.sync) != VK_SUCCESS)
1299*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "Failed to reset sync");
1300*61046927SAndroid Build Coastguard Worker       }
1301*61046927SAndroid Build Coastguard Worker 
1302*61046927SAndroid Build Coastguard Worker       mtx_unlock(&device->query_mutex);
1303*61046927SAndroid Build Coastguard Worker       return;
1304*61046927SAndroid Build Coastguard Worker    }
1305*61046927SAndroid Build Coastguard Worker 
1306*61046927SAndroid Build Coastguard Worker    for (uint32_t i = first; i < first + count; i++) {
1307*61046927SAndroid Build Coastguard Worker       assert(i < pool->query_count);
1308*61046927SAndroid Build Coastguard Worker       struct v3dv_query *q = &pool->queries[i];
1309*61046927SAndroid Build Coastguard Worker       q->maybe_available = false;
1310*61046927SAndroid Build Coastguard Worker       switch (pool->query_type) {
1311*61046927SAndroid Build Coastguard Worker       case VK_QUERY_TYPE_OCCLUSION: {
1312*61046927SAndroid Build Coastguard Worker          /* Reset availability */
1313*61046927SAndroid Build Coastguard Worker          uint8_t *base_addr = ((uint8_t *) pool->occlusion.bo->map) +
1314*61046927SAndroid Build Coastguard Worker                               pool->occlusion.avail_offset + first;
1315*61046927SAndroid Build Coastguard Worker          memset(base_addr, 0, count);
1316*61046927SAndroid Build Coastguard Worker 
1317*61046927SAndroid Build Coastguard Worker          /* Reset occlusion counter */
1318*61046927SAndroid Build Coastguard Worker          const uint8_t *q_addr =
1319*61046927SAndroid Build Coastguard Worker             ((uint8_t *) pool->occlusion.bo->map) + q->occlusion.offset;
1320*61046927SAndroid Build Coastguard Worker          uint32_t *counter = (uint32_t *) q_addr;
1321*61046927SAndroid Build Coastguard Worker          *counter = 0;
1322*61046927SAndroid Build Coastguard Worker          break;
1323*61046927SAndroid Build Coastguard Worker       }
1324*61046927SAndroid Build Coastguard Worker       case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
1325*61046927SAndroid Build Coastguard Worker          kperfmon_destroy(device, pool, i);
1326*61046927SAndroid Build Coastguard Worker          kperfmon_create(device, pool, i);
1327*61046927SAndroid Build Coastguard Worker          if (vk_sync_reset(&device->vk, q->perf.last_job_sync) != VK_SUCCESS)
1328*61046927SAndroid Build Coastguard Worker             fprintf(stderr, "Failed to reset sync");
1329*61046927SAndroid Build Coastguard Worker          break;
1330*61046927SAndroid Build Coastguard Worker       default:
1331*61046927SAndroid Build Coastguard Worker          unreachable("Unsupported query type");
1332*61046927SAndroid Build Coastguard Worker       }
1333*61046927SAndroid Build Coastguard Worker    }
1334*61046927SAndroid Build Coastguard Worker 
1335*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->query_mutex);
1336*61046927SAndroid Build Coastguard Worker }
1337*61046927SAndroid Build Coastguard Worker 
1338*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_ResetQueryPool(VkDevice _device,VkQueryPool queryPool,uint32_t firstQuery,uint32_t queryCount)1339*61046927SAndroid Build Coastguard Worker v3dv_ResetQueryPool(VkDevice _device,
1340*61046927SAndroid Build Coastguard Worker                     VkQueryPool queryPool,
1341*61046927SAndroid Build Coastguard Worker                     uint32_t firstQuery,
1342*61046927SAndroid Build Coastguard Worker                     uint32_t queryCount)
1343*61046927SAndroid Build Coastguard Worker {
1344*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_device, device, _device);
1345*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
1346*61046927SAndroid Build Coastguard Worker 
1347*61046927SAndroid Build Coastguard Worker    v3dv_reset_query_pool_cpu(device, pool, firstQuery, queryCount);
1348*61046927SAndroid Build Coastguard Worker }
1349*61046927SAndroid Build Coastguard Worker 
1350*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
v3dv_EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,uint32_t * pCounterCount,VkPerformanceCounterKHR * pCounters,VkPerformanceCounterDescriptionKHR * pCounterDescriptions)1351*61046927SAndroid Build Coastguard Worker v3dv_EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
1352*61046927SAndroid Build Coastguard Worker    VkPhysicalDevice physicalDevice,
1353*61046927SAndroid Build Coastguard Worker    uint32_t queueFamilyIndex,
1354*61046927SAndroid Build Coastguard Worker    uint32_t *pCounterCount,
1355*61046927SAndroid Build Coastguard Worker    VkPerformanceCounterKHR *pCounters,
1356*61046927SAndroid Build Coastguard Worker    VkPerformanceCounterDescriptionKHR *pCounterDescriptions)
1357*61046927SAndroid Build Coastguard Worker {
1358*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_physical_device, pDevice, physicalDevice);
1359*61046927SAndroid Build Coastguard Worker 
1360*61046927SAndroid Build Coastguard Worker    return v3dv_X(pDevice, enumerate_performance_query_counters)(pDevice,
1361*61046927SAndroid Build Coastguard Worker                                                                 pCounterCount,
1362*61046927SAndroid Build Coastguard Worker                                                                 pCounters,
1363*61046927SAndroid Build Coastguard Worker                                                                 pCounterDescriptions);
1364*61046927SAndroid Build Coastguard Worker }
1365*61046927SAndroid Build Coastguard Worker 
1366*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(VkPhysicalDevice physicalDevice,const VkQueryPoolPerformanceCreateInfoKHR * pPerformanceQueryCreateInfo,uint32_t * pNumPasses)1367*61046927SAndroid Build Coastguard Worker v3dv_GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
1368*61046927SAndroid Build Coastguard Worker    VkPhysicalDevice physicalDevice,
1369*61046927SAndroid Build Coastguard Worker    const VkQueryPoolPerformanceCreateInfoKHR *pPerformanceQueryCreateInfo,
1370*61046927SAndroid Build Coastguard Worker    uint32_t *pNumPasses)
1371*61046927SAndroid Build Coastguard Worker {
1372*61046927SAndroid Build Coastguard Worker    *pNumPasses = DIV_ROUND_UP(pPerformanceQueryCreateInfo->counterIndexCount,
1373*61046927SAndroid Build Coastguard Worker                               DRM_V3D_MAX_PERF_COUNTERS);
1374*61046927SAndroid Build Coastguard Worker }
1375*61046927SAndroid Build Coastguard Worker 
1376*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
v3dv_AcquireProfilingLockKHR(VkDevice _device,const VkAcquireProfilingLockInfoKHR * pInfo)1377*61046927SAndroid Build Coastguard Worker v3dv_AcquireProfilingLockKHR(
1378*61046927SAndroid Build Coastguard Worker    VkDevice _device,
1379*61046927SAndroid Build Coastguard Worker    const VkAcquireProfilingLockInfoKHR *pInfo)
1380*61046927SAndroid Build Coastguard Worker {
1381*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1382*61046927SAndroid Build Coastguard Worker }
1383*61046927SAndroid Build Coastguard Worker 
1384*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
v3dv_ReleaseProfilingLockKHR(VkDevice device)1385*61046927SAndroid Build Coastguard Worker v3dv_ReleaseProfilingLockKHR(VkDevice device)
1386*61046927SAndroid Build Coastguard Worker {
1387*61046927SAndroid Build Coastguard Worker }
1388*61046927SAndroid Build Coastguard Worker 
1389*61046927SAndroid Build Coastguard Worker static inline void
nir_set_query_availability(nir_builder * b,nir_def * buf,nir_def * offset,nir_def * query_idx,nir_def * avail)1390*61046927SAndroid Build Coastguard Worker nir_set_query_availability(nir_builder *b,
1391*61046927SAndroid Build Coastguard Worker                            nir_def *buf,
1392*61046927SAndroid Build Coastguard Worker                            nir_def *offset,
1393*61046927SAndroid Build Coastguard Worker                            nir_def *query_idx,
1394*61046927SAndroid Build Coastguard Worker                            nir_def *avail)
1395*61046927SAndroid Build Coastguard Worker {
1396*61046927SAndroid Build Coastguard Worker    offset = nir_iadd(b, offset, query_idx); /* we use 1B per query */
1397*61046927SAndroid Build Coastguard Worker    nir_store_ssbo(b, avail, buf, offset, .write_mask = 0x1, .align_mul = 1);
1398*61046927SAndroid Build Coastguard Worker }
1399*61046927SAndroid Build Coastguard Worker 
1400*61046927SAndroid Build Coastguard Worker static inline nir_def *
nir_get_query_availability(nir_builder * b,nir_def * buf,nir_def * offset,nir_def * query_idx)1401*61046927SAndroid Build Coastguard Worker nir_get_query_availability(nir_builder *b,
1402*61046927SAndroid Build Coastguard Worker                            nir_def *buf,
1403*61046927SAndroid Build Coastguard Worker                            nir_def *offset,
1404*61046927SAndroid Build Coastguard Worker                            nir_def *query_idx)
1405*61046927SAndroid Build Coastguard Worker {
1406*61046927SAndroid Build Coastguard Worker    offset = nir_iadd(b, offset, query_idx); /* we use 1B per query */
1407*61046927SAndroid Build Coastguard Worker    nir_def *avail = nir_load_ssbo(b, 1, 8, buf, offset, .align_mul = 1);
1408*61046927SAndroid Build Coastguard Worker    return nir_i2i32(b, avail);
1409*61046927SAndroid Build Coastguard Worker }
1410*61046927SAndroid Build Coastguard Worker 
1411*61046927SAndroid Build Coastguard Worker static nir_shader *
get_set_query_availability_cs(const nir_shader_compiler_options * options)1412*61046927SAndroid Build Coastguard Worker get_set_query_availability_cs(const nir_shader_compiler_options *options)
1413*61046927SAndroid Build Coastguard Worker {
1414*61046927SAndroid Build Coastguard Worker    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options,
1415*61046927SAndroid Build Coastguard Worker                                                   "set query availability cs");
1416*61046927SAndroid Build Coastguard Worker 
1417*61046927SAndroid Build Coastguard Worker    nir_def *buf =
1418*61046927SAndroid Build Coastguard Worker       nir_vulkan_resource_index(&b, 2, 32, nir_imm_int(&b, 0),
1419*61046927SAndroid Build Coastguard Worker                                 .desc_set = 0,
1420*61046927SAndroid Build Coastguard Worker                                 .binding = 0,
1421*61046927SAndroid Build Coastguard Worker                                 .desc_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1422*61046927SAndroid Build Coastguard Worker 
1423*61046927SAndroid Build Coastguard Worker    /* This assumes a local size of 1 and a horizontal-only dispatch. If we
1424*61046927SAndroid Build Coastguard Worker     * ever change any of these parameters we need to update how we compute the
1425*61046927SAndroid Build Coastguard Worker     * query index here.
1426*61046927SAndroid Build Coastguard Worker     */
1427*61046927SAndroid Build Coastguard Worker    nir_def *wg_id = nir_channel(&b, nir_load_workgroup_id(&b), 0);
1428*61046927SAndroid Build Coastguard Worker 
1429*61046927SAndroid Build Coastguard Worker    nir_def *offset =
1430*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
1431*61046927SAndroid Build Coastguard Worker 
1432*61046927SAndroid Build Coastguard Worker    nir_def *query_idx =
1433*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 4, .range = 4);
1434*61046927SAndroid Build Coastguard Worker 
1435*61046927SAndroid Build Coastguard Worker    nir_def *avail =
1436*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 8, nir_imm_int(&b, 0), .base = 8, .range = 1);
1437*61046927SAndroid Build Coastguard Worker 
1438*61046927SAndroid Build Coastguard Worker    query_idx = nir_iadd(&b, query_idx, wg_id);
1439*61046927SAndroid Build Coastguard Worker    nir_set_query_availability(&b, buf, offset, query_idx, avail);
1440*61046927SAndroid Build Coastguard Worker 
1441*61046927SAndroid Build Coastguard Worker    return b.shader;
1442*61046927SAndroid Build Coastguard Worker }
1443*61046927SAndroid Build Coastguard Worker 
1444*61046927SAndroid Build Coastguard Worker static inline nir_def *
nir_get_occlusion_counter_offset(nir_builder * b,nir_def * query_idx)1445*61046927SAndroid Build Coastguard Worker nir_get_occlusion_counter_offset(nir_builder *b, nir_def *query_idx)
1446*61046927SAndroid Build Coastguard Worker {
1447*61046927SAndroid Build Coastguard Worker    nir_def *query_group = nir_udiv_imm(b, query_idx, 16);
1448*61046927SAndroid Build Coastguard Worker    nir_def *query_group_offset = nir_umod_imm(b, query_idx, 16);
1449*61046927SAndroid Build Coastguard Worker    nir_def *offset =
1450*61046927SAndroid Build Coastguard Worker       nir_iadd(b, nir_imul_imm(b, query_group, 1024),
1451*61046927SAndroid Build Coastguard Worker                   nir_imul_imm(b, query_group_offset, 4));
1452*61046927SAndroid Build Coastguard Worker    return offset;
1453*61046927SAndroid Build Coastguard Worker }
1454*61046927SAndroid Build Coastguard Worker 
1455*61046927SAndroid Build Coastguard Worker static inline void
nir_reset_occlusion_counter(nir_builder * b,nir_def * buf,nir_def * query_idx)1456*61046927SAndroid Build Coastguard Worker nir_reset_occlusion_counter(nir_builder *b,
1457*61046927SAndroid Build Coastguard Worker                             nir_def *buf,
1458*61046927SAndroid Build Coastguard Worker                             nir_def *query_idx)
1459*61046927SAndroid Build Coastguard Worker {
1460*61046927SAndroid Build Coastguard Worker    nir_def *offset = nir_get_occlusion_counter_offset(b, query_idx);
1461*61046927SAndroid Build Coastguard Worker    nir_def *zero = nir_imm_int(b, 0);
1462*61046927SAndroid Build Coastguard Worker    nir_store_ssbo(b, zero, buf, offset, .write_mask = 0x1, .align_mul = 4);
1463*61046927SAndroid Build Coastguard Worker }
1464*61046927SAndroid Build Coastguard Worker 
1465*61046927SAndroid Build Coastguard Worker static inline nir_def *
nir_read_occlusion_counter(nir_builder * b,nir_def * buf,nir_def * query_idx)1466*61046927SAndroid Build Coastguard Worker nir_read_occlusion_counter(nir_builder *b,
1467*61046927SAndroid Build Coastguard Worker                            nir_def *buf,
1468*61046927SAndroid Build Coastguard Worker                            nir_def *query_idx)
1469*61046927SAndroid Build Coastguard Worker {
1470*61046927SAndroid Build Coastguard Worker    nir_def *offset = nir_get_occlusion_counter_offset(b, query_idx);
1471*61046927SAndroid Build Coastguard Worker    return nir_load_ssbo(b, 1, 32, buf, offset, .access = 0, .align_mul = 4);
1472*61046927SAndroid Build Coastguard Worker }
1473*61046927SAndroid Build Coastguard Worker 
1474*61046927SAndroid Build Coastguard Worker static nir_shader *
get_reset_occlusion_query_cs(const nir_shader_compiler_options * options)1475*61046927SAndroid Build Coastguard Worker get_reset_occlusion_query_cs(const nir_shader_compiler_options *options)
1476*61046927SAndroid Build Coastguard Worker {
1477*61046927SAndroid Build Coastguard Worker    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options,
1478*61046927SAndroid Build Coastguard Worker                                                   "reset occlusion query cs");
1479*61046927SAndroid Build Coastguard Worker 
1480*61046927SAndroid Build Coastguard Worker    nir_def *buf =
1481*61046927SAndroid Build Coastguard Worker       nir_vulkan_resource_index(&b, 2, 32, nir_imm_int(&b, 0),
1482*61046927SAndroid Build Coastguard Worker                                 .desc_set = 0,
1483*61046927SAndroid Build Coastguard Worker                                 .binding = 0,
1484*61046927SAndroid Build Coastguard Worker                                 .desc_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1485*61046927SAndroid Build Coastguard Worker 
1486*61046927SAndroid Build Coastguard Worker    /* This assumes a local size of 1 and a horizontal-only dispatch. If we
1487*61046927SAndroid Build Coastguard Worker     * ever change any of these parameters we need to update how we compute the
1488*61046927SAndroid Build Coastguard Worker     * query index here.
1489*61046927SAndroid Build Coastguard Worker     */
1490*61046927SAndroid Build Coastguard Worker    nir_def *wg_id = nir_channel(&b, nir_load_workgroup_id(&b), 0);
1491*61046927SAndroid Build Coastguard Worker 
1492*61046927SAndroid Build Coastguard Worker    nir_def *avail_offset =
1493*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
1494*61046927SAndroid Build Coastguard Worker 
1495*61046927SAndroid Build Coastguard Worker    nir_def *base_query_idx =
1496*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 4, .range = 4);
1497*61046927SAndroid Build Coastguard Worker 
1498*61046927SAndroid Build Coastguard Worker    nir_def *query_idx = nir_iadd(&b, base_query_idx, wg_id);
1499*61046927SAndroid Build Coastguard Worker 
1500*61046927SAndroid Build Coastguard Worker    nir_set_query_availability(&b, buf, avail_offset, query_idx,
1501*61046927SAndroid Build Coastguard Worker                               nir_imm_intN_t(&b, 0, 8));
1502*61046927SAndroid Build Coastguard Worker    nir_reset_occlusion_counter(&b, buf, query_idx);
1503*61046927SAndroid Build Coastguard Worker 
1504*61046927SAndroid Build Coastguard Worker    return b.shader;
1505*61046927SAndroid Build Coastguard Worker }
1506*61046927SAndroid Build Coastguard Worker 
1507*61046927SAndroid Build Coastguard Worker static void
write_query_buffer(nir_builder * b,nir_def * buf,nir_def ** offset,nir_def * value,bool flag_64bit)1508*61046927SAndroid Build Coastguard Worker write_query_buffer(nir_builder *b,
1509*61046927SAndroid Build Coastguard Worker                    nir_def *buf,
1510*61046927SAndroid Build Coastguard Worker                    nir_def **offset,
1511*61046927SAndroid Build Coastguard Worker                    nir_def *value,
1512*61046927SAndroid Build Coastguard Worker                    bool flag_64bit)
1513*61046927SAndroid Build Coastguard Worker {
1514*61046927SAndroid Build Coastguard Worker    if (flag_64bit) {
1515*61046927SAndroid Build Coastguard Worker       /* Create a 64-bit value using a vec2 with the .Y component set to 0
1516*61046927SAndroid Build Coastguard Worker        * so we can write a 64-bit value in a single store.
1517*61046927SAndroid Build Coastguard Worker        */
1518*61046927SAndroid Build Coastguard Worker       nir_def *value64 = nir_vec2(b, value, nir_imm_int(b, 0));
1519*61046927SAndroid Build Coastguard Worker       nir_store_ssbo(b, value64, buf, *offset, .write_mask = 0x3, .align_mul = 8);
1520*61046927SAndroid Build Coastguard Worker       *offset = nir_iadd_imm(b, *offset, 8);
1521*61046927SAndroid Build Coastguard Worker    } else {
1522*61046927SAndroid Build Coastguard Worker       nir_store_ssbo(b, value, buf, *offset, .write_mask = 0x1, .align_mul = 4);
1523*61046927SAndroid Build Coastguard Worker       *offset = nir_iadd_imm(b, *offset, 4);
1524*61046927SAndroid Build Coastguard Worker    }
1525*61046927SAndroid Build Coastguard Worker }
1526*61046927SAndroid Build Coastguard Worker 
1527*61046927SAndroid Build Coastguard Worker static nir_shader *
get_copy_query_results_cs(const nir_shader_compiler_options * options,VkQueryResultFlags flags)1528*61046927SAndroid Build Coastguard Worker get_copy_query_results_cs(const nir_shader_compiler_options *options,
1529*61046927SAndroid Build Coastguard Worker                           VkQueryResultFlags flags)
1530*61046927SAndroid Build Coastguard Worker {
1531*61046927SAndroid Build Coastguard Worker    bool flag_64bit = flags & VK_QUERY_RESULT_64_BIT;
1532*61046927SAndroid Build Coastguard Worker    bool flag_avail = flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
1533*61046927SAndroid Build Coastguard Worker    bool flag_partial = flags & VK_QUERY_RESULT_PARTIAL_BIT;
1534*61046927SAndroid Build Coastguard Worker 
1535*61046927SAndroid Build Coastguard Worker    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, options,
1536*61046927SAndroid Build Coastguard Worker                                                   "copy query results cs");
1537*61046927SAndroid Build Coastguard Worker 
1538*61046927SAndroid Build Coastguard Worker    nir_def *buf =
1539*61046927SAndroid Build Coastguard Worker       nir_vulkan_resource_index(&b, 2, 32, nir_imm_int(&b, 0),
1540*61046927SAndroid Build Coastguard Worker                                 .desc_set = 0,
1541*61046927SAndroid Build Coastguard Worker                                 .binding = 0,
1542*61046927SAndroid Build Coastguard Worker                                 .desc_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1543*61046927SAndroid Build Coastguard Worker 
1544*61046927SAndroid Build Coastguard Worker    nir_def *buf_out =
1545*61046927SAndroid Build Coastguard Worker       nir_vulkan_resource_index(&b, 2, 32, nir_imm_int(&b, 0),
1546*61046927SAndroid Build Coastguard Worker                                 .desc_set = 1,
1547*61046927SAndroid Build Coastguard Worker                                 .binding = 0,
1548*61046927SAndroid Build Coastguard Worker                                 .desc_type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1549*61046927SAndroid Build Coastguard Worker 
1550*61046927SAndroid Build Coastguard Worker    /* Read push constants */
1551*61046927SAndroid Build Coastguard Worker    nir_def *avail_offset =
1552*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4);
1553*61046927SAndroid Build Coastguard Worker 
1554*61046927SAndroid Build Coastguard Worker    nir_def *base_query_idx =
1555*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 4, .range = 4);
1556*61046927SAndroid Build Coastguard Worker 
1557*61046927SAndroid Build Coastguard Worker    nir_def *base_offset_out =
1558*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 8, .range = 4);
1559*61046927SAndroid Build Coastguard Worker 
1560*61046927SAndroid Build Coastguard Worker    nir_def *stride =
1561*61046927SAndroid Build Coastguard Worker       nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 12, .range = 4);
1562*61046927SAndroid Build Coastguard Worker 
1563*61046927SAndroid Build Coastguard Worker    /* This assumes a local size of 1 and a horizontal-only dispatch. If we
1564*61046927SAndroid Build Coastguard Worker     * ever change any of these parameters we need to update how we compute the
1565*61046927SAndroid Build Coastguard Worker     * query index here.
1566*61046927SAndroid Build Coastguard Worker     */
1567*61046927SAndroid Build Coastguard Worker    nir_def *wg_id = nir_channel(&b, nir_load_workgroup_id(&b), 0);
1568*61046927SAndroid Build Coastguard Worker    nir_def *query_idx = nir_iadd(&b, base_query_idx, wg_id);
1569*61046927SAndroid Build Coastguard Worker 
1570*61046927SAndroid Build Coastguard Worker    /* Read query availability if needed */
1571*61046927SAndroid Build Coastguard Worker    nir_def *avail = NULL;
1572*61046927SAndroid Build Coastguard Worker    if (flag_avail || !flag_partial)
1573*61046927SAndroid Build Coastguard Worker       avail = nir_get_query_availability(&b, buf, avail_offset, query_idx);
1574*61046927SAndroid Build Coastguard Worker 
1575*61046927SAndroid Build Coastguard Worker    /* Write occusion query result... */
1576*61046927SAndroid Build Coastguard Worker    nir_def *offset =
1577*61046927SAndroid Build Coastguard Worker       nir_iadd(&b, base_offset_out, nir_imul(&b, wg_id, stride));
1578*61046927SAndroid Build Coastguard Worker 
1579*61046927SAndroid Build Coastguard Worker    /* ...if partial is requested, we always write */
1580*61046927SAndroid Build Coastguard Worker    if(flag_partial) {
1581*61046927SAndroid Build Coastguard Worker       nir_def *query_res = nir_read_occlusion_counter(&b, buf, query_idx);
1582*61046927SAndroid Build Coastguard Worker       write_query_buffer(&b, buf_out, &offset, query_res, flag_64bit);
1583*61046927SAndroid Build Coastguard Worker    } else {
1584*61046927SAndroid Build Coastguard Worker       /*...otherwise, we only write if the query is available */
1585*61046927SAndroid Build Coastguard Worker       nir_if *if_stmt = nir_push_if(&b, nir_ine_imm(&b, avail, 0));
1586*61046927SAndroid Build Coastguard Worker          nir_def *query_res = nir_read_occlusion_counter(&b, buf, query_idx);
1587*61046927SAndroid Build Coastguard Worker          write_query_buffer(&b, buf_out, &offset, query_res, flag_64bit);
1588*61046927SAndroid Build Coastguard Worker       nir_pop_if(&b, if_stmt);
1589*61046927SAndroid Build Coastguard Worker    }
1590*61046927SAndroid Build Coastguard Worker 
1591*61046927SAndroid Build Coastguard Worker    /* Write query availability */
1592*61046927SAndroid Build Coastguard Worker    if (flag_avail)
1593*61046927SAndroid Build Coastguard Worker       write_query_buffer(&b, buf_out, &offset, avail, flag_64bit);
1594*61046927SAndroid Build Coastguard Worker 
1595*61046927SAndroid Build Coastguard Worker    return b.shader;
1596*61046927SAndroid Build Coastguard Worker }
1597*61046927SAndroid Build Coastguard Worker 
1598*61046927SAndroid Build Coastguard Worker static bool
create_query_pipelines(struct v3dv_device * device)1599*61046927SAndroid Build Coastguard Worker create_query_pipelines(struct v3dv_device *device)
1600*61046927SAndroid Build Coastguard Worker {
1601*61046927SAndroid Build Coastguard Worker    VkResult result;
1602*61046927SAndroid Build Coastguard Worker    VkPipeline pipeline;
1603*61046927SAndroid Build Coastguard Worker 
1604*61046927SAndroid Build Coastguard Worker    /* Set layout: single storage buffer */
1605*61046927SAndroid Build Coastguard Worker    if (!device->queries.buf_descriptor_set_layout) {
1606*61046927SAndroid Build Coastguard Worker       VkDescriptorSetLayoutBinding descriptor_set_layout_binding = {
1607*61046927SAndroid Build Coastguard Worker          .binding = 0,
1608*61046927SAndroid Build Coastguard Worker          .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1609*61046927SAndroid Build Coastguard Worker          .descriptorCount = 1,
1610*61046927SAndroid Build Coastguard Worker          .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
1611*61046927SAndroid Build Coastguard Worker       };
1612*61046927SAndroid Build Coastguard Worker       VkDescriptorSetLayoutCreateInfo descriptor_set_layout_info = {
1613*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1614*61046927SAndroid Build Coastguard Worker          .bindingCount = 1,
1615*61046927SAndroid Build Coastguard Worker          .pBindings = &descriptor_set_layout_binding,
1616*61046927SAndroid Build Coastguard Worker       };
1617*61046927SAndroid Build Coastguard Worker       result =
1618*61046927SAndroid Build Coastguard Worker          v3dv_CreateDescriptorSetLayout(v3dv_device_to_handle(device),
1619*61046927SAndroid Build Coastguard Worker                                         &descriptor_set_layout_info,
1620*61046927SAndroid Build Coastguard Worker                                         &device->vk.alloc,
1621*61046927SAndroid Build Coastguard Worker                                         &device->queries.buf_descriptor_set_layout);
1622*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1623*61046927SAndroid Build Coastguard Worker          return false;
1624*61046927SAndroid Build Coastguard Worker    }
1625*61046927SAndroid Build Coastguard Worker 
1626*61046927SAndroid Build Coastguard Worker    /* Set availability pipeline.
1627*61046927SAndroid Build Coastguard Worker     *
1628*61046927SAndroid Build Coastguard Worker     * Pipeline layout:
1629*61046927SAndroid Build Coastguard Worker     *  - 1 storage buffer for the BO with the query availability.
1630*61046927SAndroid Build Coastguard Worker     *  - 2 push constants:
1631*61046927SAndroid Build Coastguard Worker     *    0B: offset of the availability info in the buffer (4 bytes)
1632*61046927SAndroid Build Coastguard Worker     *    4B: base query index (4 bytes).
1633*61046927SAndroid Build Coastguard Worker     *    8B: availability (1 byte).
1634*61046927SAndroid Build Coastguard Worker     */
1635*61046927SAndroid Build Coastguard Worker    if (!device->queries.avail_pipeline_layout) {
1636*61046927SAndroid Build Coastguard Worker       VkPipelineLayoutCreateInfo pipeline_layout_info = {
1637*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1638*61046927SAndroid Build Coastguard Worker          .setLayoutCount = 1,
1639*61046927SAndroid Build Coastguard Worker          .pSetLayouts = &device->queries.buf_descriptor_set_layout,
1640*61046927SAndroid Build Coastguard Worker          .pushConstantRangeCount = 1,
1641*61046927SAndroid Build Coastguard Worker          .pPushConstantRanges =
1642*61046927SAndroid Build Coastguard Worker              &(VkPushConstantRange) { VK_SHADER_STAGE_COMPUTE_BIT, 0, 9 },
1643*61046927SAndroid Build Coastguard Worker       };
1644*61046927SAndroid Build Coastguard Worker 
1645*61046927SAndroid Build Coastguard Worker       result =
1646*61046927SAndroid Build Coastguard Worker          v3dv_CreatePipelineLayout(v3dv_device_to_handle(device),
1647*61046927SAndroid Build Coastguard Worker                                    &pipeline_layout_info,
1648*61046927SAndroid Build Coastguard Worker                                    &device->vk.alloc,
1649*61046927SAndroid Build Coastguard Worker                                    &device->queries.avail_pipeline_layout);
1650*61046927SAndroid Build Coastguard Worker 
1651*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1652*61046927SAndroid Build Coastguard Worker          return false;
1653*61046927SAndroid Build Coastguard Worker    }
1654*61046927SAndroid Build Coastguard Worker 
1655*61046927SAndroid Build Coastguard Worker    const nir_shader_compiler_options *compiler_options =
1656*61046927SAndroid Build Coastguard Worker       v3dv_pipeline_get_nir_options(&device->devinfo);
1657*61046927SAndroid Build Coastguard Worker 
1658*61046927SAndroid Build Coastguard Worker    if (!device->queries.avail_pipeline) {
1659*61046927SAndroid Build Coastguard Worker       nir_shader *set_query_availability_cs_nir =
1660*61046927SAndroid Build Coastguard Worker          get_set_query_availability_cs(compiler_options);
1661*61046927SAndroid Build Coastguard Worker       result = v3dv_create_compute_pipeline_from_nir(device,
1662*61046927SAndroid Build Coastguard Worker                                                      set_query_availability_cs_nir,
1663*61046927SAndroid Build Coastguard Worker                                                      device->queries.avail_pipeline_layout,
1664*61046927SAndroid Build Coastguard Worker                                                      &pipeline);
1665*61046927SAndroid Build Coastguard Worker       ralloc_free(set_query_availability_cs_nir);
1666*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1667*61046927SAndroid Build Coastguard Worker          return false;
1668*61046927SAndroid Build Coastguard Worker 
1669*61046927SAndroid Build Coastguard Worker       device->queries.avail_pipeline = pipeline;
1670*61046927SAndroid Build Coastguard Worker    }
1671*61046927SAndroid Build Coastguard Worker 
1672*61046927SAndroid Build Coastguard Worker    /* Reset occlusion query pipeline.
1673*61046927SAndroid Build Coastguard Worker     *
1674*61046927SAndroid Build Coastguard Worker     * Pipeline layout:
1675*61046927SAndroid Build Coastguard Worker     *  - 1 storage buffer for the BO with the occlusion and availability data.
1676*61046927SAndroid Build Coastguard Worker     *  - Push constants:
1677*61046927SAndroid Build Coastguard Worker     *    0B: offset of the availability info in the buffer (4B)
1678*61046927SAndroid Build Coastguard Worker     *    4B: base query index (4B)
1679*61046927SAndroid Build Coastguard Worker     */
1680*61046927SAndroid Build Coastguard Worker    if (!device->queries.reset_occlusion_pipeline_layout) {
1681*61046927SAndroid Build Coastguard Worker       VkPipelineLayoutCreateInfo pipeline_layout_info = {
1682*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1683*61046927SAndroid Build Coastguard Worker          .setLayoutCount = 1,
1684*61046927SAndroid Build Coastguard Worker          .pSetLayouts = &device->queries.buf_descriptor_set_layout,
1685*61046927SAndroid Build Coastguard Worker          .pushConstantRangeCount = 1,
1686*61046927SAndroid Build Coastguard Worker          .pPushConstantRanges =
1687*61046927SAndroid Build Coastguard Worker              &(VkPushConstantRange) { VK_SHADER_STAGE_COMPUTE_BIT, 0, 8 },
1688*61046927SAndroid Build Coastguard Worker       };
1689*61046927SAndroid Build Coastguard Worker 
1690*61046927SAndroid Build Coastguard Worker       result =
1691*61046927SAndroid Build Coastguard Worker          v3dv_CreatePipelineLayout(v3dv_device_to_handle(device),
1692*61046927SAndroid Build Coastguard Worker                                    &pipeline_layout_info,
1693*61046927SAndroid Build Coastguard Worker                                    &device->vk.alloc,
1694*61046927SAndroid Build Coastguard Worker                                    &device->queries.reset_occlusion_pipeline_layout);
1695*61046927SAndroid Build Coastguard Worker 
1696*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1697*61046927SAndroid Build Coastguard Worker          return false;
1698*61046927SAndroid Build Coastguard Worker    }
1699*61046927SAndroid Build Coastguard Worker 
1700*61046927SAndroid Build Coastguard Worker    if (!device->queries.reset_occlusion_pipeline) {
1701*61046927SAndroid Build Coastguard Worker       nir_shader *reset_occlusion_query_cs_nir =
1702*61046927SAndroid Build Coastguard Worker          get_reset_occlusion_query_cs(compiler_options);
1703*61046927SAndroid Build Coastguard Worker       result = v3dv_create_compute_pipeline_from_nir(
1704*61046927SAndroid Build Coastguard Worker                   device,
1705*61046927SAndroid Build Coastguard Worker                   reset_occlusion_query_cs_nir,
1706*61046927SAndroid Build Coastguard Worker                   device->queries.reset_occlusion_pipeline_layout,
1707*61046927SAndroid Build Coastguard Worker                   &pipeline);
1708*61046927SAndroid Build Coastguard Worker       ralloc_free(reset_occlusion_query_cs_nir);
1709*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1710*61046927SAndroid Build Coastguard Worker          return false;
1711*61046927SAndroid Build Coastguard Worker 
1712*61046927SAndroid Build Coastguard Worker       device->queries.reset_occlusion_pipeline = pipeline;
1713*61046927SAndroid Build Coastguard Worker    }
1714*61046927SAndroid Build Coastguard Worker 
1715*61046927SAndroid Build Coastguard Worker    /* Copy query results pipelines.
1716*61046927SAndroid Build Coastguard Worker     *
1717*61046927SAndroid Build Coastguard Worker     * Pipeline layout:
1718*61046927SAndroid Build Coastguard Worker     *  - 1 storage buffer for the BO with the query availability and occlusion.
1719*61046927SAndroid Build Coastguard Worker     *  - 1 storage buffer for the output.
1720*61046927SAndroid Build Coastguard Worker     *  - Push constants:
1721*61046927SAndroid Build Coastguard Worker     *    0B: offset of the availability info in the buffer (4B)
1722*61046927SAndroid Build Coastguard Worker     *    4B: base query index (4B)
1723*61046927SAndroid Build Coastguard Worker     *    8B: offset into output buffer (4B)
1724*61046927SAndroid Build Coastguard Worker     *    12B: stride (4B)
1725*61046927SAndroid Build Coastguard Worker     *
1726*61046927SAndroid Build Coastguard Worker     * We create multiple specialized pipelines depending on the copy flags
1727*61046927SAndroid Build Coastguard Worker     * to remove conditionals from the copy shader and get more optimized
1728*61046927SAndroid Build Coastguard Worker     * pipelines.
1729*61046927SAndroid Build Coastguard Worker     */
1730*61046927SAndroid Build Coastguard Worker    if (!device->queries.copy_pipeline_layout) {
1731*61046927SAndroid Build Coastguard Worker       VkDescriptorSetLayout set_layouts[2] = {
1732*61046927SAndroid Build Coastguard Worker          device->queries.buf_descriptor_set_layout,
1733*61046927SAndroid Build Coastguard Worker          device->queries.buf_descriptor_set_layout
1734*61046927SAndroid Build Coastguard Worker       };
1735*61046927SAndroid Build Coastguard Worker       VkPipelineLayoutCreateInfo pipeline_layout_info = {
1736*61046927SAndroid Build Coastguard Worker          .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1737*61046927SAndroid Build Coastguard Worker          .setLayoutCount = 2,
1738*61046927SAndroid Build Coastguard Worker          .pSetLayouts = set_layouts,
1739*61046927SAndroid Build Coastguard Worker          .pushConstantRangeCount = 1,
1740*61046927SAndroid Build Coastguard Worker          .pPushConstantRanges =
1741*61046927SAndroid Build Coastguard Worker              &(VkPushConstantRange) { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 },
1742*61046927SAndroid Build Coastguard Worker       };
1743*61046927SAndroid Build Coastguard Worker 
1744*61046927SAndroid Build Coastguard Worker       result =
1745*61046927SAndroid Build Coastguard Worker          v3dv_CreatePipelineLayout(v3dv_device_to_handle(device),
1746*61046927SAndroid Build Coastguard Worker                                    &pipeline_layout_info,
1747*61046927SAndroid Build Coastguard Worker                                    &device->vk.alloc,
1748*61046927SAndroid Build Coastguard Worker                                    &device->queries.copy_pipeline_layout);
1749*61046927SAndroid Build Coastguard Worker 
1750*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1751*61046927SAndroid Build Coastguard Worker          return false;
1752*61046927SAndroid Build Coastguard Worker    }
1753*61046927SAndroid Build Coastguard Worker 
1754*61046927SAndroid Build Coastguard Worker    /* Actual copy pipelines are created lazily on demand since there can be up
1755*61046927SAndroid Build Coastguard Worker     * to 8 depending on the flags used, however it is likely that applications
1756*61046927SAndroid Build Coastguard Worker     * will use the same flags every time and only one pipeline is required.
1757*61046927SAndroid Build Coastguard Worker     */
1758*61046927SAndroid Build Coastguard Worker 
1759*61046927SAndroid Build Coastguard Worker    return true;
1760*61046927SAndroid Build Coastguard Worker }
1761*61046927SAndroid Build Coastguard Worker 
1762*61046927SAndroid Build Coastguard Worker static void
destroy_query_pipelines(struct v3dv_device * device)1763*61046927SAndroid Build Coastguard Worker destroy_query_pipelines(struct v3dv_device *device)
1764*61046927SAndroid Build Coastguard Worker {
1765*61046927SAndroid Build Coastguard Worker    VkDevice _device = v3dv_device_to_handle(device);
1766*61046927SAndroid Build Coastguard Worker 
1767*61046927SAndroid Build Coastguard Worker    /* Availability pipeline */
1768*61046927SAndroid Build Coastguard Worker    v3dv_DestroyPipeline(_device, device->queries.avail_pipeline,
1769*61046927SAndroid Build Coastguard Worker                          &device->vk.alloc);
1770*61046927SAndroid Build Coastguard Worker    device->queries.avail_pipeline = VK_NULL_HANDLE;
1771*61046927SAndroid Build Coastguard Worker    v3dv_DestroyPipelineLayout(_device, device->queries.avail_pipeline_layout,
1772*61046927SAndroid Build Coastguard Worker                               &device->vk.alloc);
1773*61046927SAndroid Build Coastguard Worker    device->queries.avail_pipeline_layout = VK_NULL_HANDLE;
1774*61046927SAndroid Build Coastguard Worker 
1775*61046927SAndroid Build Coastguard Worker    /* Reset occlusion pipeline */
1776*61046927SAndroid Build Coastguard Worker    v3dv_DestroyPipeline(_device, device->queries.reset_occlusion_pipeline,
1777*61046927SAndroid Build Coastguard Worker                          &device->vk.alloc);
1778*61046927SAndroid Build Coastguard Worker    device->queries.reset_occlusion_pipeline = VK_NULL_HANDLE;
1779*61046927SAndroid Build Coastguard Worker    v3dv_DestroyPipelineLayout(_device,
1780*61046927SAndroid Build Coastguard Worker                               device->queries.reset_occlusion_pipeline_layout,
1781*61046927SAndroid Build Coastguard Worker                               &device->vk.alloc);
1782*61046927SAndroid Build Coastguard Worker    device->queries.reset_occlusion_pipeline_layout = VK_NULL_HANDLE;
1783*61046927SAndroid Build Coastguard Worker 
1784*61046927SAndroid Build Coastguard Worker    /* Copy pipelines */
1785*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 8; i++) {
1786*61046927SAndroid Build Coastguard Worker       v3dv_DestroyPipeline(_device, device->queries.copy_pipeline[i],
1787*61046927SAndroid Build Coastguard Worker                             &device->vk.alloc);
1788*61046927SAndroid Build Coastguard Worker       device->queries.copy_pipeline[i] = VK_NULL_HANDLE;
1789*61046927SAndroid Build Coastguard Worker    }
1790*61046927SAndroid Build Coastguard Worker    v3dv_DestroyPipelineLayout(_device, device->queries.copy_pipeline_layout,
1791*61046927SAndroid Build Coastguard Worker                               &device->vk.alloc);
1792*61046927SAndroid Build Coastguard Worker    device->queries.copy_pipeline_layout = VK_NULL_HANDLE;
1793*61046927SAndroid Build Coastguard Worker 
1794*61046927SAndroid Build Coastguard Worker    v3dv_DestroyDescriptorSetLayout(_device,
1795*61046927SAndroid Build Coastguard Worker                                    device->queries.buf_descriptor_set_layout,
1796*61046927SAndroid Build Coastguard Worker                                    &device->vk.alloc);
1797*61046927SAndroid Build Coastguard Worker    device->queries.buf_descriptor_set_layout = VK_NULL_HANDLE;
1798*61046927SAndroid Build Coastguard Worker }
1799*61046927SAndroid Build Coastguard Worker 
1800*61046927SAndroid Build Coastguard Worker /**
1801*61046927SAndroid Build Coastguard Worker  * Allocates device resources for implementing certain types of queries.
1802*61046927SAndroid Build Coastguard Worker  */
1803*61046927SAndroid Build Coastguard Worker VkResult
v3dv_query_allocate_resources(struct v3dv_device * device)1804*61046927SAndroid Build Coastguard Worker v3dv_query_allocate_resources(struct v3dv_device *device)
1805*61046927SAndroid Build Coastguard Worker {
1806*61046927SAndroid Build Coastguard Worker    if (!create_query_pipelines(device))
1807*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1808*61046927SAndroid Build Coastguard Worker 
1809*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1810*61046927SAndroid Build Coastguard Worker }
1811*61046927SAndroid Build Coastguard Worker 
1812*61046927SAndroid Build Coastguard Worker void
v3dv_query_free_resources(struct v3dv_device * device)1813*61046927SAndroid Build Coastguard Worker v3dv_query_free_resources(struct v3dv_device *device)
1814*61046927SAndroid Build Coastguard Worker {
1815*61046927SAndroid Build Coastguard Worker    destroy_query_pipelines(device);
1816*61046927SAndroid Build Coastguard Worker }
1817