From 7a40b734ee2ba7da7975ac858022b6f175ddcb5a Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 10 Jul 2020 14:44:58 -0400 Subject: [PATCH] zink: handle timestamp queries a lot of this is just rejiggering code to allow timestamp queries to take the same codepaths as "normal" queries instead of even more explicitly special casing everything key point here is that we need to convert vulkan-level timestamp "ticks" to nanoseconds like the gallium api expects Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_query.c | 67 +++++++++++++++++++-------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/gallium/drivers/zink/zink_query.c b/src/gallium/drivers/zink/zink_query.c index 2a0e5520d47..7c771c06766 100644 --- a/src/gallium/drivers/zink/zink_query.c +++ b/src/gallium/drivers/zink/zink_query.c @@ -35,6 +35,21 @@ struct zink_query { union pipe_query_result accumulated_result; }; +static void +timestamp_to_nanoseconds(struct zink_screen *screen, uint64_t *timestamp) +{ + /* The number of valid bits in a timestamp value is determined by + * the VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is written. + * - 17.5. Timestamp Queries + */ + *timestamp &= ((1ull << screen->timestamp_valid_bits) - 1); + /* The number of nanoseconds it takes for a timestamp value to be incremented by 1 + * can be obtained from VkPhysicalDeviceLimits::timestampPeriod + * - 17.5. Timestamp Queries + */ + *timestamp *= screen->info.props.limits.timestampPeriod; +} + static VkQueryType convert_query_type(unsigned query_type, bool *use_64bit, bool *precise) { @@ -81,7 +96,7 @@ zink_create_query(struct pipe_context *pctx, if (query->vkqtype == -1) return NULL; - query->num_queries = query_type == PIPE_QUERY_TIMESTAMP ? 1 : NUM_QUERIES; + query->num_queries = NUM_QUERIES; query->curr_query = 0; pool_create.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; @@ -97,6 +112,8 @@ zink_create_query(struct pipe_context *pctx, } struct zink_batch *batch = zink_batch_no_rp(zink_context(pctx)); vkCmdResetQueryPool(batch->cmdbuf, query->query_pool, 0, query->num_queries); + if (query->type == PIPE_QUERY_TIMESTAMP) + query->active = true; return (struct pipe_query *)query; } @@ -156,12 +173,14 @@ get_query_result(struct pipe_context *pctx, flags |= VK_QUERY_RESULT_64_BIT; if (result != &query->accumulated_result) { - memcpy(result, &query->accumulated_result, sizeof(query->accumulated_result)); - util_query_clear_result(&query->accumulated_result, query->type); - } else { - assert(query->vkqtype != VK_QUERY_TYPE_TIMESTAMP); + if (query->type == PIPE_QUERY_TIMESTAMP) + util_query_clear_result(result, query->type); + else { + memcpy(result, &query->accumulated_result, sizeof(query->accumulated_result)); + util_query_clear_result(&query->accumulated_result, query->type); + } + } else flags |= VK_QUERY_RESULT_PARTIAL_BIT; - } // union pipe_query_result results[NUM_QUERIES * 2]; /* xfb queries return 2 results */ @@ -193,6 +212,7 @@ get_query_result(struct pipe_context *pctx, return false; } + uint64_t last_val = 0; for (int i = 0; i < num_results; ++i) { switch (query->type) { case PIPE_QUERY_OCCLUSION_PREDICATE: @@ -203,6 +223,13 @@ get_query_result(struct pipe_context *pctx, result->b |= results[i] != 0; break; + case PIPE_QUERY_TIMESTAMP: + /* the application can sum the differences between all N queries to determine the total execution time. + * - 17.5. Timestamp Queries + */ + result->u64 += results[i] - last_val; + last_val = results[i]; + break; case PIPE_QUERY_OCCLUSION_COUNTER: result->u64 += results[i]; break; @@ -227,6 +254,9 @@ get_query_result(struct pipe_context *pctx, } query->last_checked_query = query->curr_query; + if (query->type == PIPE_QUERY_TIMESTAMP) + timestamp_to_nanoseconds(screen, &result->u64); + return TRUE; } @@ -239,7 +269,8 @@ reset_pool(struct zink_context *ctx, struct zink_batch *batch, struct zink_query */ batch = zink_batch_no_rp(ctx); - get_query_result(&ctx->base, (struct pipe_query*)q, false, &q->accumulated_result); + if (q->type != PIPE_QUERY_TIMESTAMP) + get_query_result(&ctx->base, (struct pipe_query*)q, false, &q->accumulated_result); vkCmdResetQueryPool(batch->cmdbuf, q->query_pool, 0, q->num_queries); q->last_checked_query = q->curr_query = 0; q->needs_reset = false; @@ -253,6 +284,10 @@ begin_query(struct zink_context *ctx, struct zink_batch *batch, struct zink_quer if (q->needs_reset) reset_pool(ctx, batch, q); assert(q->curr_query < q->num_queries); + q->active = true; + /* ignore the rest of begin_query for timestamps */ + if (q->type == PIPE_QUERY_TIMESTAMP) + return; if (q->precise) flags |= VK_QUERY_CONTROL_PRECISE_BIT; if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) { @@ -264,7 +299,6 @@ begin_query(struct zink_context *ctx, struct zink_batch *batch, struct zink_quer q->xfb_running = true; } else vkCmdBeginQuery(batch->cmdbuf, q->query_pool, q->curr_query, flags); - q->active = true; if (!batch->active_queries) batch->active_queries = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); assert(batch->active_queries); @@ -279,9 +313,6 @@ zink_begin_query(struct pipe_context *pctx, struct zink_query *query = (struct zink_query *)q; struct zink_batch *batch = zink_curr_batch(zink_context(pctx)); - /* ignore begin_query for timestamps */ - if (query->type == PIPE_QUERY_TIMESTAMP) - return true; util_query_clear_result(&query->accumulated_result, query->type); begin_query(zink_context(pctx), batch, query); @@ -293,9 +324,11 @@ static void end_query(struct zink_context *ctx, struct zink_batch *batch, struct zink_query *q) { struct zink_screen *screen = zink_screen(ctx->base.screen); - assert(q->type != PIPE_QUERY_TIMESTAMP); - q->active = false; - if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) + q->active = q->type == PIPE_QUERY_TIMESTAMP; + if (q->type == PIPE_QUERY_TIMESTAMP) + vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + q->query_pool, q->curr_query); + else if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) screen->vk_CmdEndQueryIndexedEXT(batch->cmdbuf, q->query_pool, q->curr_query, q->index); else vkCmdEndQuery(batch->cmdbuf, q->query_pool, q->curr_query); @@ -316,11 +349,7 @@ zink_end_query(struct pipe_context *pctx, struct zink_query *query = (struct zink_query *)q; struct zink_batch *batch = zink_curr_batch(ctx); - if (query->type == PIPE_QUERY_TIMESTAMP) { - assert(query->curr_query == 0); - vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - query->query_pool, 0); - } else if (query->active) + if (query->active) end_query(ctx, batch, query); return true;