Browse Source

turnip: Initial support for occlusion vkGetQueryPoolResults

turnip-occlusion-query
Brian Ho 6 years ago
parent
commit
b8cc3a36da
1 changed files with 75 additions and 0 deletions
  1. 75
    0
      src/freedreno/vulkan/tu_query.c

+ 75
- 0
src/freedreno/vulkan/tu_query.c View File

@@ -36,9 +36,12 @@
#include "registers/a6xx.xml.h"

#include "nir/nir_builder.h"
#include "util/os_time.h"

#include "tu_cs.h"

#define NSEC_PER_SEC 1000000000ull

struct PACKED occlusion_query_slot {
uint64_t available; /* 0 when unavailable, 1 when available */
uint64_t begin;
@@ -53,6 +56,13 @@ static uint64_t query_iova(struct tu_query_pool *pool, uint32_t query,
return pool->bo->iova + pool->stride * query + index * sizeof(uint64_t);
}

/*
* Returns a pointer to a given slot in a query pool.
*/
static void* slot_address(struct tu_query_pool *pool, uint32_t query) {
return (char*)pool->bo->map + query * pool->stride;
}

VkResult
tu_CreateQueryPool(VkDevice _device,
const VkQueryPoolCreateInfo *pCreateInfo,
@@ -123,6 +133,56 @@ tu_DestroyQueryPool(VkDevice _device,
vk_free2(&device->alloc, pAllocator, pool);
}

static bool
query_is_available(void *slot) {
return *(uint64_t*)slot;
}

/* Poll the availability status of a query up until a timeout.
*/
static VkResult
wait_for_available(struct tu_device *device, void *slot) {
uint64_t abs_timeout = os_time_get_absolute_timeout(5 * NSEC_PER_SEC);
while(os_time_get_nano() < abs_timeout) {
if (query_is_available(slot))
return VK_SUCCESS;
}
return vk_error(device->instance, VK_TIMEOUT);
}

static VkResult
get_occlusion_query_pool_results(struct tu_device *device,
struct tu_query_pool *pool,
uint32_t firstQuery,
uint32_t queryCount,
size_t dataSize,
void *pData,
VkDeviceSize stride,
VkQueryResultFlags flags) {
// TODO: Support other flags.
assert(flags & VK_QUERY_RESULT_WAIT_BIT);
assert(!(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
assert(!(flags & VK_QUERY_RESULT_PARTIAL_BIT));
assert(dataSize >= stride * queryCount);

char *query_result = pData;
for (uint32_t i = 0; i < queryCount; i++) {
struct occlusion_query_slot *slot = slot_address(pool, firstQuery + i);
if (flags & VK_QUERY_RESULT_WAIT_BIT) {
VkResult result = wait_for_available(device, slot);
if (result != VK_SUCCESS)
return result;
}
if (flags & VK_QUERY_RESULT_64_BIT) {
*(uint64_t*)query_result = slot->end - slot->begin;
} else {
*(uint32_t*)query_result = slot->end - slot->begin;
}
query_result += stride;
}
return VK_SUCCESS;
}

VkResult
tu_GetQueryPoolResults(VkDevice _device,
VkQueryPool queryPool,
@@ -133,6 +193,21 @@ tu_GetQueryPoolResults(VkDevice _device,
VkDeviceSize stride,
VkQueryResultFlags flags)
{
TU_FROM_HANDLE(tu_device, device, _device);
TU_FROM_HANDLE(tu_query_pool, pool, queryPool);
assert(firstQuery + queryCount <= pool->size);

switch (pool->type) {
case VK_QUERY_TYPE_OCCLUSION: {
return get_occlusion_query_pool_results(device, pool, firstQuery,
queryCount, dataSize, pData, stride, flags);
}
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
case VK_QUERY_TYPE_TIMESTAMP:
unreachable("Unimplemented query type");
default:
assert(!"Invalid query type");
}
return VK_SUCCESS;
}


Loading…
Cancel
Save