2021-04-08 00:37:33 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2019 Google LLC
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
* based in part on anv and radv which are:
|
|
|
|
* Copyright © 2015 Intel Corporation
|
|
|
|
* Copyright © 2016 Red Hat.
|
|
|
|
* Copyright © 2016 Bas Nieuwenhuizen
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "vn_query_pool.h"
|
|
|
|
|
|
|
|
#include "venus-protocol/vn_protocol_driver_query_pool.h"
|
|
|
|
|
|
|
|
#include "vn_device.h"
|
|
|
|
|
|
|
|
/* query pool commands */
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_CreateQueryPool(VkDevice device,
|
|
|
|
const VkQueryPoolCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkQueryPool *pQueryPool)
|
|
|
|
{
|
2022-07-12 07:31:37 +01:00
|
|
|
VN_TRACE_FUNC();
|
2021-04-08 00:37:33 +01:00
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
const VkAllocationCallbacks *alloc =
|
|
|
|
pAllocator ? pAllocator : &dev->base.base.alloc;
|
|
|
|
|
|
|
|
struct vn_query_pool *pool =
|
|
|
|
vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
if (!pool)
|
|
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
vn_object_base_init(&pool->base, VK_OBJECT_TYPE_QUERY_POOL, &dev->base);
|
|
|
|
|
|
|
|
pool->allocator = *alloc;
|
|
|
|
|
|
|
|
switch (pCreateInfo->queryType) {
|
|
|
|
case VK_QUERY_TYPE_OCCLUSION:
|
|
|
|
pool->result_array_size = 1;
|
|
|
|
break;
|
|
|
|
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
|
|
|
|
pool->result_array_size =
|
|
|
|
util_bitcount(pCreateInfo->pipelineStatistics);
|
|
|
|
break;
|
|
|
|
case VK_QUERY_TYPE_TIMESTAMP:
|
|
|
|
pool->result_array_size = 1;
|
|
|
|
break;
|
|
|
|
case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
|
|
|
|
pool->result_array_size = 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
unreachable("bad query type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkQueryPool pool_handle = vn_query_pool_to_handle(pool);
|
|
|
|
vn_async_vkCreateQueryPool(dev->instance, device, pCreateInfo, NULL,
|
|
|
|
&pool_handle);
|
|
|
|
|
|
|
|
*pQueryPool = pool_handle;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vn_DestroyQueryPool(VkDevice device,
|
|
|
|
VkQueryPool queryPool,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
2022-07-12 07:31:37 +01:00
|
|
|
VN_TRACE_FUNC();
|
2021-04-08 00:37:33 +01:00
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool);
|
|
|
|
const VkAllocationCallbacks *alloc;
|
|
|
|
|
|
|
|
if (!pool)
|
|
|
|
return;
|
|
|
|
|
|
|
|
alloc = pAllocator ? pAllocator : &pool->allocator;
|
|
|
|
|
|
|
|
vn_async_vkDestroyQueryPool(dev->instance, device, queryPool, NULL);
|
|
|
|
|
|
|
|
vn_object_base_fini(&pool->base);
|
|
|
|
vk_free(alloc, pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vn_ResetQueryPool(VkDevice device,
|
|
|
|
VkQueryPool queryPool,
|
|
|
|
uint32_t firstQuery,
|
|
|
|
uint32_t queryCount)
|
|
|
|
{
|
2022-07-12 07:31:37 +01:00
|
|
|
VN_TRACE_FUNC();
|
2021-04-08 00:37:33 +01:00
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
|
|
|
|
vn_async_vkResetQueryPool(dev->instance, device, queryPool, firstQuery,
|
|
|
|
queryCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
vn_GetQueryPoolResults(VkDevice device,
|
|
|
|
VkQueryPool queryPool,
|
|
|
|
uint32_t firstQuery,
|
|
|
|
uint32_t queryCount,
|
|
|
|
size_t dataSize,
|
|
|
|
void *pData,
|
|
|
|
VkDeviceSize stride,
|
|
|
|
VkQueryResultFlags flags)
|
|
|
|
{
|
2022-07-12 07:31:37 +01:00
|
|
|
VN_TRACE_FUNC();
|
2021-04-08 00:37:33 +01:00
|
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool);
|
|
|
|
const VkAllocationCallbacks *alloc = &pool->allocator;
|
|
|
|
|
|
|
|
const size_t result_width = flags & VK_QUERY_RESULT_64_BIT ? 8 : 4;
|
|
|
|
const size_t result_size = pool->result_array_size * result_width;
|
|
|
|
const bool result_always_written =
|
|
|
|
flags & (VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_PARTIAL_BIT);
|
|
|
|
|
|
|
|
VkQueryResultFlags packed_flags = flags;
|
|
|
|
size_t packed_stride = result_size;
|
|
|
|
if (!result_always_written)
|
|
|
|
packed_flags |= VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
|
|
|
|
if (packed_flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
|
|
|
|
packed_stride += result_width;
|
|
|
|
|
|
|
|
const size_t packed_size = packed_stride * queryCount;
|
|
|
|
void *packed_data;
|
|
|
|
if (result_always_written && packed_stride == stride) {
|
|
|
|
packed_data = pData;
|
|
|
|
} else {
|
|
|
|
packed_data = vk_alloc(alloc, packed_size, VN_DEFAULT_ALIGN,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
|
|
if (!packed_data)
|
|
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO the renderer should transparently vkCmdCopyQueryPoolResults to a
|
|
|
|
* coherent memory such that we can memcpy from the coherent memory to
|
|
|
|
* avoid this serialized round trip.
|
|
|
|
*/
|
|
|
|
VkResult result = vn_call_vkGetQueryPoolResults(
|
|
|
|
dev->instance, device, queryPool, firstQuery, queryCount, packed_size,
|
|
|
|
packed_data, packed_stride, packed_flags);
|
|
|
|
|
|
|
|
if (packed_data == pData)
|
|
|
|
return vn_result(dev->instance, result);
|
|
|
|
|
|
|
|
const size_t copy_size =
|
|
|
|
result_size +
|
|
|
|
(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT ? result_width : 0);
|
|
|
|
const void *src = packed_data;
|
|
|
|
void *dst = pData;
|
|
|
|
if (result == VK_SUCCESS) {
|
|
|
|
for (uint32_t i = 0; i < queryCount; i++) {
|
|
|
|
memcpy(dst, src, copy_size);
|
|
|
|
src += packed_stride;
|
|
|
|
dst += stride;
|
|
|
|
}
|
|
|
|
} else if (result == VK_NOT_READY) {
|
|
|
|
assert(!result_always_written &&
|
|
|
|
(packed_flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
|
|
|
|
if (flags & VK_QUERY_RESULT_64_BIT) {
|
|
|
|
for (uint32_t i = 0; i < queryCount; i++) {
|
|
|
|
const bool avail = *(const uint64_t *)(src + result_size);
|
|
|
|
if (avail)
|
|
|
|
memcpy(dst, src, copy_size);
|
|
|
|
else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
|
|
|
|
*(uint64_t *)(dst + result_size) = 0;
|
|
|
|
|
|
|
|
src += packed_stride;
|
|
|
|
dst += stride;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (uint32_t i = 0; i < queryCount; i++) {
|
|
|
|
const bool avail = *(const uint32_t *)(src + result_size);
|
|
|
|
if (avail)
|
|
|
|
memcpy(dst, src, copy_size);
|
|
|
|
else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
|
|
|
|
*(uint32_t *)(dst + result_size) = 0;
|
|
|
|
|
|
|
|
src += packed_stride;
|
|
|
|
dst += stride;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vk_free(alloc, packed_data);
|
|
|
|
return vn_result(dev->instance, result);
|
|
|
|
}
|