zink: query support (v2)
authorDave Airlie <airlied@redhat.com>
Tue, 2 Oct 2018 23:57:41 +0000 (00:57 +0100)
committerErik Faye-Lund <erik.faye-lund@collabora.com>
Mon, 28 Oct 2019 08:51:43 +0000 (08:51 +0000)
This at least passes piglit occlusion_query test for me here now.

Acked-by: Jordan Justen <jordan.l.justen@intel.com>
src/gallium/drivers/zink/meson.build
src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_context.h
src/gallium/drivers/zink/zink_query.c [new file with mode: 0644]
src/gallium/drivers/zink/zink_screen.c

index 75edc36ca6849479af09ecb642e659706231013c..1552696d8fe5e7f4b30efaf9bdd325ff1e20853a 100644 (file)
@@ -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',
index 5b3f2d5263d1e27e229b69e97f45366fccb3909f..2ce780ce9ff02e4956e2cd119a1499fb3e288f83 100644 (file)
@@ -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);
 
index d2d669e927d8404123c86db69cab5a26c6a65b42..69e2fdd797e14fbfabca28ea2314d292ea2f03d2 100644 (file)
@@ -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 (file)
index 0000000..65babe5
--- /dev/null
@@ -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;
+}
index b50f2f5d0307b38f72f0eae932be55de6f2ab4d3..88b2d5088d473c3a6dab12f0fb353c637190a70a 100644 (file)
@@ -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;