summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Faye-Lund <[email protected]>2019-07-16 13:29:06 +0200
committerErik Faye-Lund <[email protected]>2019-10-28 08:51:47 +0000
commit2683619955b973046b266c45afa0c10de8f0ef57 (patch)
tree9cda2f1b6b5a7f9890411ce06a7e9e66d07b7d5e
parent67cde39c8c6734d7dd05b53dfcf4a6f3133ca577 (diff)
HACK: zink: suspend / resume queries on batch-boundaries
HACK because we assert that we don't overrun the pool. We need a fallback here instead. Acked-by: Jordan Justen <[email protected]>
-rw-r--r--src/gallium/drivers/zink/zink_batch.c7
-rw-r--r--src/gallium/drivers/zink/zink_context.h5
-rw-r--r--src/gallium/drivers/zink/zink_query.c161
-rw-r--r--src/gallium/drivers/zink/zink_query.h36
4 files changed, 176 insertions, 33 deletions
diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c
index 2a1e7f8e65b..74700acb340 100644
--- a/src/gallium/drivers/zink/zink_batch.c
+++ b/src/gallium/drivers/zink/zink_batch.c
@@ -3,6 +3,7 @@
#include "zink_context.h"
#include "zink_fence.h"
#include "zink_framebuffer.h"
+#include "zink_query.h"
#include "zink_render_pass.h"
#include "zink_resource.h"
#include "zink_screen.h"
@@ -58,11 +59,17 @@ zink_start_batch(struct zink_context *ctx, struct zink_batch *batch)
cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
if (vkBeginCommandBuffer(batch->cmdbuf, &cbbi) != VK_SUCCESS)
debug_printf("vkBeginCommandBuffer failed\n");
+
+ if (!ctx->queries_disabled)
+ zink_resume_queries(ctx, batch);
}
void
zink_end_batch(struct zink_context *ctx, struct zink_batch *batch)
{
+ if (!ctx->queries_disabled)
+ zink_suspend_queries(ctx, batch);
+
if (vkEndCommandBuffer(batch->cmdbuf) != VK_SUCCESS) {
debug_printf("vkEndCommandBuffer failed\n");
return;
diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h
index 445579c59b9..147f35f6d18 100644
--- a/src/gallium/drivers/zink/zink_context.h
+++ b/src/gallium/drivers/zink/zink_context.h
@@ -31,11 +31,13 @@
#include "pipe/p_state.h"
#include "util/slab.h"
+#include "util/list.h"
#include <vulkan/vulkan.h>
struct blitter_context;
struct primconvert_context;
+struct list_head;
struct zink_blend_state;
struct zink_depth_stencil_alpha_state;
@@ -106,6 +108,9 @@ struct zink_context {
float blend_constants[4];
struct pipe_stencil_ref stencil_ref;
+
+ struct list_head active_queries;
+ bool queries_disabled;
};
static inline struct zink_context *
diff --git a/src/gallium/drivers/zink/zink_query.c b/src/gallium/drivers/zink/zink_query.c
index d5fc8005915..615bd2b9368 100644
--- a/src/gallium/drivers/zink/zink_query.c
+++ b/src/gallium/drivers/zink/zink_query.c
@@ -1,16 +1,23 @@
+#include "zink_query.h"
#include "zink_context.h"
#include "zink_screen.h"
-#include "util/u_memory.h"
#include "util/u_dump.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
struct zink_query {
enum pipe_query_type type;
- VkQueryPool queryPool;
+
+ VkQueryPool query_pool;
+ unsigned curr_query, num_queries;
+
VkQueryType vkqtype;
bool use_64bit;
bool precise;
+
+ struct list_head active_list;
};
static VkQueryType
@@ -53,11 +60,14 @@ zink_create_query(struct pipe_context *pctx,
if (query->vkqtype == -1)
return NULL;
+ query->num_queries = query_type == PIPE_QUERY_TIMESTAMP ? 1 : 100;
+ query->curr_query = 0;
+
pool_create.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
pool_create.queryType = query->vkqtype;
- pool_create.queryCount = 1;
+ pool_create.queryCount = query->num_queries;
- VkResult status = vkCreateQueryPool(screen->dev, &pool_create, NULL, &query->queryPool);
+ VkResult status = vkCreateQueryPool(screen->dev, &pool_create, NULL, &query->query_pool);
if (status != VK_SUCCESS) {
FREE(query);
return NULL;
@@ -72,7 +82,18 @@ zink_destroy_query(struct pipe_context *pctx,
struct zink_screen *screen = zink_screen(pctx->screen);
struct zink_query *query = CALLOC_STRUCT(zink_query);
- vkDestroyQueryPool(screen->dev, query->queryPool, NULL);
+ vkDestroyQueryPool(screen->dev, query->query_pool, NULL);
+}
+
+static void
+begin_query(struct zink_context *ctx, struct zink_query *q)
+{
+ VkQueryControlFlags flags = 0;
+ if (q->precise)
+ flags |= VK_QUERY_CONTROL_PRECISE_BIT;
+
+ struct zink_batch *batch = zink_curr_batch(ctx);
+ vkCmdBeginQuery(batch->cmdbuf, q->query_pool, q->curr_query, flags);
}
static bool
@@ -82,19 +103,36 @@ zink_begin_query(struct pipe_context *pctx,
struct zink_context *ctx = zink_context(pctx);
struct zink_query *query = (struct zink_query *)q;
- if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP)
+ /* ignore begin_query for timestamps */
+ if (query->type == PIPE_QUERY_TIMESTAMP)
return true;
- VkQueryControlFlags flags = 0;
- if (query->precise)
- flags |= VK_QUERY_CONTROL_PRECISE_BIT;
+ /* TODO: resetting on begin isn't ideal, as it forces render-pass exit...
+ * should instead reset on creation (if possible?)... Or perhaps maintain
+ * the pool in the batch instead?
+ */
+ struct zink_batch *batch = zink_batch_no_rp(zink_context(pctx));
+ vkCmdResetQueryPool(batch->cmdbuf, query->query_pool, 0, query->curr_query);
+ query->curr_query = 0;
- struct zink_batch *batch = zink_curr_batch(ctx);
- vkCmdBeginQuery(batch->cmdbuf, query->queryPool, 0, flags);
+ begin_query(ctx, query);
+ list_addtail(&query->active_list, &ctx->active_queries);
return true;
}
+static void
+end_query(struct zink_context *ctx, struct zink_query *q)
+{
+ struct zink_batch *batch = zink_curr_batch(ctx);
+ assert(q->type != PIPE_QUERY_TIMESTAMP);
+ vkCmdEndQuery(batch->cmdbuf, q->query_pool, q->curr_query);
+ if (++q->curr_query == q->num_queries) {
+ assert(0);
+ /* need to reset pool! */
+ }
+}
+
static bool
zink_end_query(struct pipe_context *pctx,
struct pipe_query *q)
@@ -102,12 +140,16 @@ zink_end_query(struct pipe_context *pctx,
struct zink_context *ctx = zink_context(pctx);
struct zink_query *query = (struct zink_query *)q;
- struct zink_batch *batch = zink_curr_batch(ctx);
- if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP)
+ if (query->type == PIPE_QUERY_TIMESTAMP) {
+ assert(query->curr_query == 0);
+ struct zink_batch *batch = zink_curr_batch(ctx);
vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
- query->queryPool, 0);
- else
- vkCmdEndQuery(batch->cmdbuf, query->queryPool, 0);
+ query->query_pool, 0);
+ } else {
+ end_query(ctx, query);
+ list_delinit(&query->active_list);
+ }
+
return true;
}
@@ -121,43 +163,96 @@ zink_get_query_result(struct pipe_context *pctx,
struct zink_query *query = (struct zink_query *)q;
VkQueryResultFlagBits flags = 0;
- pctx->flush(pctx, NULL, 0);
-
- if (wait)
+ if (wait) {
+ struct pipe_fence_handle *fence = NULL;
+ pctx->flush(pctx, &fence, PIPE_FLUSH_HINT_FINISH);
+ if (fence) {
+ pctx->screen->fence_finish(pctx->screen, NULL, fence,
+ PIPE_TIMEOUT_INFINITE);
+ pctx->screen->fence_reference(pctx->screen, &fence, NULL);
+ }
flags |= VK_QUERY_RESULT_WAIT_BIT;
+ } else
+ pctx->flush(pctx, NULL, 0);
if (query->use_64bit)
flags |= VK_QUERY_RESULT_64_BIT;
- if (vkGetQueryPoolResults(screen->dev, query->queryPool,
- 0, 1, sizeof(*result), result,
- 0, flags) != VK_SUCCESS)
+ // TODO: handle curr_query > 100
+ // union pipe_query_result results[100];
+ uint64_t results[100];
+ memset(results, 0, sizeof(results));
+ assert(query->curr_query <= ARRAY_SIZE(results));
+ if (vkGetQueryPoolResults(screen->dev, query->query_pool,
+ 0, query->curr_query,
+ sizeof(results),
+ results,
+ sizeof(uint64_t),
+ flags) != VK_SUCCESS)
return false;
- switch (query->type) {
- case PIPE_QUERY_OCCLUSION_PREDICATE:
- case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
- case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
- case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
- case PIPE_QUERY_GPU_FINISHED:
- /* fixup bool-queries */
- result->b = result->u32 != 0;
- break;
- default:
- ; /* nothing */
+ util_query_clear_result(result, query->type);
+ for (int i = 0; i < query->curr_query; ++i) {
+ switch (query->type) {
+ case PIPE_QUERY_OCCLUSION_PREDICATE:
+ case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
+ case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
+ case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
+ case PIPE_QUERY_GPU_FINISHED:
+ result->b |= results[i] != 0;
+ break;
+
+ case PIPE_QUERY_OCCLUSION_COUNTER:
+ result->u64 += results[i];
+ break;
+
+ default:
+ debug_printf("unhangled query type: %s\n",
+ util_str_query_type(query->type, true));
+ unreachable("unexpected query type");
+ }
}
return TRUE;
}
+void
+zink_suspend_queries(struct zink_context *ctx, struct zink_batch *batch)
+{
+ struct zink_query *query;
+ LIST_FOR_EACH_ENTRY(query, &ctx->active_queries, active_list) {
+ end_query(ctx, query);
+ }
+}
+
+void
+zink_resume_queries(struct zink_context *ctx, struct zink_batch *batch)
+{
+ struct zink_query *query;
+ LIST_FOR_EACH_ENTRY(query, &ctx->active_queries, active_list) {
+ begin_query(ctx, query);
+ }
+}
+
static void
zink_set_active_query_state(struct pipe_context *pctx, bool enable)
{
+ struct zink_context *ctx = zink_context(pctx);
+ ctx->queries_disabled = !enable;
+
+ struct zink_batch *batch = zink_curr_batch(ctx);
+ if (ctx->queries_disabled)
+ zink_suspend_queries(ctx, batch);
+ else
+ zink_resume_queries(ctx, batch);
}
void
zink_context_query_init(struct pipe_context *pctx)
{
+ struct zink_context *ctx = zink_context(pctx);
+ list_inithead(&ctx->active_queries);
+
pctx->create_query = zink_create_query;
pctx->destroy_query = zink_destroy_query;
pctx->begin_query = zink_begin_query;
diff --git a/src/gallium/drivers/zink/zink_query.h b/src/gallium/drivers/zink/zink_query.h
new file mode 100644
index 00000000000..4b26b443454
--- /dev/null
+++ b/src/gallium/drivers/zink/zink_query.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Collabora Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ZINK_QUERY_H
+#define ZINK_QUERY_H
+
+struct zink_batch;
+struct zink_context;
+
+void
+zink_suspend_queries(struct zink_context *ctx, struct zink_batch *batch);
+
+void
+zink_resume_queries(struct zink_context *ctx, struct zink_batch *batch);
+
+#endif