1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2019 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * based in part on anv and radv which are: 6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 9bf215546Sopenharmony_ci */ 10bf215546Sopenharmony_ci 11bf215546Sopenharmony_ci#include "vn_query_pool.h" 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_query_pool.h" 14bf215546Sopenharmony_ci 15bf215546Sopenharmony_ci#include "vn_device.h" 16bf215546Sopenharmony_ci 17bf215546Sopenharmony_ci/* query pool commands */ 18bf215546Sopenharmony_ci 19bf215546Sopenharmony_ciVkResult 20bf215546Sopenharmony_civn_CreateQueryPool(VkDevice device, 21bf215546Sopenharmony_ci const VkQueryPoolCreateInfo *pCreateInfo, 22bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 23bf215546Sopenharmony_ci VkQueryPool *pQueryPool) 24bf215546Sopenharmony_ci{ 25bf215546Sopenharmony_ci VN_TRACE_FUNC(); 26bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 27bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 28bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci struct vn_query_pool *pool = 31bf215546Sopenharmony_ci vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN, 32bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 33bf215546Sopenharmony_ci if (!pool) 34bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci vn_object_base_init(&pool->base, VK_OBJECT_TYPE_QUERY_POOL, &dev->base); 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci pool->allocator = *alloc; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci switch (pCreateInfo->queryType) { 41bf215546Sopenharmony_ci case VK_QUERY_TYPE_OCCLUSION: 42bf215546Sopenharmony_ci pool->result_array_size = 1; 43bf215546Sopenharmony_ci break; 44bf215546Sopenharmony_ci case VK_QUERY_TYPE_PIPELINE_STATISTICS: 45bf215546Sopenharmony_ci pool->result_array_size = 46bf215546Sopenharmony_ci util_bitcount(pCreateInfo->pipelineStatistics); 47bf215546Sopenharmony_ci break; 48bf215546Sopenharmony_ci case VK_QUERY_TYPE_TIMESTAMP: 49bf215546Sopenharmony_ci pool->result_array_size = 1; 50bf215546Sopenharmony_ci break; 51bf215546Sopenharmony_ci case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: 52bf215546Sopenharmony_ci pool->result_array_size = 2; 53bf215546Sopenharmony_ci break; 54bf215546Sopenharmony_ci default: 55bf215546Sopenharmony_ci unreachable("bad query type"); 56bf215546Sopenharmony_ci break; 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci VkQueryPool pool_handle = vn_query_pool_to_handle(pool); 60bf215546Sopenharmony_ci vn_async_vkCreateQueryPool(dev->instance, device, pCreateInfo, NULL, 61bf215546Sopenharmony_ci &pool_handle); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci *pQueryPool = pool_handle; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci return VK_SUCCESS; 66bf215546Sopenharmony_ci} 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_civoid 69bf215546Sopenharmony_civn_DestroyQueryPool(VkDevice device, 70bf215546Sopenharmony_ci VkQueryPool queryPool, 71bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci VN_TRACE_FUNC(); 74bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 75bf215546Sopenharmony_ci struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool); 76bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (!pool) 79bf215546Sopenharmony_ci return; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci alloc = pAllocator ? pAllocator : &pool->allocator; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci vn_async_vkDestroyQueryPool(dev->instance, device, queryPool, NULL); 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci vn_object_base_fini(&pool->base); 86bf215546Sopenharmony_ci vk_free(alloc, pool); 87bf215546Sopenharmony_ci} 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_civoid 90bf215546Sopenharmony_civn_ResetQueryPool(VkDevice device, 91bf215546Sopenharmony_ci VkQueryPool queryPool, 92bf215546Sopenharmony_ci uint32_t firstQuery, 93bf215546Sopenharmony_ci uint32_t queryCount) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci VN_TRACE_FUNC(); 96bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci vn_async_vkResetQueryPool(dev->instance, device, queryPool, firstQuery, 99bf215546Sopenharmony_ci queryCount); 100bf215546Sopenharmony_ci} 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ciVkResult 103bf215546Sopenharmony_civn_GetQueryPoolResults(VkDevice device, 104bf215546Sopenharmony_ci VkQueryPool queryPool, 105bf215546Sopenharmony_ci uint32_t firstQuery, 106bf215546Sopenharmony_ci uint32_t queryCount, 107bf215546Sopenharmony_ci size_t dataSize, 108bf215546Sopenharmony_ci void *pData, 109bf215546Sopenharmony_ci VkDeviceSize stride, 110bf215546Sopenharmony_ci VkQueryResultFlags flags) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci VN_TRACE_FUNC(); 113bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 114bf215546Sopenharmony_ci struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool); 115bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &pool->allocator; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci const size_t result_width = flags & VK_QUERY_RESULT_64_BIT ? 8 : 4; 118bf215546Sopenharmony_ci const size_t result_size = pool->result_array_size * result_width; 119bf215546Sopenharmony_ci const bool result_always_written = 120bf215546Sopenharmony_ci flags & (VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_PARTIAL_BIT); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci VkQueryResultFlags packed_flags = flags; 123bf215546Sopenharmony_ci size_t packed_stride = result_size; 124bf215546Sopenharmony_ci if (!result_always_written) 125bf215546Sopenharmony_ci packed_flags |= VK_QUERY_RESULT_WITH_AVAILABILITY_BIT; 126bf215546Sopenharmony_ci if (packed_flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) 127bf215546Sopenharmony_ci packed_stride += result_width; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci const size_t packed_size = packed_stride * queryCount; 130bf215546Sopenharmony_ci void *packed_data; 131bf215546Sopenharmony_ci if (result_always_written && packed_stride == stride) { 132bf215546Sopenharmony_ci packed_data = pData; 133bf215546Sopenharmony_ci } else { 134bf215546Sopenharmony_ci packed_data = vk_alloc(alloc, packed_size, VN_DEFAULT_ALIGN, 135bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 136bf215546Sopenharmony_ci if (!packed_data) 137bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci /* TODO the renderer should transparently vkCmdCopyQueryPoolResults to a 141bf215546Sopenharmony_ci * coherent memory such that we can memcpy from the coherent memory to 142bf215546Sopenharmony_ci * avoid this serialized round trip. 143bf215546Sopenharmony_ci */ 144bf215546Sopenharmony_ci VkResult result = vn_call_vkGetQueryPoolResults( 145bf215546Sopenharmony_ci dev->instance, device, queryPool, firstQuery, queryCount, packed_size, 146bf215546Sopenharmony_ci packed_data, packed_stride, packed_flags); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (packed_data == pData) 149bf215546Sopenharmony_ci return vn_result(dev->instance, result); 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci const size_t copy_size = 152bf215546Sopenharmony_ci result_size + 153bf215546Sopenharmony_ci (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT ? result_width : 0); 154bf215546Sopenharmony_ci const void *src = packed_data; 155bf215546Sopenharmony_ci void *dst = pData; 156bf215546Sopenharmony_ci if (result == VK_SUCCESS) { 157bf215546Sopenharmony_ci for (uint32_t i = 0; i < queryCount; i++) { 158bf215546Sopenharmony_ci memcpy(dst, src, copy_size); 159bf215546Sopenharmony_ci src += packed_stride; 160bf215546Sopenharmony_ci dst += stride; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci } else if (result == VK_NOT_READY) { 163bf215546Sopenharmony_ci assert(!result_always_written && 164bf215546Sopenharmony_ci (packed_flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)); 165bf215546Sopenharmony_ci if (flags & VK_QUERY_RESULT_64_BIT) { 166bf215546Sopenharmony_ci for (uint32_t i = 0; i < queryCount; i++) { 167bf215546Sopenharmony_ci const bool avail = *(const uint64_t *)(src + result_size); 168bf215546Sopenharmony_ci if (avail) 169bf215546Sopenharmony_ci memcpy(dst, src, copy_size); 170bf215546Sopenharmony_ci else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) 171bf215546Sopenharmony_ci *(uint64_t *)(dst + result_size) = 0; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci src += packed_stride; 174bf215546Sopenharmony_ci dst += stride; 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci } else { 177bf215546Sopenharmony_ci for (uint32_t i = 0; i < queryCount; i++) { 178bf215546Sopenharmony_ci const bool avail = *(const uint32_t *)(src + result_size); 179bf215546Sopenharmony_ci if (avail) 180bf215546Sopenharmony_ci memcpy(dst, src, copy_size); 181bf215546Sopenharmony_ci else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) 182bf215546Sopenharmony_ci *(uint32_t *)(dst + result_size) = 0; 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci src += packed_stride; 185bf215546Sopenharmony_ci dst += stride; 186bf215546Sopenharmony_ci } 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci vk_free(alloc, packed_data); 191bf215546Sopenharmony_ci return vn_result(dev->instance, result); 192bf215546Sopenharmony_ci} 193