1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Raspberry Pi Ltd
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "v3dv_private.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "util/timespec.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_cistatic const char *v3dv_counters[][3] = {
29bf215546Sopenharmony_ci   {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
30bf215546Sopenharmony_ci   {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
31bf215546Sopenharmony_ci   {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
32bf215546Sopenharmony_ci   {"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
33bf215546Sopenharmony_ci   {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
34bf215546Sopenharmony_ci   {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
35bf215546Sopenharmony_ci   {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
36bf215546Sopenharmony_ci   {"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"},
37bf215546Sopenharmony_ci   {"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"},
38bf215546Sopenharmony_ci   {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
39bf215546Sopenharmony_ci   {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
40bf215546Sopenharmony_ci   {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
41bf215546Sopenharmony_ci   {"PTB", "PTB-primitives-discared-reversed", "[PTB] Primitives that are discarded because they are reversed"},
42bf215546Sopenharmony_ci   {"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"},
43bf215546Sopenharmony_ci   {"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"},
44bf215546Sopenharmony_ci   {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
45bf215546Sopenharmony_ci   {"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"},
46bf215546Sopenharmony_ci   {"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"},
47bf215546Sopenharmony_ci   {"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"},
48bf215546Sopenharmony_ci   {"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"},
49bf215546Sopenharmony_ci   {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
50bf215546Sopenharmony_ci   {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
51bf215546Sopenharmony_ci   {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
52bf215546Sopenharmony_ci   {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
53bf215546Sopenharmony_ci   {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
54bf215546Sopenharmony_ci   {"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"},
55bf215546Sopenharmony_ci   {"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"},
56bf215546Sopenharmony_ci   {"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"},
57bf215546Sopenharmony_ci   {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
58bf215546Sopenharmony_ci   {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
59bf215546Sopenharmony_ci   {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
60bf215546Sopenharmony_ci   {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
61bf215546Sopenharmony_ci   {"CORE", "cycle-count", "[CORE] Cycle counter"},
62bf215546Sopenharmony_ci   {"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"},
63bf215546Sopenharmony_ci   {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
64bf215546Sopenharmony_ci   {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
65bf215546Sopenharmony_ci   {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
66bf215546Sopenharmony_ci   {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
67bf215546Sopenharmony_ci   {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
68bf215546Sopenharmony_ci   {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
69bf215546Sopenharmony_ci   {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
70bf215546Sopenharmony_ci   {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
71bf215546Sopenharmony_ci   {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
72bf215546Sopenharmony_ci   {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
73bf215546Sopenharmony_ci   {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
74bf215546Sopenharmony_ci   {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
75bf215546Sopenharmony_ci   {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
76bf215546Sopenharmony_ci   {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
77bf215546Sopenharmony_ci   {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
78bf215546Sopenharmony_ci   {"TMU", "TMU-total-config-access", "[TMU] Total config accesses"},
79bf215546Sopenharmony_ci   {"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"},
80bf215546Sopenharmony_ci   {"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"},
81bf215546Sopenharmony_ci   {"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"},
82bf215546Sopenharmony_ci   {"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
83bf215546Sopenharmony_ci   {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
84bf215546Sopenharmony_ci   {"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"},
85bf215546Sopenharmony_ci   {"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"},
86bf215546Sopenharmony_ci   {"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"},
87bf215546Sopenharmony_ci   {"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"},
88bf215546Sopenharmony_ci   {"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"},
89bf215546Sopenharmony_ci   {"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"},
90bf215546Sopenharmony_ci   {"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"},
91bf215546Sopenharmony_ci   {"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"},
92bf215546Sopenharmony_ci   {"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"},
93bf215546Sopenharmony_ci   {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
94bf215546Sopenharmony_ci   {"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"},
95bf215546Sopenharmony_ci   {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
96bf215546Sopenharmony_ci   {"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"},
97bf215546Sopenharmony_ci   {"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"},
98bf215546Sopenharmony_ci   {"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"},
99bf215546Sopenharmony_ci   {"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"},
100bf215546Sopenharmony_ci   {"CORE", "core-memory-writes", "[CORE] Total memory writes"},
101bf215546Sopenharmony_ci   {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
102bf215546Sopenharmony_ci   {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
103bf215546Sopenharmony_ci   {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
104bf215546Sopenharmony_ci   {"CORE", "core-memory-reads", "[CORE] Total memory reads"},
105bf215546Sopenharmony_ci   {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
106bf215546Sopenharmony_ci   {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
107bf215546Sopenharmony_ci   {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
108bf215546Sopenharmony_ci   {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
109bf215546Sopenharmony_ci   {"GMP", "GMP-memory-reads", "[GMP] Total memory reads"},
110bf215546Sopenharmony_ci   {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
111bf215546Sopenharmony_ci   {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
112bf215546Sopenharmony_ci   {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
113bf215546Sopenharmony_ci   {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
114bf215546Sopenharmony_ci   {"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"},
115bf215546Sopenharmony_ci   {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
116bf215546Sopenharmony_ci};
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_cistatic void
119bf215546Sopenharmony_cikperfmon_create(struct v3dv_device *device,
120bf215546Sopenharmony_ci                struct v3dv_query_pool *pool,
121bf215546Sopenharmony_ci                uint32_t query)
122bf215546Sopenharmony_ci{
123bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pool->perfmon.nperfmons; i++) {
124bf215546Sopenharmony_ci      assert(i * DRM_V3D_MAX_PERF_COUNTERS < pool->perfmon.ncounters);
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci      struct drm_v3d_perfmon_create req = {
127bf215546Sopenharmony_ci         .ncounters = MIN2(pool->perfmon.ncounters -
128bf215546Sopenharmony_ci                           i * DRM_V3D_MAX_PERF_COUNTERS,
129bf215546Sopenharmony_ci                           DRM_V3D_MAX_PERF_COUNTERS),
130bf215546Sopenharmony_ci      };
131bf215546Sopenharmony_ci      memcpy(req.counters,
132bf215546Sopenharmony_ci             &pool->perfmon.counters[i * DRM_V3D_MAX_PERF_COUNTERS],
133bf215546Sopenharmony_ci             req.ncounters);
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci      int ret = v3dv_ioctl(device->pdevice->render_fd,
136bf215546Sopenharmony_ci                           DRM_IOCTL_V3D_PERFMON_CREATE,
137bf215546Sopenharmony_ci                           &req);
138bf215546Sopenharmony_ci      if (ret)
139bf215546Sopenharmony_ci         fprintf(stderr, "Failed to create perfmon: %s\n", strerror(ret));
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci      pool->queries[query].perf.kperfmon_ids[i] = req.id;
142bf215546Sopenharmony_ci   }
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_cistatic void
146bf215546Sopenharmony_cikperfmon_destroy(struct v3dv_device *device,
147bf215546Sopenharmony_ci                 struct v3dv_query_pool *pool,
148bf215546Sopenharmony_ci                 uint32_t query)
149bf215546Sopenharmony_ci{
150bf215546Sopenharmony_ci   /* Skip destroying if never created */
151bf215546Sopenharmony_ci   if (!pool->queries[query].perf.kperfmon_ids[0])
152bf215546Sopenharmony_ci      return;
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pool->perfmon.nperfmons; i++) {
155bf215546Sopenharmony_ci      struct drm_v3d_perfmon_destroy req = {
156bf215546Sopenharmony_ci         .id = pool->queries[query].perf.kperfmon_ids[i]
157bf215546Sopenharmony_ci      };
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci      int ret = v3dv_ioctl(device->pdevice->render_fd,
160bf215546Sopenharmony_ci                           DRM_IOCTL_V3D_PERFMON_DESTROY,
161bf215546Sopenharmony_ci                           &req);
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci      if (ret) {
164bf215546Sopenharmony_ci         fprintf(stderr, "Failed to destroy perfmon %u: %s\n",
165bf215546Sopenharmony_ci                 req.id, strerror(ret));
166bf215546Sopenharmony_ci      }
167bf215546Sopenharmony_ci   }
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
171bf215546Sopenharmony_civ3dv_CreateQueryPool(VkDevice _device,
172bf215546Sopenharmony_ci                     const VkQueryPoolCreateInfo *pCreateInfo,
173bf215546Sopenharmony_ci                     const VkAllocationCallbacks *pAllocator,
174bf215546Sopenharmony_ci                     VkQueryPool *pQueryPool)
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   assert(pCreateInfo->queryType == VK_QUERY_TYPE_OCCLUSION ||
179bf215546Sopenharmony_ci          pCreateInfo->queryType == VK_QUERY_TYPE_TIMESTAMP ||
180bf215546Sopenharmony_ci          pCreateInfo->queryType == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
181bf215546Sopenharmony_ci   assert(pCreateInfo->queryCount > 0);
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci   struct v3dv_query_pool *pool =
184bf215546Sopenharmony_ci      vk_object_zalloc(&device->vk, pAllocator, sizeof(*pool),
185bf215546Sopenharmony_ci                       VK_OBJECT_TYPE_QUERY_POOL);
186bf215546Sopenharmony_ci   if (pool == NULL)
187bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   pool->query_type = pCreateInfo->queryType;
190bf215546Sopenharmony_ci   pool->query_count = pCreateInfo->queryCount;
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   uint32_t query_idx = 0;
193bf215546Sopenharmony_ci   VkResult result;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   const uint32_t pool_bytes = sizeof(struct v3dv_query) * pool->query_count;
196bf215546Sopenharmony_ci   pool->queries = vk_alloc2(&device->vk.alloc, pAllocator, pool_bytes, 8,
197bf215546Sopenharmony_ci                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
198bf215546Sopenharmony_ci   if (pool->queries == NULL) {
199bf215546Sopenharmony_ci      result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
200bf215546Sopenharmony_ci      goto fail;
201bf215546Sopenharmony_ci   }
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci   switch (pool->query_type) {
204bf215546Sopenharmony_ci   case VK_QUERY_TYPE_OCCLUSION: {
205bf215546Sopenharmony_ci      /* The hardware allows us to setup groups of 16 queries in consecutive
206bf215546Sopenharmony_ci       * 4-byte addresses, requiring only that each group of 16 queries is
207bf215546Sopenharmony_ci       * aligned to a 1024 byte boundary.
208bf215546Sopenharmony_ci       */
209bf215546Sopenharmony_ci      const uint32_t query_groups = DIV_ROUND_UP(pool->query_count, 16);
210bf215546Sopenharmony_ci      const uint32_t bo_size = query_groups * 1024;
211bf215546Sopenharmony_ci      pool->bo = v3dv_bo_alloc(device, bo_size, "query", true);
212bf215546Sopenharmony_ci      if (!pool->bo) {
213bf215546Sopenharmony_ci         result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
214bf215546Sopenharmony_ci         goto fail;
215bf215546Sopenharmony_ci      }
216bf215546Sopenharmony_ci      if (!v3dv_bo_map(device, pool->bo, bo_size)) {
217bf215546Sopenharmony_ci         result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
218bf215546Sopenharmony_ci         goto fail;
219bf215546Sopenharmony_ci      }
220bf215546Sopenharmony_ci      break;
221bf215546Sopenharmony_ci   }
222bf215546Sopenharmony_ci   case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: {
223bf215546Sopenharmony_ci      const VkQueryPoolPerformanceCreateInfoKHR *pq_info =
224bf215546Sopenharmony_ci         vk_find_struct_const(pCreateInfo->pNext,
225bf215546Sopenharmony_ci                              QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR);
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci      assert(pq_info);
228bf215546Sopenharmony_ci      assert(pq_info->counterIndexCount <= V3D_PERFCNT_NUM);
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci      pool->perfmon.ncounters = pq_info->counterIndexCount;
231bf215546Sopenharmony_ci      for (uint32_t i = 0; i < pq_info->counterIndexCount; i++)
232bf215546Sopenharmony_ci         pool->perfmon.counters[i] = pq_info->pCounterIndices[i];
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci      pool->perfmon.nperfmons = DIV_ROUND_UP(pool->perfmon.ncounters,
235bf215546Sopenharmony_ci                                             DRM_V3D_MAX_PERF_COUNTERS);
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci      assert(pool->perfmon.nperfmons <= V3DV_MAX_PERFMONS);
238bf215546Sopenharmony_ci      break;
239bf215546Sopenharmony_ci   }
240bf215546Sopenharmony_ci   case VK_QUERY_TYPE_TIMESTAMP:
241bf215546Sopenharmony_ci      break;
242bf215546Sopenharmony_ci   default:
243bf215546Sopenharmony_ci      unreachable("Unsupported query type");
244bf215546Sopenharmony_ci   }
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   for (; query_idx < pool->query_count; query_idx++) {
247bf215546Sopenharmony_ci      pool->queries[query_idx].maybe_available = false;
248bf215546Sopenharmony_ci      switch (pool->query_type) {
249bf215546Sopenharmony_ci      case VK_QUERY_TYPE_OCCLUSION: {
250bf215546Sopenharmony_ci         const uint32_t query_group = query_idx / 16;
251bf215546Sopenharmony_ci         const uint32_t query_offset = query_group * 1024 + (query_idx % 16) * 4;
252bf215546Sopenharmony_ci         pool->queries[query_idx].bo = pool->bo;
253bf215546Sopenharmony_ci         pool->queries[query_idx].offset = query_offset;
254bf215546Sopenharmony_ci         break;
255bf215546Sopenharmony_ci         }
256bf215546Sopenharmony_ci      case VK_QUERY_TYPE_TIMESTAMP:
257bf215546Sopenharmony_ci         pool->queries[query_idx].value = 0;
258bf215546Sopenharmony_ci         break;
259bf215546Sopenharmony_ci      case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: {
260bf215546Sopenharmony_ci         result = vk_sync_create(&device->vk,
261bf215546Sopenharmony_ci                                 &device->pdevice->drm_syncobj_type, 0, 0,
262bf215546Sopenharmony_ci                                 &pool->queries[query_idx].perf.last_job_sync);
263bf215546Sopenharmony_ci         if (result != VK_SUCCESS)
264bf215546Sopenharmony_ci            goto fail;
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci         for (uint32_t j = 0; j < pool->perfmon.nperfmons; j++)
267bf215546Sopenharmony_ci            pool->queries[query_idx].perf.kperfmon_ids[j] = 0;
268bf215546Sopenharmony_ci         break;
269bf215546Sopenharmony_ci         }
270bf215546Sopenharmony_ci      default:
271bf215546Sopenharmony_ci         unreachable("Unsupported query type");
272bf215546Sopenharmony_ci      }
273bf215546Sopenharmony_ci   }
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   *pQueryPool = v3dv_query_pool_to_handle(pool);
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   return VK_SUCCESS;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_cifail:
280bf215546Sopenharmony_ci   if (pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
281bf215546Sopenharmony_ci      for (uint32_t j = 0; j < query_idx; j++)
282bf215546Sopenharmony_ci         vk_sync_destroy(&device->vk, pool->queries[j].perf.last_job_sync);
283bf215546Sopenharmony_ci   }
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   if (pool->bo)
286bf215546Sopenharmony_ci      v3dv_bo_free(device, pool->bo);
287bf215546Sopenharmony_ci   if (pool->queries)
288bf215546Sopenharmony_ci      vk_free2(&device->vk.alloc, pAllocator, pool->queries);
289bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, pool);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   return result;
292bf215546Sopenharmony_ci}
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
295bf215546Sopenharmony_civ3dv_DestroyQueryPool(VkDevice _device,
296bf215546Sopenharmony_ci                      VkQueryPool queryPool,
297bf215546Sopenharmony_ci                      const VkAllocationCallbacks *pAllocator)
298bf215546Sopenharmony_ci{
299bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
300bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   if (!pool)
303bf215546Sopenharmony_ci      return;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   if (pool->bo)
306bf215546Sopenharmony_ci      v3dv_bo_free(device, pool->bo);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci   if (pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
309bf215546Sopenharmony_ci      for (uint32_t i = 0; i < pool->query_count; i++) {
310bf215546Sopenharmony_ci         kperfmon_destroy(device, pool, i);
311bf215546Sopenharmony_ci         vk_sync_destroy(&device->vk, pool->queries[i].perf.last_job_sync);
312bf215546Sopenharmony_ci      }
313bf215546Sopenharmony_ci   }
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   if (pool->queries)
316bf215546Sopenharmony_ci      vk_free2(&device->vk.alloc, pAllocator, pool->queries);
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   vk_object_free(&device->vk, pAllocator, pool);
319bf215546Sopenharmony_ci}
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_cistatic void
322bf215546Sopenharmony_ciwrite_to_buffer(void *dst, uint32_t idx, bool do_64bit, uint64_t value)
323bf215546Sopenharmony_ci{
324bf215546Sopenharmony_ci   if (do_64bit) {
325bf215546Sopenharmony_ci      uint64_t *dst64 = (uint64_t *) dst;
326bf215546Sopenharmony_ci      dst64[idx] = value;
327bf215546Sopenharmony_ci   } else {
328bf215546Sopenharmony_ci      uint32_t *dst32 = (uint32_t *) dst;
329bf215546Sopenharmony_ci      dst32[idx] = (uint32_t) value;
330bf215546Sopenharmony_ci   }
331bf215546Sopenharmony_ci}
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_cistatic VkResult
334bf215546Sopenharmony_ciquery_wait_available(struct v3dv_device *device,
335bf215546Sopenharmony_ci                     struct v3dv_query *q,
336bf215546Sopenharmony_ci                     VkQueryType query_type)
337bf215546Sopenharmony_ci{
338bf215546Sopenharmony_ci   if (!q->maybe_available) {
339bf215546Sopenharmony_ci      struct timespec timeout;
340bf215546Sopenharmony_ci      timespec_get(&timeout, TIME_UTC);
341bf215546Sopenharmony_ci      timespec_add_msec(&timeout, &timeout, 2000);
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci      VkResult result = VK_SUCCESS;
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci      mtx_lock(&device->query_mutex);
346bf215546Sopenharmony_ci      while (!q->maybe_available) {
347bf215546Sopenharmony_ci         if (vk_device_is_lost(&device->vk)) {
348bf215546Sopenharmony_ci            result = VK_ERROR_DEVICE_LOST;
349bf215546Sopenharmony_ci            break;
350bf215546Sopenharmony_ci         }
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci         int ret = cnd_timedwait(&device->query_ended,
353bf215546Sopenharmony_ci                                 &device->query_mutex,
354bf215546Sopenharmony_ci                                 &timeout);
355bf215546Sopenharmony_ci         if (ret != thrd_success) {
356bf215546Sopenharmony_ci            mtx_unlock(&device->query_mutex);
357bf215546Sopenharmony_ci            result = vk_device_set_lost(&device->vk, "Query wait failed");
358bf215546Sopenharmony_ci            break;
359bf215546Sopenharmony_ci         }
360bf215546Sopenharmony_ci      }
361bf215546Sopenharmony_ci      mtx_unlock(&device->query_mutex);
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
364bf215546Sopenharmony_ci         return result;
365bf215546Sopenharmony_ci   }
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   if (query_type == VK_QUERY_TYPE_OCCLUSION &&
368bf215546Sopenharmony_ci       !v3dv_bo_wait(device, q->bo, 0xffffffffffffffffull))
369bf215546Sopenharmony_ci      return vk_device_set_lost(&device->vk, "Query BO wait failed: %m");
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci   if (query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR &&
372bf215546Sopenharmony_ci       vk_sync_wait(&device->vk, q->perf.last_job_sync,
373bf215546Sopenharmony_ci                    0, VK_SYNC_WAIT_COMPLETE, UINT64_MAX) != VK_SUCCESS)
374bf215546Sopenharmony_ci      return vk_device_set_lost(&device->vk, "Query job wait failed");
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci   return VK_SUCCESS;
377bf215546Sopenharmony_ci}
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_cistatic VkResult
380bf215546Sopenharmony_ciwrite_occlusion_query_result(struct v3dv_device *device,
381bf215546Sopenharmony_ci                             struct v3dv_query_pool *pool,
382bf215546Sopenharmony_ci                             uint32_t query,
383bf215546Sopenharmony_ci                             bool do_64bit,
384bf215546Sopenharmony_ci                             void *data,
385bf215546Sopenharmony_ci                             uint32_t slot)
386bf215546Sopenharmony_ci{
387bf215546Sopenharmony_ci   assert(pool && pool->query_type == VK_QUERY_TYPE_OCCLUSION);
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci   if (vk_device_is_lost(&device->vk))
390bf215546Sopenharmony_ci      return VK_ERROR_DEVICE_LOST;
391bf215546Sopenharmony_ci
392bf215546Sopenharmony_ci   struct v3dv_query *q = &pool->queries[query];
393bf215546Sopenharmony_ci   assert(q->bo && q->bo->map);
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   const uint8_t *query_addr = ((uint8_t *) q->bo->map) + q->offset;
396bf215546Sopenharmony_ci   write_to_buffer(data, slot, do_64bit, (uint64_t) *((uint32_t *)query_addr));
397bf215546Sopenharmony_ci   return VK_SUCCESS;
398bf215546Sopenharmony_ci}
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_cistatic VkResult
401bf215546Sopenharmony_ciwrite_timestamp_query_result(struct v3dv_device *device,
402bf215546Sopenharmony_ci                             struct v3dv_query_pool *pool,
403bf215546Sopenharmony_ci                             uint32_t query,
404bf215546Sopenharmony_ci                             bool do_64bit,
405bf215546Sopenharmony_ci                             void *data,
406bf215546Sopenharmony_ci                             uint32_t slot)
407bf215546Sopenharmony_ci{
408bf215546Sopenharmony_ci   assert(pool && pool->query_type == VK_QUERY_TYPE_TIMESTAMP);
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   struct v3dv_query *q = &pool->queries[query];
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   write_to_buffer(data, slot, do_64bit, q->value);
413bf215546Sopenharmony_ci   return VK_SUCCESS;
414bf215546Sopenharmony_ci}
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_cistatic VkResult
417bf215546Sopenharmony_ciwrite_performance_query_result(struct v3dv_device *device,
418bf215546Sopenharmony_ci                               struct v3dv_query_pool *pool,
419bf215546Sopenharmony_ci                               uint32_t query,
420bf215546Sopenharmony_ci                               bool do_64bit,
421bf215546Sopenharmony_ci                               void *data,
422bf215546Sopenharmony_ci                               uint32_t slot)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci   assert(pool && pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   struct v3dv_query *q = &pool->queries[query];
427bf215546Sopenharmony_ci   uint64_t counter_values[V3D_PERFCNT_NUM];
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pool->perfmon.nperfmons; i++) {
430bf215546Sopenharmony_ci      struct drm_v3d_perfmon_get_values req = {
431bf215546Sopenharmony_ci         .id = q->perf.kperfmon_ids[i],
432bf215546Sopenharmony_ci         .values_ptr = (uintptr_t)(&counter_values[i *
433bf215546Sopenharmony_ci                                   DRM_V3D_MAX_PERF_COUNTERS])
434bf215546Sopenharmony_ci      };
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci      int ret = v3dv_ioctl(device->pdevice->render_fd,
437bf215546Sopenharmony_ci                           DRM_IOCTL_V3D_PERFMON_GET_VALUES,
438bf215546Sopenharmony_ci                           &req);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci      if (ret) {
441bf215546Sopenharmony_ci         fprintf(stderr, "failed to get perfmon values: %s\n", strerror(ret));
442bf215546Sopenharmony_ci         return vk_error(device, VK_ERROR_DEVICE_LOST);
443bf215546Sopenharmony_ci      }
444bf215546Sopenharmony_ci   }
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pool->perfmon.ncounters; i++)
447bf215546Sopenharmony_ci      write_to_buffer(data, slot + i, do_64bit, counter_values[i]);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   return VK_SUCCESS;
450bf215546Sopenharmony_ci}
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_cistatic VkResult
453bf215546Sopenharmony_ciquery_check_available(struct v3dv_device *device,
454bf215546Sopenharmony_ci                      struct v3dv_query *q,
455bf215546Sopenharmony_ci                      VkQueryType query_type)
456bf215546Sopenharmony_ci{
457bf215546Sopenharmony_ci   if (!q->maybe_available)
458bf215546Sopenharmony_ci      return VK_NOT_READY;
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   if (query_type == VK_QUERY_TYPE_OCCLUSION &&
461bf215546Sopenharmony_ci       !v3dv_bo_wait(device, q->bo, 0))
462bf215546Sopenharmony_ci      return VK_NOT_READY;
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci   if (query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR &&
465bf215546Sopenharmony_ci       vk_sync_wait(&device->vk, q->perf.last_job_sync,
466bf215546Sopenharmony_ci                    0, VK_SYNC_WAIT_COMPLETE, 0) != VK_SUCCESS)
467bf215546Sopenharmony_ci      return VK_NOT_READY;
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci   return VK_SUCCESS;
470bf215546Sopenharmony_ci}
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_cistatic VkResult
473bf215546Sopenharmony_ciwrite_query_result(struct v3dv_device *device,
474bf215546Sopenharmony_ci                   struct v3dv_query_pool *pool,
475bf215546Sopenharmony_ci                   uint32_t query,
476bf215546Sopenharmony_ci                   bool do_64bit,
477bf215546Sopenharmony_ci                   void *data,
478bf215546Sopenharmony_ci                   uint32_t slot)
479bf215546Sopenharmony_ci{
480bf215546Sopenharmony_ci   switch (pool->query_type) {
481bf215546Sopenharmony_ci   case VK_QUERY_TYPE_OCCLUSION:
482bf215546Sopenharmony_ci      return write_occlusion_query_result(device, pool, query, do_64bit,
483bf215546Sopenharmony_ci                                          data, slot);
484bf215546Sopenharmony_ci   case VK_QUERY_TYPE_TIMESTAMP:
485bf215546Sopenharmony_ci      return write_timestamp_query_result(device, pool, query, do_64bit,
486bf215546Sopenharmony_ci                                          data, slot);
487bf215546Sopenharmony_ci   case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
488bf215546Sopenharmony_ci      return write_performance_query_result(device, pool, query, do_64bit,
489bf215546Sopenharmony_ci                                            data, slot);
490bf215546Sopenharmony_ci   default:
491bf215546Sopenharmony_ci      unreachable("Unsupported query type");
492bf215546Sopenharmony_ci   }
493bf215546Sopenharmony_ci}
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_cistatic VkResult
496bf215546Sopenharmony_ciquery_is_available(struct v3dv_device *device,
497bf215546Sopenharmony_ci                   struct v3dv_query_pool *pool,
498bf215546Sopenharmony_ci                   uint32_t query,
499bf215546Sopenharmony_ci                   bool do_wait,
500bf215546Sopenharmony_ci                   bool *available)
501bf215546Sopenharmony_ci{
502bf215546Sopenharmony_ci   struct v3dv_query *q = &pool->queries[query];
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   assert(pool->query_type != VK_QUERY_TYPE_OCCLUSION ||
505bf215546Sopenharmony_ci          (q->bo && q->bo->map));
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   if (do_wait) {
508bf215546Sopenharmony_ci      VkResult result = query_wait_available(device, q, pool->query_type);
509bf215546Sopenharmony_ci      if (result != VK_SUCCESS) {
510bf215546Sopenharmony_ci         *available = false;
511bf215546Sopenharmony_ci         return result;
512bf215546Sopenharmony_ci      }
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci      *available = true;
515bf215546Sopenharmony_ci   } else {
516bf215546Sopenharmony_ci      VkResult result = query_check_available(device, q, pool->query_type);
517bf215546Sopenharmony_ci      assert(result == VK_SUCCESS || result == VK_NOT_READY);
518bf215546Sopenharmony_ci      *available = (result == VK_SUCCESS);
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci   return VK_SUCCESS;
522bf215546Sopenharmony_ci}
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_cistatic uint32_t
525bf215546Sopenharmony_ciget_query_result_count(struct v3dv_query_pool *pool)
526bf215546Sopenharmony_ci{
527bf215546Sopenharmony_ci   switch (pool->query_type) {
528bf215546Sopenharmony_ci   case VK_QUERY_TYPE_OCCLUSION:
529bf215546Sopenharmony_ci   case VK_QUERY_TYPE_TIMESTAMP:
530bf215546Sopenharmony_ci      return 1;
531bf215546Sopenharmony_ci   case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
532bf215546Sopenharmony_ci      return pool->perfmon.ncounters;
533bf215546Sopenharmony_ci   default:
534bf215546Sopenharmony_ci      unreachable("Unsupported query type");
535bf215546Sopenharmony_ci   }
536bf215546Sopenharmony_ci}
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ciVkResult
539bf215546Sopenharmony_civ3dv_get_query_pool_results(struct v3dv_device *device,
540bf215546Sopenharmony_ci                            struct v3dv_query_pool *pool,
541bf215546Sopenharmony_ci                            uint32_t first,
542bf215546Sopenharmony_ci                            uint32_t count,
543bf215546Sopenharmony_ci                            void *data,
544bf215546Sopenharmony_ci                            VkDeviceSize stride,
545bf215546Sopenharmony_ci                            VkQueryResultFlags flags)
546bf215546Sopenharmony_ci{
547bf215546Sopenharmony_ci   assert(first < pool->query_count);
548bf215546Sopenharmony_ci   assert(first + count <= pool->query_count);
549bf215546Sopenharmony_ci   assert(data);
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   const bool do_64bit = flags & VK_QUERY_RESULT_64_BIT ||
552bf215546Sopenharmony_ci      pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR;
553bf215546Sopenharmony_ci   const bool do_wait = flags & VK_QUERY_RESULT_WAIT_BIT;
554bf215546Sopenharmony_ci   const bool do_partial = flags & VK_QUERY_RESULT_PARTIAL_BIT;
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci   uint32_t result_count = get_query_result_count(pool);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
559bf215546Sopenharmony_ci   for (uint32_t i = first; i < first + count; i++) {
560bf215546Sopenharmony_ci      bool available = false;
561bf215546Sopenharmony_ci      VkResult query_result =
562bf215546Sopenharmony_ci         query_is_available(device, pool, i, do_wait, &available);
563bf215546Sopenharmony_ci      if (query_result == VK_ERROR_DEVICE_LOST)
564bf215546Sopenharmony_ci         result = VK_ERROR_DEVICE_LOST;
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci      /**
567bf215546Sopenharmony_ci       * From the Vulkan 1.0 spec:
568bf215546Sopenharmony_ci       *
569bf215546Sopenharmony_ci       *    "If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are
570bf215546Sopenharmony_ci       *     both not set then no result values are written to pData for queries
571bf215546Sopenharmony_ci       *     that are in the unavailable state at the time of the call, and
572bf215546Sopenharmony_ci       *     vkGetQueryPoolResults returns VK_NOT_READY. However, availability
573bf215546Sopenharmony_ci       *     state is still written to pData for those queries if
574bf215546Sopenharmony_ci       *     VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set."
575bf215546Sopenharmony_ci       */
576bf215546Sopenharmony_ci      uint32_t slot = 0;
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci      const bool write_result = available || do_partial;
579bf215546Sopenharmony_ci      if (write_result)
580bf215546Sopenharmony_ci         write_query_result(device, pool, i, do_64bit, data, slot);
581bf215546Sopenharmony_ci      slot += result_count;
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci      if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
584bf215546Sopenharmony_ci         write_to_buffer(data, slot++, do_64bit, available ? 1u : 0u);
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci      if (!write_result && result != VK_ERROR_DEVICE_LOST)
587bf215546Sopenharmony_ci         result = VK_NOT_READY;
588bf215546Sopenharmony_ci
589bf215546Sopenharmony_ci      data += stride;
590bf215546Sopenharmony_ci   }
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci   return result;
593bf215546Sopenharmony_ci}
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
596bf215546Sopenharmony_civ3dv_GetQueryPoolResults(VkDevice _device,
597bf215546Sopenharmony_ci                         VkQueryPool queryPool,
598bf215546Sopenharmony_ci                         uint32_t firstQuery,
599bf215546Sopenharmony_ci                         uint32_t queryCount,
600bf215546Sopenharmony_ci                         size_t dataSize,
601bf215546Sopenharmony_ci                         void *pData,
602bf215546Sopenharmony_ci                         VkDeviceSize stride,
603bf215546Sopenharmony_ci                         VkQueryResultFlags flags)
604bf215546Sopenharmony_ci{
605bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
606bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci   return v3dv_get_query_pool_results(device, pool, firstQuery, queryCount,
609bf215546Sopenharmony_ci                                      pData, stride, flags);
610bf215546Sopenharmony_ci}
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
613bf215546Sopenharmony_civ3dv_CmdResetQueryPool(VkCommandBuffer commandBuffer,
614bf215546Sopenharmony_ci                       VkQueryPool queryPool,
615bf215546Sopenharmony_ci                       uint32_t firstQuery,
616bf215546Sopenharmony_ci                       uint32_t queryCount)
617bf215546Sopenharmony_ci{
618bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
619bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci   v3dv_cmd_buffer_reset_queries(cmd_buffer, pool, firstQuery, queryCount);
622bf215546Sopenharmony_ci}
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
625bf215546Sopenharmony_civ3dv_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
626bf215546Sopenharmony_ci                             VkQueryPool queryPool,
627bf215546Sopenharmony_ci                             uint32_t firstQuery,
628bf215546Sopenharmony_ci                             uint32_t queryCount,
629bf215546Sopenharmony_ci                             VkBuffer dstBuffer,
630bf215546Sopenharmony_ci                             VkDeviceSize dstOffset,
631bf215546Sopenharmony_ci                             VkDeviceSize stride,
632bf215546Sopenharmony_ci                             VkQueryResultFlags flags)
633bf215546Sopenharmony_ci{
634bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
635bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
636bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_buffer, dst, dstBuffer);
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci   v3dv_cmd_buffer_copy_query_results(cmd_buffer, pool,
639bf215546Sopenharmony_ci                                      firstQuery, queryCount,
640bf215546Sopenharmony_ci                                      dst, dstOffset, stride, flags);
641bf215546Sopenharmony_ci}
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
644bf215546Sopenharmony_civ3dv_CmdBeginQuery(VkCommandBuffer commandBuffer,
645bf215546Sopenharmony_ci                   VkQueryPool queryPool,
646bf215546Sopenharmony_ci                   uint32_t query,
647bf215546Sopenharmony_ci                   VkQueryControlFlags flags)
648bf215546Sopenharmony_ci{
649bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
650bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci   v3dv_cmd_buffer_begin_query(cmd_buffer, pool, query, flags);
653bf215546Sopenharmony_ci}
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
656bf215546Sopenharmony_civ3dv_CmdEndQuery(VkCommandBuffer commandBuffer,
657bf215546Sopenharmony_ci                 VkQueryPool queryPool,
658bf215546Sopenharmony_ci                 uint32_t query)
659bf215546Sopenharmony_ci{
660bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
661bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   v3dv_cmd_buffer_end_query(cmd_buffer, pool, query);
664bf215546Sopenharmony_ci}
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_civoid
667bf215546Sopenharmony_civ3dv_reset_query_pools(struct v3dv_device *device,
668bf215546Sopenharmony_ci                       struct v3dv_query_pool *pool,
669bf215546Sopenharmony_ci                       uint32_t first,
670bf215546Sopenharmony_ci                       uint32_t count)
671bf215546Sopenharmony_ci{
672bf215546Sopenharmony_ci   mtx_lock(&device->query_mutex);
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   for (uint32_t i = first; i < first + count; i++) {
675bf215546Sopenharmony_ci      assert(i < pool->query_count);
676bf215546Sopenharmony_ci      struct v3dv_query *q = &pool->queries[i];
677bf215546Sopenharmony_ci      q->maybe_available = false;
678bf215546Sopenharmony_ci      switch (pool->query_type) {
679bf215546Sopenharmony_ci      case VK_QUERY_TYPE_OCCLUSION: {
680bf215546Sopenharmony_ci         const uint8_t *q_addr = ((uint8_t *) q->bo->map) + q->offset;
681bf215546Sopenharmony_ci         uint32_t *counter = (uint32_t *) q_addr;
682bf215546Sopenharmony_ci         *counter = 0;
683bf215546Sopenharmony_ci         break;
684bf215546Sopenharmony_ci      }
685bf215546Sopenharmony_ci      case VK_QUERY_TYPE_TIMESTAMP:
686bf215546Sopenharmony_ci         q->value = 0;
687bf215546Sopenharmony_ci         break;
688bf215546Sopenharmony_ci      case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR:
689bf215546Sopenharmony_ci         kperfmon_destroy(device, pool, i);
690bf215546Sopenharmony_ci         kperfmon_create(device, pool, i);
691bf215546Sopenharmony_ci         if (vk_sync_reset(&device->vk, q->perf.last_job_sync) != VK_SUCCESS)
692bf215546Sopenharmony_ci            fprintf(stderr, "Failed to reset sync");
693bf215546Sopenharmony_ci         break;
694bf215546Sopenharmony_ci      default:
695bf215546Sopenharmony_ci         unreachable("Unsupported query type");
696bf215546Sopenharmony_ci      }
697bf215546Sopenharmony_ci   }
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci   mtx_unlock(&device->query_mutex);
700bf215546Sopenharmony_ci}
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
703bf215546Sopenharmony_civ3dv_ResetQueryPool(VkDevice _device,
704bf215546Sopenharmony_ci                    VkQueryPool queryPool,
705bf215546Sopenharmony_ci                    uint32_t firstQuery,
706bf215546Sopenharmony_ci                    uint32_t queryCount)
707bf215546Sopenharmony_ci{
708bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_device, device, _device);
709bf215546Sopenharmony_ci   V3DV_FROM_HANDLE(v3dv_query_pool, pool, queryPool);
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_ci   v3dv_reset_query_pools(device, pool, firstQuery, queryCount);
712bf215546Sopenharmony_ci}
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
715bf215546Sopenharmony_civ3dv_EnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
716bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
717bf215546Sopenharmony_ci   uint32_t queueFamilyIndex,
718bf215546Sopenharmony_ci   uint32_t *pCounterCount,
719bf215546Sopenharmony_ci   VkPerformanceCounterKHR *pCounters,
720bf215546Sopenharmony_ci   VkPerformanceCounterDescriptionKHR *pCounterDescriptions)
721bf215546Sopenharmony_ci{
722bf215546Sopenharmony_ci   uint32_t desc_count = *pCounterCount;
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkPerformanceCounterKHR,
725bf215546Sopenharmony_ci                          out, pCounters, pCounterCount);
726bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkPerformanceCounterDescriptionKHR,
727bf215546Sopenharmony_ci                          out_desc, pCounterDescriptions, &desc_count);
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   for (int i = 0; i < ARRAY_SIZE(v3dv_counters); i++) {
730bf215546Sopenharmony_ci      vk_outarray_append_typed(VkPerformanceCounterKHR, &out, counter) {
731bf215546Sopenharmony_ci         counter->unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR;
732bf215546Sopenharmony_ci         counter->scope = VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR;
733bf215546Sopenharmony_ci         counter->storage = VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR;
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci         unsigned char sha1_result[20];
736bf215546Sopenharmony_ci         _mesa_sha1_compute(v3dv_counters[i][1], strlen(v3dv_counters[i][1]),
737bf215546Sopenharmony_ci                            sha1_result);
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci         memcpy(counter->uuid, sha1_result, sizeof(counter->uuid));
740bf215546Sopenharmony_ci      }
741bf215546Sopenharmony_ci
742bf215546Sopenharmony_ci      vk_outarray_append_typed(VkPerformanceCounterDescriptionKHR,
743bf215546Sopenharmony_ci                               &out_desc, desc) {
744bf215546Sopenharmony_ci         desc->flags = 0;
745bf215546Sopenharmony_ci         snprintf(desc->name, sizeof(desc->name), "%s",
746bf215546Sopenharmony_ci            v3dv_counters[i][1]);
747bf215546Sopenharmony_ci         snprintf(desc->category, sizeof(desc->category), "%s",
748bf215546Sopenharmony_ci            v3dv_counters[i][0]);
749bf215546Sopenharmony_ci         snprintf(desc->description, sizeof(desc->description), "%s",
750bf215546Sopenharmony_ci            v3dv_counters[i][2]);
751bf215546Sopenharmony_ci      }
752bf215546Sopenharmony_ci   }
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci   return vk_outarray_status(&out);
755bf215546Sopenharmony_ci}
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
758bf215546Sopenharmony_civ3dv_GetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
759bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
760bf215546Sopenharmony_ci   const VkQueryPoolPerformanceCreateInfoKHR *pPerformanceQueryCreateInfo,
761bf215546Sopenharmony_ci   uint32_t *pNumPasses)
762bf215546Sopenharmony_ci{
763bf215546Sopenharmony_ci   *pNumPasses = DIV_ROUND_UP(pPerformanceQueryCreateInfo->counterIndexCount,
764bf215546Sopenharmony_ci                              DRM_V3D_MAX_PERF_COUNTERS);
765bf215546Sopenharmony_ci}
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
768bf215546Sopenharmony_civ3dv_AcquireProfilingLockKHR(
769bf215546Sopenharmony_ci   VkDevice _device,
770bf215546Sopenharmony_ci   const VkAcquireProfilingLockInfoKHR *pInfo)
771bf215546Sopenharmony_ci{
772bf215546Sopenharmony_ci   return VK_SUCCESS;
773bf215546Sopenharmony_ci}
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
776bf215546Sopenharmony_civ3dv_ReleaseProfilingLockKHR(VkDevice device)
777bf215546Sopenharmony_ci{
778bf215546Sopenharmony_ci}
779