Commit 5cb539ac authored by Erik Faye-Lund 's avatar Erik Faye-Lund

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.
parent 7cbc4f63
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "zink_context.h" #include "zink_context.h"
#include "zink_fence.h" #include "zink_fence.h"
#include "zink_framebuffer.h" #include "zink_framebuffer.h"
#include "zink_query.h"
#include "zink_render_pass.h" #include "zink_render_pass.h"
#include "zink_resource.h" #include "zink_resource.h"
#include "zink_screen.h" #include "zink_screen.h"
...@@ -58,11 +59,17 @@ zink_start_batch(struct zink_context *ctx, struct zink_batch *batch) ...@@ -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; cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
if (vkBeginCommandBuffer(batch->cmdbuf, &cbbi) != VK_SUCCESS) if (vkBeginCommandBuffer(batch->cmdbuf, &cbbi) != VK_SUCCESS)
debug_printf("vkBeginCommandBuffer failed\n"); debug_printf("vkBeginCommandBuffer failed\n");
if (!ctx->queries_disabled)
zink_resume_queries(ctx, batch);
} }
void void
zink_end_batch(struct zink_context *ctx, struct zink_batch *batch) 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) { if (vkEndCommandBuffer(batch->cmdbuf) != VK_SUCCESS) {
debug_printf("vkEndCommandBuffer failed\n"); debug_printf("vkEndCommandBuffer failed\n");
return; return;
......
...@@ -31,11 +31,13 @@ ...@@ -31,11 +31,13 @@
#include "pipe/p_state.h" #include "pipe/p_state.h"
#include "util/slab.h" #include "util/slab.h"
#include "util/list.h"
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
struct blitter_context; struct blitter_context;
struct primconvert_context; struct primconvert_context;
struct list_head;
struct zink_blend_state; struct zink_blend_state;
struct zink_depth_stencil_alpha_state; struct zink_depth_stencil_alpha_state;
...@@ -106,6 +108,9 @@ struct zink_context { ...@@ -106,6 +108,9 @@ struct zink_context {
float blend_constants[4]; float blend_constants[4];
struct pipe_stencil_ref stencil_ref; struct pipe_stencil_ref stencil_ref;
struct list_head active_queries;
bool queries_disabled;
}; };
static inline struct zink_context * static inline struct zink_context *
......
#include "zink_query.h"
#include "zink_context.h" #include "zink_context.h"
#include "zink_screen.h" #include "zink_screen.h"
#include "util/u_memory.h"
#include "util/u_dump.h" #include "util/u_dump.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
struct zink_query { struct zink_query {
enum pipe_query_type type; enum pipe_query_type type;
VkQueryPool queryPool;
VkQueryPool query_pool;
unsigned curr_query, num_queries;
VkQueryType vkqtype; VkQueryType vkqtype;
bool use_64bit; bool use_64bit;
bool precise; bool precise;
struct list_head active_list;
}; };
static VkQueryType static VkQueryType
...@@ -53,11 +60,14 @@ zink_create_query(struct pipe_context *pctx, ...@@ -53,11 +60,14 @@ zink_create_query(struct pipe_context *pctx,
if (query->vkqtype == -1) if (query->vkqtype == -1)
return NULL; 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.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
pool_create.queryType = query->vkqtype; 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) { if (status != VK_SUCCESS) {
FREE(query); FREE(query);
return NULL; return NULL;
...@@ -72,7 +82,18 @@ zink_destroy_query(struct pipe_context *pctx, ...@@ -72,7 +82,18 @@ zink_destroy_query(struct pipe_context *pctx,
struct zink_screen *screen = zink_screen(pctx->screen); struct zink_screen *screen = zink_screen(pctx->screen);
struct zink_query *query = CALLOC_STRUCT(zink_query); 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 boolean static boolean
...@@ -82,19 +103,36 @@ zink_begin_query(struct pipe_context *pctx, ...@@ -82,19 +103,36 @@ zink_begin_query(struct pipe_context *pctx,
struct zink_context *ctx = zink_context(pctx); struct zink_context *ctx = zink_context(pctx);
struct zink_query *query = (struct zink_query *)q; 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; return true;
VkQueryControlFlags flags = 0; /* TODO: resetting on begin isn't ideal, as it forces render-pass exit...
if (query->precise) * should instead reset on creation (if possible?)... Or perhaps maintain
flags |= VK_QUERY_CONTROL_PRECISE_BIT; * 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); begin_query(ctx, query);
vkCmdBeginQuery(batch->cmdbuf, query->queryPool, 0, flags); list_addtail(&query->active_list, &ctx->active_queries);
return true; 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 static bool
zink_end_query(struct pipe_context *pctx, zink_end_query(struct pipe_context *pctx,
struct pipe_query *q) struct pipe_query *q)
...@@ -102,12 +140,16 @@ zink_end_query(struct pipe_context *pctx, ...@@ -102,12 +140,16 @@ zink_end_query(struct pipe_context *pctx,
struct zink_context *ctx = zink_context(pctx); struct zink_context *ctx = zink_context(pctx);
struct zink_query *query = (struct zink_query *)q; struct zink_query *query = (struct zink_query *)q;
if (query->type == PIPE_QUERY_TIMESTAMP) {
assert(query->curr_query == 0);
struct zink_batch *batch = zink_curr_batch(ctx); struct zink_batch *batch = zink_curr_batch(ctx);
if (query->vkqtype == VK_QUERY_TYPE_TIMESTAMP)
vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
query->queryPool, 0); query->query_pool, 0);
else } else {
vkCmdEndQuery(batch->cmdbuf, query->queryPool, 0); end_query(ctx, query);
list_delinit(&query->active_list);
}
return true; return true;
} }
...@@ -121,43 +163,96 @@ zink_get_query_result(struct pipe_context *pctx, ...@@ -121,43 +163,96 @@ zink_get_query_result(struct pipe_context *pctx,
struct zink_query *query = (struct zink_query *)q; struct zink_query *query = (struct zink_query *)q;
VkQueryResultFlagBits flags = 0; VkQueryResultFlagBits flags = 0;
pctx->flush(pctx, NULL, 0); if (wait) {
struct pipe_fence_handle *fence = NULL;
if (wait) 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; flags |= VK_QUERY_RESULT_WAIT_BIT;
} else
pctx->flush(pctx, NULL, 0);
if (query->use_64bit) if (query->use_64bit)
flags |= VK_QUERY_RESULT_64_BIT; flags |= VK_QUERY_RESULT_64_BIT;
if (vkGetQueryPoolResults(screen->dev, query->queryPool, // TODO: handle curr_query > 100
0, 1, sizeof(*result), result, // union pipe_query_result results[100];
0, flags) != VK_SUCCESS) 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; return false;
util_query_clear_result(result, query->type);
for (int i = 0; i < query->curr_query; ++i) {
switch (query->type) { switch (query->type) {
case PIPE_QUERY_OCCLUSION_PREDICATE: case PIPE_QUERY_OCCLUSION_PREDICATE:
case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
case PIPE_QUERY_SO_OVERFLOW_PREDICATE: case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
case PIPE_QUERY_GPU_FINISHED: case PIPE_QUERY_GPU_FINISHED:
/* fixup bool-queries */ result->b |= results[i] != 0;
result->b = result->u32 != 0; break;
case PIPE_QUERY_OCCLUSION_COUNTER:
result->u64 += results[i];
break; break;
default: default:
; /* nothing */ debug_printf("unhangled query type: %s\n",
util_str_query_type(query->type, true));
unreachable("unexpected query type");
}
} }
return TRUE; 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 static void
zink_set_active_query_state(struct pipe_context *pctx, boolean enable) zink_set_active_query_state(struct pipe_context *pctx, boolean 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 void
zink_context_query_init(struct pipe_context *pctx) 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->create_query = zink_create_query;
pctx->destroy_query = zink_destroy_query; pctx->destroy_query = zink_destroy_query;
pctx->begin_query = zink_begin_query; pctx->begin_query = zink_begin_query;
......
/*
* 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment