mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 06:48:06 +02:00
zink: add a get_query_result_resource hook
this is messy due to how we have to accumulate all the query results in some cases future patches will break things up into utility functions for reuse Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8944>
This commit is contained in:
parent
ffc66d4d8f
commit
49dd9d2026
1 changed files with 104 additions and 0 deletions
|
|
@ -538,6 +538,109 @@ zink_render_condition(struct pipe_context *pctx,
|
|||
pipe_resource_reference(&pres, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
zink_get_query_result_resource(struct pipe_context *pctx,
|
||||
struct pipe_query *pquery,
|
||||
bool wait,
|
||||
enum pipe_query_value_type result_type,
|
||||
int index,
|
||||
struct pipe_resource *pres,
|
||||
unsigned offset)
|
||||
{
|
||||
struct zink_context *ctx = zink_context(pctx);
|
||||
struct zink_screen *screen = zink_screen(pctx->screen);
|
||||
struct zink_query *query = (struct zink_query*)pquery;
|
||||
struct zink_resource *res = zink_resource(pres);
|
||||
unsigned result_size = result_type <= PIPE_QUERY_TYPE_U32 ? sizeof(uint32_t) : sizeof(uint64_t);
|
||||
VkQueryResultFlagBits size_flags = result_type <= PIPE_QUERY_TYPE_U32 ? 0 : VK_QUERY_RESULT_64_BIT;
|
||||
unsigned num_queries = query->curr_query - query->last_start;
|
||||
unsigned query_id = query->last_start;
|
||||
|
||||
if (index == -1) {
|
||||
uint64_t u64[2] = {0};
|
||||
/* TODO: this is awful. when we hook up valid regions for resources, we can at least check
|
||||
* whether the preceding area has valid data and clobber it with a direct copy here for a
|
||||
* big perf win
|
||||
*
|
||||
* VK_QUERY_RESULT_WITH_AVAILABILITY_BIT always writes result data at the specified offset,
|
||||
* so we have to do a manual read
|
||||
*/
|
||||
if (vkGetQueryPoolResults(screen->dev, query->query_pool, query_id, 1, 2 * result_size, u64,
|
||||
0, size_flags | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | VK_QUERY_RESULT_PARTIAL_BIT) != VK_SUCCESS) {
|
||||
debug_printf("zink: getting query result failed\n");
|
||||
return;
|
||||
}
|
||||
struct pipe_transfer *transfer = NULL;
|
||||
void *map = pipe_buffer_map_range(pctx, pres, offset, result_size, PIPE_MAP_WRITE, &transfer);
|
||||
if (!transfer) {
|
||||
debug_printf("zink: mapping result buffer failed\n");
|
||||
return;
|
||||
}
|
||||
if (result_type <= PIPE_QUERY_TYPE_U32) {
|
||||
uint32_t *u32_map = map;
|
||||
uint32_t *u32_u64 = (void*)u64;
|
||||
u32_map[0] = u32_u64[1];
|
||||
} else {
|
||||
uint64_t *u64_map = map;
|
||||
u64_map[0] = u64[1];
|
||||
}
|
||||
pipe_buffer_unmap(pctx, transfer);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned fences = p_atomic_read(&query->fences);
|
||||
if (!is_time_query(query) && (!fences || wait)) {
|
||||
/* result happens to be ready or we're waiting */
|
||||
if (num_queries == 1 && query->type != PIPE_QUERY_PRIMITIVES_GENERATED &&
|
||||
query->type != PIPE_QUERY_PRIMITIVES_EMITTED &&
|
||||
/* FIXME: I don't know why, but occlusion is broken here */
|
||||
query->type != PIPE_QUERY_OCCLUSION_PREDICATE &&
|
||||
query->type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
|
||||
struct zink_batch *batch = zink_batch_no_rp(ctx);
|
||||
/* if it's a single query that doesn't need special handling, we can copy it and be done */
|
||||
zink_batch_reference_resource_rw(batch, res, true);
|
||||
zink_resource_buffer_barrier(batch->cmdbuf, res, VK_ACCESS_TRANSFER_WRITE_BIT, 0);
|
||||
vkCmdCopyQueryPoolResults(batch->cmdbuf, query->query_pool, query_id, 1, res->buffer,
|
||||
offset, 0, size_flags);
|
||||
/* this is required for compute batch sync and will be removed later */
|
||||
if (batch->batch_id != ZINK_COMPUTE_BATCH_ID)
|
||||
pctx->flush(pctx, NULL, PIPE_FLUSH_HINT_FINISH);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (zink_curr_batch(ctx)->batch_id == query->batch_id)
|
||||
pctx->flush(pctx, NULL, PIPE_FLUSH_HINT_FINISH);
|
||||
/* unfortunately, there's no way to accumulate results from multiple queries on the gpu without either
|
||||
* clobbering all but the last result or writing the results sequentially, so we have to manually write the result
|
||||
*/
|
||||
union pipe_query_result result;
|
||||
bool success = get_query_result(&ctx->base, pquery, wait, &result);
|
||||
if (!success) {
|
||||
debug_printf("zink: getting query result failed");
|
||||
return;
|
||||
}
|
||||
|
||||
struct pipe_transfer *transfer = NULL;
|
||||
void *map = pipe_buffer_map_range(pctx, pres, offset, result_size, PIPE_MAP_WRITE, &transfer);
|
||||
if (!transfer) {
|
||||
debug_printf("zink: mapping result buffer failed");
|
||||
return;
|
||||
}
|
||||
if (result_type <= PIPE_QUERY_TYPE_U32) {
|
||||
uint32_t *u32 = map;
|
||||
uint32_t limit;
|
||||
if (result_type == PIPE_QUERY_TYPE_I32)
|
||||
limit = INT_MAX;
|
||||
else
|
||||
limit = UINT_MAX;
|
||||
u32[0] = MIN2(limit, result.u64);
|
||||
} else {
|
||||
uint64_t *u64 = map;
|
||||
u64[0] = result.u64;
|
||||
}
|
||||
pipe_buffer_unmap(pctx, transfer);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
zink_get_timestamp(struct pipe_context *pctx)
|
||||
{
|
||||
|
|
@ -564,6 +667,7 @@ zink_context_query_init(struct pipe_context *pctx)
|
|||
pctx->begin_query = zink_begin_query;
|
||||
pctx->end_query = zink_end_query;
|
||||
pctx->get_query_result = zink_get_query_result;
|
||||
pctx->get_query_result_resource = zink_get_query_result_resource;
|
||||
pctx->set_active_query_state = zink_set_active_query_state;
|
||||
pctx->render_condition = zink_render_condition;
|
||||
pctx->get_timestamp = zink_get_timestamp;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue