From 1a3e2a7fa8bf184b5f9214d4c404e4c2c754aa58 Mon Sep 17 00:00:00 2001 From: Brian Ho Date: Fri, 24 Jan 2020 16:39:47 -0500 Subject: [PATCH] turnip: Fix vkGetQueryPoolResults with available flag Previously, calling vkGetQueryPoolResults with the VK_QUERY_RESULT_WITH_AVAILABILITY_BIT flag set the query result field in *pData to 0 if unavailable and the query result if available. This was a misunderstanding of the Vulkan spec, and this commit corrects the behavior to eriting a separate available result in addition to the query result. Part-of: --- src/freedreno/vulkan/tu_query.c | 52 +++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/freedreno/vulkan/tu_query.c b/src/freedreno/vulkan/tu_query.c index bb6cc2247ff..c37647154f7 100644 --- a/src/freedreno/vulkan/tu_query.c +++ b/src/freedreno/vulkan/tu_query.c @@ -168,6 +168,20 @@ wait_for_available(struct tu_device *device, struct tu_query_pool *pool, return vk_error(device->instance, VK_TIMEOUT); } +/* Writes a query value to a buffer from the CPU. */ +static void +write_query_value_cpu(char* base, + uint32_t offset, + uint64_t value, + VkQueryResultFlags flags) +{ + if (flags & VK_QUERY_RESULT_64_BIT) { + *(uint64_t*)(base + (offset * sizeof(uint64_t))) = value; + } else { + *(uint32_t*)(base + (offset * sizeof(uint32_t))) = value; + } +} + static VkResult get_occlusion_query_pool_results(struct tu_device *device, struct tu_query_pool *pool, @@ -180,7 +194,7 @@ get_occlusion_query_pool_results(struct tu_device *device, { assert(dataSize >= stride * queryCount); - char *query_result = pData; + char *result_base = pData; VkResult result = VK_SUCCESS; for (uint32_t i = 0; i < queryCount; i++) { uint32_t query = firstQuery + i; @@ -203,23 +217,14 @@ get_occlusion_query_pool_results(struct tu_device *device, */ result = VK_NOT_READY; if (!(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)) { - query_result += stride; + result_base += stride; continue; } } - uint64_t value; - if (available) { - value = slot->result.value; - } else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) { - /* From the Vulkan 1.1.130 spec: - * - * If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, the final - * integer value written for each query is non-zero if the query’s - * status was available or zero if the status was unavailable. - */ - value = 0; - } else if (flags & VK_QUERY_RESULT_PARTIAL_BIT) { + if (available) + write_query_value_cpu(result_base, 0, slot->result.value, flags); + else if (flags & VK_QUERY_RESULT_PARTIAL_BIT) /* From the Vulkan 1.1.130 spec: * * If VK_QUERY_RESULT_PARTIAL_BIT is set, VK_QUERY_RESULT_WAIT_BIT @@ -229,15 +234,18 @@ get_occlusion_query_pool_results(struct tu_device *device, * * Just return 0 here for simplicity since it's a valid result. */ - value = 0; - } + write_query_value_cpu(result_base, 0, 0, flags); - if (flags & VK_QUERY_RESULT_64_BIT) { - *(uint64_t*)query_result = value; - } else { - *(uint32_t*)query_result = value; - } - query_result += stride; + if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) + /* From the Vulkan 1.1.130 spec: + * + * If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, the final + * integer value written for each query is non-zero if the query’s + * status was available or zero if the status was unavailable. + */ + write_query_value_cpu(result_base, 1, available, flags); + + result_base += stride; } return result; } -- 2.30.2