summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/zink/zink_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/zink/zink_query.c')
-rw-r--r--src/gallium/drivers/zink/zink_query.c161
1 files changed, 128 insertions, 33 deletions
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;