1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation
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 "dzn_private.h"
25bf215546Sopenharmony_ci#include "dzn_abi_helper.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "vk_alloc.h"
28bf215546Sopenharmony_ci#include "vk_debug_report.h"
29bf215546Sopenharmony_ci#include "vk_util.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "os_time.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_cistatic D3D12_QUERY_HEAP_TYPE
34bf215546Sopenharmony_cidzn_query_pool_get_heap_type(VkQueryType in)
35bf215546Sopenharmony_ci{
36bf215546Sopenharmony_ci   switch (in) {
37bf215546Sopenharmony_ci   case VK_QUERY_TYPE_OCCLUSION: return D3D12_QUERY_HEAP_TYPE_OCCLUSION;
38bf215546Sopenharmony_ci   case VK_QUERY_TYPE_PIPELINE_STATISTICS: return D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS;
39bf215546Sopenharmony_ci   case VK_QUERY_TYPE_TIMESTAMP: return D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
40bf215546Sopenharmony_ci   default: unreachable("Unsupported query type");
41bf215546Sopenharmony_ci   }
42bf215546Sopenharmony_ci}
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ciD3D12_QUERY_TYPE
45bf215546Sopenharmony_cidzn_query_pool_get_query_type(const struct dzn_query_pool *qpool,
46bf215546Sopenharmony_ci                              VkQueryControlFlags flags)
47bf215546Sopenharmony_ci{
48bf215546Sopenharmony_ci   switch (qpool->heap_type) {
49bf215546Sopenharmony_ci   case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
50bf215546Sopenharmony_ci      return flags & VK_QUERY_CONTROL_PRECISE_BIT ?
51bf215546Sopenharmony_ci             D3D12_QUERY_TYPE_OCCLUSION : D3D12_QUERY_TYPE_BINARY_OCCLUSION;
52bf215546Sopenharmony_ci   case D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS: return D3D12_QUERY_TYPE_PIPELINE_STATISTICS;
53bf215546Sopenharmony_ci   case D3D12_QUERY_HEAP_TYPE_TIMESTAMP: return D3D12_QUERY_TYPE_TIMESTAMP;
54bf215546Sopenharmony_ci   default: unreachable("Unsupported query type");
55bf215546Sopenharmony_ci   }
56bf215546Sopenharmony_ci}
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_cistatic void
59bf215546Sopenharmony_cidzn_query_pool_destroy(struct dzn_query_pool *qpool,
60bf215546Sopenharmony_ci                       const VkAllocationCallbacks *alloc)
61bf215546Sopenharmony_ci{
62bf215546Sopenharmony_ci   if (!qpool)
63bf215546Sopenharmony_ci      return;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   struct dzn_device *device = container_of(qpool->base.device, struct dzn_device, vk);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   if (qpool->collect_map)
68bf215546Sopenharmony_ci      ID3D12Resource_Unmap(qpool->collect_buffer, 0, NULL);
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   if (qpool->collect_buffer)
71bf215546Sopenharmony_ci      ID3D12Resource_Release(qpool->collect_buffer);
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci   if (qpool->resolve_buffer)
74bf215546Sopenharmony_ci      ID3D12Resource_Release(qpool->resolve_buffer);
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   if (qpool->heap)
77bf215546Sopenharmony_ci      ID3D12QueryHeap_Release(qpool->heap);
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   for (uint32_t q = 0; q < qpool->query_count; q++) {
80bf215546Sopenharmony_ci      if (qpool->queries[q].fence)
81bf215546Sopenharmony_ci         ID3D12Fence_Release(qpool->queries[q].fence);
82bf215546Sopenharmony_ci   }
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   mtx_destroy(&qpool->queries_lock);
85bf215546Sopenharmony_ci   vk_object_base_finish(&qpool->base);
86bf215546Sopenharmony_ci   vk_free2(&device->vk.alloc, alloc, qpool);
87bf215546Sopenharmony_ci}
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_cistatic VkResult
90bf215546Sopenharmony_cidzn_query_pool_create(struct dzn_device *device,
91bf215546Sopenharmony_ci                      const VkQueryPoolCreateInfo *info,
92bf215546Sopenharmony_ci                      const VkAllocationCallbacks *alloc,
93bf215546Sopenharmony_ci                      VkQueryPool *out)
94bf215546Sopenharmony_ci{
95bf215546Sopenharmony_ci   VK_MULTIALLOC(ma);
96bf215546Sopenharmony_ci   VK_MULTIALLOC_DECL(&ma, struct dzn_query_pool, qpool, 1);
97bf215546Sopenharmony_ci   VK_MULTIALLOC_DECL(&ma, struct dzn_query, queries, info->queryCount);
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, alloc,
100bf215546Sopenharmony_ci                              VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
101bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   vk_object_base_init(&device->vk, &qpool->base, VK_OBJECT_TYPE_QUERY_POOL);
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   mtx_init(&qpool->queries_lock, mtx_plain);
106bf215546Sopenharmony_ci   qpool->query_count = info->queryCount;
107bf215546Sopenharmony_ci   qpool->queries = queries;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   D3D12_QUERY_HEAP_DESC desc = { 0 };
110bf215546Sopenharmony_ci   qpool->heap_type = desc.Type = dzn_query_pool_get_heap_type(info->queryType);
111bf215546Sopenharmony_ci   desc.Count = info->queryCount;
112bf215546Sopenharmony_ci   desc.NodeMask = 0;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   HRESULT hres =
115bf215546Sopenharmony_ci      ID3D12Device1_CreateQueryHeap(device->dev, &desc,
116bf215546Sopenharmony_ci                                    &IID_ID3D12QueryHeap,
117bf215546Sopenharmony_ci                                    (void **)&qpool->heap);
118bf215546Sopenharmony_ci   if (FAILED(hres)) {
119bf215546Sopenharmony_ci      dzn_query_pool_destroy(qpool, alloc);
120bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
121bf215546Sopenharmony_ci   }
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   switch (info->queryType) {
124bf215546Sopenharmony_ci   case VK_QUERY_TYPE_OCCLUSION:
125bf215546Sopenharmony_ci   case VK_QUERY_TYPE_TIMESTAMP:
126bf215546Sopenharmony_ci      qpool->query_size = sizeof(uint64_t);
127bf215546Sopenharmony_ci      break;
128bf215546Sopenharmony_ci   case VK_QUERY_TYPE_PIPELINE_STATISTICS:
129bf215546Sopenharmony_ci      qpool->pipeline_statistics = info->pipelineStatistics;
130bf215546Sopenharmony_ci      qpool->query_size = sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS);
131bf215546Sopenharmony_ci      break;
132bf215546Sopenharmony_ci   default: unreachable("Unsupported query type");
133bf215546Sopenharmony_ci   }
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   D3D12_HEAP_PROPERTIES hprops =
136bf215546Sopenharmony_ci      dzn_ID3D12Device2_GetCustomHeapProperties(device->dev, 0, D3D12_HEAP_TYPE_DEFAULT);
137bf215546Sopenharmony_ci   D3D12_RESOURCE_DESC rdesc = {
138bf215546Sopenharmony_ci      .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
139bf215546Sopenharmony_ci      .Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
140bf215546Sopenharmony_ci      .Width = info->queryCount * qpool->query_size,
141bf215546Sopenharmony_ci      .Height = 1,
142bf215546Sopenharmony_ci      .DepthOrArraySize = 1,
143bf215546Sopenharmony_ci      .MipLevels = 1,
144bf215546Sopenharmony_ci      .Format = DXGI_FORMAT_UNKNOWN,
145bf215546Sopenharmony_ci      .SampleDesc = { .Count = 1, .Quality = 0 },
146bf215546Sopenharmony_ci      .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
147bf215546Sopenharmony_ci      .Flags = D3D12_RESOURCE_FLAG_NONE,
148bf215546Sopenharmony_ci   };
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   hres = ID3D12Device1_CreateCommittedResource(device->dev, &hprops,
151bf215546Sopenharmony_ci                                                D3D12_HEAP_FLAG_NONE,
152bf215546Sopenharmony_ci                                                &rdesc,
153bf215546Sopenharmony_ci                                                D3D12_RESOURCE_STATE_COPY_DEST,
154bf215546Sopenharmony_ci                                                NULL,
155bf215546Sopenharmony_ci                                                &IID_ID3D12Resource,
156bf215546Sopenharmony_ci                                                (void **)&qpool->resolve_buffer);
157bf215546Sopenharmony_ci   if (FAILED(hres)) {
158bf215546Sopenharmony_ci      dzn_query_pool_destroy(qpool, alloc);
159bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
160bf215546Sopenharmony_ci   }
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   hprops = dzn_ID3D12Device2_GetCustomHeapProperties(device->dev, 0,
163bf215546Sopenharmony_ci                                                      D3D12_HEAP_TYPE_READBACK);
164bf215546Sopenharmony_ci   rdesc.Width = info->queryCount * (qpool->query_size + sizeof(uint64_t));
165bf215546Sopenharmony_ci   hres = ID3D12Device1_CreateCommittedResource(device->dev, &hprops,
166bf215546Sopenharmony_ci                                                D3D12_HEAP_FLAG_NONE,
167bf215546Sopenharmony_ci                                                &rdesc,
168bf215546Sopenharmony_ci                                                D3D12_RESOURCE_STATE_COPY_DEST,
169bf215546Sopenharmony_ci                                                NULL,
170bf215546Sopenharmony_ci                                                &IID_ID3D12Resource,
171bf215546Sopenharmony_ci                                                (void **)&qpool->collect_buffer);
172bf215546Sopenharmony_ci   if (FAILED(hres)) {
173bf215546Sopenharmony_ci      dzn_query_pool_destroy(qpool, alloc);
174bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
175bf215546Sopenharmony_ci   }
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   hres = ID3D12Resource_Map(qpool->collect_buffer, 0, NULL, (void **)&qpool->collect_map);
178bf215546Sopenharmony_ci   if (FAILED(hres)) {
179bf215546Sopenharmony_ci      dzn_query_pool_destroy(qpool, alloc);
180bf215546Sopenharmony_ci      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
181bf215546Sopenharmony_ci   }
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci   memset(qpool->collect_map, 0, rdesc.Width);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   *out = dzn_query_pool_to_handle(qpool);
186bf215546Sopenharmony_ci   return VK_SUCCESS;
187bf215546Sopenharmony_ci}
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ciuint32_t
190bf215546Sopenharmony_cidzn_query_pool_get_result_offset(const struct dzn_query_pool *qpool, uint32_t query)
191bf215546Sopenharmony_ci{
192bf215546Sopenharmony_ci   return query * qpool->query_size;
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ciuint32_t
196bf215546Sopenharmony_cidzn_query_pool_get_result_size(const struct dzn_query_pool *qpool, uint32_t query_count)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   return query_count * qpool->query_size;
199bf215546Sopenharmony_ci}
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ciuint32_t
202bf215546Sopenharmony_cidzn_query_pool_get_availability_offset(const struct dzn_query_pool *qpool, uint32_t query)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   return (qpool->query_count * qpool->query_size) + (sizeof(uint64_t) * query);
205bf215546Sopenharmony_ci}
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
208bf215546Sopenharmony_cidzn_CreateQueryPool(VkDevice device,
209bf215546Sopenharmony_ci                    const VkQueryPoolCreateInfo *pCreateInfo,
210bf215546Sopenharmony_ci                    const VkAllocationCallbacks *pAllocator,
211bf215546Sopenharmony_ci                    VkQueryPool *pQueryPool)
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci   return dzn_query_pool_create(dzn_device_from_handle(device),
214bf215546Sopenharmony_ci                                pCreateInfo, pAllocator, pQueryPool);
215bf215546Sopenharmony_ci}
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
218bf215546Sopenharmony_cidzn_DestroyQueryPool(VkDevice device,
219bf215546Sopenharmony_ci                     VkQueryPool queryPool,
220bf215546Sopenharmony_ci                     const VkAllocationCallbacks *pAllocator)
221bf215546Sopenharmony_ci{
222bf215546Sopenharmony_ci   dzn_query_pool_destroy(dzn_query_pool_from_handle(queryPool), pAllocator);
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
226bf215546Sopenharmony_cidzn_ResetQueryPool(VkDevice device,
227bf215546Sopenharmony_ci                   VkQueryPool queryPool,
228bf215546Sopenharmony_ci                   uint32_t firstQuery,
229bf215546Sopenharmony_ci                   uint32_t queryCount)
230bf215546Sopenharmony_ci{
231bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_query_pool, qpool, queryPool);
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   mtx_lock(&qpool->queries_lock);
234bf215546Sopenharmony_ci   for (uint32_t q = 0; q < queryCount; q++) {
235bf215546Sopenharmony_ci      struct dzn_query *query = &qpool->queries[firstQuery + q];
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci      query->fence_value = 0;
238bf215546Sopenharmony_ci      if (query->fence) {
239bf215546Sopenharmony_ci         ID3D12Fence_Release(query->fence);
240bf215546Sopenharmony_ci         query->fence = NULL;
241bf215546Sopenharmony_ci      }
242bf215546Sopenharmony_ci   }
243bf215546Sopenharmony_ci   mtx_lock(&qpool->queries_lock);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   memset((uint8_t *)qpool->collect_map + dzn_query_pool_get_result_offset(qpool, firstQuery),
246bf215546Sopenharmony_ci          0, queryCount * qpool->query_size);
247bf215546Sopenharmony_ci   memset((uint8_t *)qpool->collect_map + dzn_query_pool_get_availability_offset(qpool, firstQuery),
248bf215546Sopenharmony_ci          0, queryCount * sizeof(uint64_t));
249bf215546Sopenharmony_ci}
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
252bf215546Sopenharmony_cidzn_GetQueryPoolResults(VkDevice device,
253bf215546Sopenharmony_ci                        VkQueryPool queryPool,
254bf215546Sopenharmony_ci                        uint32_t firstQuery,
255bf215546Sopenharmony_ci                        uint32_t queryCount,
256bf215546Sopenharmony_ci                        size_t dataSize,
257bf215546Sopenharmony_ci                        void *pData,
258bf215546Sopenharmony_ci                        VkDeviceSize stride,
259bf215546Sopenharmony_ci                        VkQueryResultFlags flags)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   VK_FROM_HANDLE(dzn_query_pool, qpool, queryPool);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   uint32_t step = (flags & VK_QUERY_RESULT_64_BIT) ?
264bf215546Sopenharmony_ci                   sizeof(uint64_t) : sizeof(uint32_t);
265bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   for (uint32_t q = 0; q < queryCount; q++) {
268bf215546Sopenharmony_ci      struct dzn_query *query = &qpool->queries[q + firstQuery];
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci      uint8_t *dst_ptr = (uint8_t *)pData + (stride * q);
271bf215546Sopenharmony_ci      uint8_t *src_ptr =
272bf215546Sopenharmony_ci         (uint8_t *)qpool->collect_map +
273bf215546Sopenharmony_ci         dzn_query_pool_get_result_offset(qpool, firstQuery + q);
274bf215546Sopenharmony_ci      uint64_t available = 0;
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci      if (flags & VK_QUERY_RESULT_WAIT_BIT) {
277bf215546Sopenharmony_ci         ID3D12Fence *query_fence = NULL;
278bf215546Sopenharmony_ci         uint64_t query_fence_val = 0;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci         while (true) {
281bf215546Sopenharmony_ci            mtx_lock(&qpool->queries_lock);
282bf215546Sopenharmony_ci            if (query->fence) {
283bf215546Sopenharmony_ci               query_fence = query->fence;
284bf215546Sopenharmony_ci               ID3D12Fence_AddRef(query_fence);
285bf215546Sopenharmony_ci            }
286bf215546Sopenharmony_ci            query_fence_val = query->fence_value;
287bf215546Sopenharmony_ci            mtx_unlock(&qpool->queries_lock);
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci            if (query_fence)
290bf215546Sopenharmony_ci               break;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci            /* Check again in 10ms.
293bf215546Sopenharmony_ci             * FIXME: decrease the polling period if it happens to hurt latency.
294bf215546Sopenharmony_ci             */
295bf215546Sopenharmony_ci            os_time_sleep(10 * 1000);
296bf215546Sopenharmony_ci         }
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci         ID3D12Fence_SetEventOnCompletion(query_fence, query_fence_val, NULL);
299bf215546Sopenharmony_ci         ID3D12Fence_Release(query_fence);
300bf215546Sopenharmony_ci         available = UINT64_MAX;
301bf215546Sopenharmony_ci      } else {
302bf215546Sopenharmony_ci         ID3D12Fence *query_fence = NULL;
303bf215546Sopenharmony_ci         mtx_lock(&qpool->queries_lock);
304bf215546Sopenharmony_ci         if (query->fence) {
305bf215546Sopenharmony_ci            query_fence = query->fence;
306bf215546Sopenharmony_ci            ID3D12Fence_AddRef(query_fence);
307bf215546Sopenharmony_ci         }
308bf215546Sopenharmony_ci         uint64_t query_fence_val = query->fence_value;
309bf215546Sopenharmony_ci         mtx_unlock(&qpool->queries_lock);
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci         if (query_fence) {
312bf215546Sopenharmony_ci            if (ID3D12Fence_GetCompletedValue(query_fence) >= query_fence_val)
313bf215546Sopenharmony_ci               available = UINT64_MAX;
314bf215546Sopenharmony_ci            ID3D12Fence_Release(query_fence);
315bf215546Sopenharmony_ci         }
316bf215546Sopenharmony_ci      }
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci      if (qpool->heap_type != D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS) {
319bf215546Sopenharmony_ci         if (available)
320bf215546Sopenharmony_ci            memcpy(dst_ptr, src_ptr, step);
321bf215546Sopenharmony_ci         else if (flags & VK_QUERY_RESULT_PARTIAL_BIT)
322bf215546Sopenharmony_ci            memset(dst_ptr, 0, step);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci         dst_ptr += step;
325bf215546Sopenharmony_ci      } else {
326bf215546Sopenharmony_ci         for (uint32_t c = 0; c < sizeof(D3D12_QUERY_DATA_PIPELINE_STATISTICS) / sizeof(uint64_t); c++) {
327bf215546Sopenharmony_ci            if (!(BITFIELD_BIT(c) & qpool->pipeline_statistics))
328bf215546Sopenharmony_ci               continue;
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci            if (available)
331bf215546Sopenharmony_ci               memcpy(dst_ptr, src_ptr + (c * sizeof(uint64_t)), step);
332bf215546Sopenharmony_ci            else if (flags & VK_QUERY_RESULT_PARTIAL_BIT)
333bf215546Sopenharmony_ci               memset(dst_ptr, 0, step);
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci            dst_ptr += step;
336bf215546Sopenharmony_ci         }
337bf215546Sopenharmony_ci      }
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
340bf215546Sopenharmony_ci         memcpy(dst_ptr, &available, step);
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci      if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
343bf215546Sopenharmony_ci         result = VK_NOT_READY;
344bf215546Sopenharmony_ci   }
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci   return result;
347bf215546Sopenharmony_ci}
348