From 6d96578912cd509a8d91912feacaa8a0169b7d90 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 3 Oct 2018 00:57:41 +0100 Subject: [PATCH] zink: query support (v2) This at least passes piglit occlusion_query test for me here now. Acked-by: Jordan Justen --- src/gallium/drivers/zink/meson.build | 1 + src/gallium/drivers/zink/zink_context.c | 1 + src/gallium/drivers/zink/zink_context.h | 3 + src/gallium/drivers/zink/zink_query.c | 147 ++++++++++++++++++++++++ src/gallium/drivers/zink/zink_screen.c | 7 ++ 5 files changed, 159 insertions(+) create mode 100644 src/gallium/drivers/zink/zink_query.c diff --git a/src/gallium/drivers/zink/meson.build b/src/gallium/drivers/zink/meson.build index 75edc36ca68..1552696d8fe 100644 --- a/src/gallium/drivers/zink/meson.build +++ b/src/gallium/drivers/zink/meson.build @@ -28,6 +28,7 @@ files_libzink = files( 'zink_framebuffer.c', 'zink_pipeline.c', 'zink_program.c', + 'zink_query.c', 'zink_render_pass.c', 'zink_resource.c', 'zink_screen.c', diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 5b3f2d5263d..2ce780ce9ff 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -1143,6 +1143,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->base.flush_resource = zink_flush_resource; zink_context_surface_init(&ctx->base); zink_context_resource_init(&ctx->base); + zink_context_query_init(&ctx->base); slab_create_child(&ctx->transfer_pool, &screen->transfer_pool); diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index d2d669e927d..69e2fdd797e 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -104,4 +104,7 @@ zink_shader_stage(enum pipe_shader_type type); struct pipe_context * zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags); +void +zink_context_query_init(struct pipe_context *ctx); + #endif diff --git a/src/gallium/drivers/zink/zink_query.c b/src/gallium/drivers/zink/zink_query.c new file mode 100644 index 00000000000..65babe5d763 --- /dev/null +++ b/src/gallium/drivers/zink/zink_query.c @@ -0,0 +1,147 @@ + +#include "zink_context.h" +#include "zink_screen.h" + +#include "util/u_memory.h" +struct zink_query { + VkQueryPool queryPool; + VkQueryType vkqtype; + bool use_64bit; + bool precise; +}; + +static VkQueryType +convert_query_type(unsigned query_type, bool *use_64bit, bool *precise) +{ + *use_64bit = false; + *precise = false; + switch (query_type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + *precise = true; + *use_64bit = true; + case PIPE_QUERY_OCCLUSION_PREDICATE: + case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: + return VK_QUERY_TYPE_OCCLUSION; + case PIPE_QUERY_TIMESTAMP: + *use_64bit = true; + return VK_QUERY_TYPE_TIMESTAMP; + case PIPE_QUERY_PIPELINE_STATISTICS: + return VK_QUERY_TYPE_PIPELINE_STATISTICS; + default: + fprintf(stderr, "zink: unknown query type\n"); + return -1; + } +} + +static struct pipe_query * +zink_create_query(struct pipe_context *pctx, + unsigned query_type, unsigned index) +{ + struct zink_screen *screen = zink_screen(pctx->screen); + struct zink_query *query = CALLOC_STRUCT(zink_query); + VkQueryPoolCreateInfo pool_create = {}; + + if (!query) + return NULL; + + query->vkqtype = convert_query_type(query_type, &query->use_64bit, &query->precise); + if (query->vkqtype == -1) + return NULL; + + pool_create.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + pool_create.queryType = query->vkqtype; + pool_create.queryCount = 1; + + VkResult status = vkCreateQueryPool(screen->dev, &pool_create, NULL, &query->queryPool); + if (status != VK_SUCCESS) { + FREE(query); + return NULL; + } + return (struct pipe_query *)query; +} + +static void +zink_destroy_query(struct pipe_context *pctx, + struct pipe_query *q) +{ + struct zink_screen *screen = zink_screen(pctx->screen); + struct zink_query *query = CALLOC_STRUCT(zink_query); + + vkDestroyQueryPool(screen->dev, query->queryPool, NULL); +} + +static bool +zink_begin_query(struct pipe_context *pctx, + struct pipe_query *q) +{ + struct zink_context *ctx = zink_context(pctx); + struct zink_query *query = (struct zink_query *)q; + + struct zink_cmdbuf *cmdbuf = zink_start_cmdbuf(ctx); + if (!cmdbuf) + return false; + + if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP) + return true; + + VkQueryControlFlags flags = 0; + if (query->precise) + flags |= VK_QUERY_CONTROL_PRECISE_BIT; + + vkCmdBeginQuery(cmdbuf->cmdbuf, query->queryPool, 0, flags); + + return true; +} + +static bool +zink_end_query(struct pipe_context *pctx, + struct pipe_query *q) +{ + struct zink_context *ctx = zink_context(pctx); + struct zink_query *query = (struct zink_query *)q; + + struct zink_cmdbuf *cmdbuf = zink_start_cmdbuf(ctx); + if (!cmdbuf) + return false; + + if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP) + vkCmdWriteTimestamp(cmdbuf->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + query->queryPool, 0); + else + vkCmdEndQuery(cmdbuf->cmdbuf, query->queryPool, 0); + return true; +} + +static bool +zink_get_query_result(struct pipe_context *pctx, + struct pipe_query *q, + bool wait, + union pipe_query_result *result) +{ + struct zink_screen *screen = zink_screen(pctx->screen); + struct zink_query *query = (struct zink_query *)q; + VkQueryResultFlagBits flags = 0; + + pctx->flush(pctx, NULL, 0); + + if (wait) + flags |= VK_QUERY_RESULT_WAIT_BIT; + + if (query->use_64bit) + flags |= VK_QUERY_RESULT_64_BIT; + + VkResult status = vkGetQueryPoolResults(screen->dev, query->queryPool, + 0, 1, sizeof(*result), result, + 0, flags); + return status == VK_SUCCESS; +} + +void +zink_context_query_init(struct pipe_context *pctx) +{ + pctx->create_query = zink_create_query; + pctx->destroy_query = zink_destroy_query; + pctx->begin_query = zink_begin_query; + pctx->end_query = zink_end_query; + pctx->get_query_result = zink_get_query_result; +} diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index b50f2f5d030..88b2d5088d4 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -102,6 +102,10 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_MAX_RENDER_TARGETS: return screen->props.limits.maxColorAttachments; + case PIPE_CAP_OCCLUSION_QUERY: + case PIPE_CAP_QUERY_TIME_ELAPSED: + return 1; + case PIPE_CAP_TEXTURE_SWIZZLE: return 1; @@ -160,6 +164,9 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return screen->props.limits.minUniformBufferOffsetAlignment; + case PIPE_CAP_QUERY_TIMESTAMP: + return 1; + case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return screen->props.limits.minMemoryMapAlignment; -- 2.30.2