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 <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6923>
This commit is contained in:
Mike Blumenkrantz 2020-07-10 14:44:58 -04:00 committed by Marge Bot
parent 79f3544412
commit 7a40b734ee

View file

@ -35,6 +35,21 @@ struct zink_query {
union pipe_query_result accumulated_result; 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 static VkQueryType
convert_query_type(unsigned query_type, bool *use_64bit, bool *precise) 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) if (query->vkqtype == -1)
return NULL; return NULL;
query->num_queries = query_type == PIPE_QUERY_TIMESTAMP ? 1 : NUM_QUERIES; query->num_queries = NUM_QUERIES;
query->curr_query = 0; query->curr_query = 0;
pool_create.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; 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)); struct zink_batch *batch = zink_batch_no_rp(zink_context(pctx));
vkCmdResetQueryPool(batch->cmdbuf, query->query_pool, 0, query->num_queries); vkCmdResetQueryPool(batch->cmdbuf, query->query_pool, 0, query->num_queries);
if (query->type == PIPE_QUERY_TIMESTAMP)
query->active = true;
return (struct pipe_query *)query; return (struct pipe_query *)query;
} }
@ -156,12 +173,14 @@ get_query_result(struct pipe_context *pctx,
flags |= VK_QUERY_RESULT_64_BIT; flags |= VK_QUERY_RESULT_64_BIT;
if (result != &query->accumulated_result) { if (result != &query->accumulated_result) {
if (query->type == PIPE_QUERY_TIMESTAMP)
util_query_clear_result(result, query->type);
else {
memcpy(result, &query->accumulated_result, sizeof(query->accumulated_result)); memcpy(result, &query->accumulated_result, sizeof(query->accumulated_result));
util_query_clear_result(&query->accumulated_result, query->type); util_query_clear_result(&query->accumulated_result, query->type);
} else {
assert(query->vkqtype != VK_QUERY_TYPE_TIMESTAMP);
flags |= VK_QUERY_RESULT_PARTIAL_BIT;
} }
} else
flags |= VK_QUERY_RESULT_PARTIAL_BIT;
// union pipe_query_result results[NUM_QUERIES * 2]; // union pipe_query_result results[NUM_QUERIES * 2];
/* xfb queries return 2 results */ /* xfb queries return 2 results */
@ -193,6 +212,7 @@ get_query_result(struct pipe_context *pctx,
return false; return false;
} }
uint64_t last_val = 0;
for (int i = 0; i < num_results; ++i) { for (int i = 0; i < num_results; ++i) {
switch (query->type) { switch (query->type) {
case PIPE_QUERY_OCCLUSION_PREDICATE: case PIPE_QUERY_OCCLUSION_PREDICATE:
@ -203,6 +223,13 @@ get_query_result(struct pipe_context *pctx,
result->b |= results[i] != 0; result->b |= results[i] != 0;
break; 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: case PIPE_QUERY_OCCLUSION_COUNTER:
result->u64 += results[i]; result->u64 += results[i];
break; break;
@ -227,6 +254,9 @@ get_query_result(struct pipe_context *pctx,
} }
query->last_checked_query = query->curr_query; query->last_checked_query = query->curr_query;
if (query->type == PIPE_QUERY_TIMESTAMP)
timestamp_to_nanoseconds(screen, &result->u64);
return TRUE; return TRUE;
} }
@ -239,6 +269,7 @@ reset_pool(struct zink_context *ctx, struct zink_batch *batch, struct zink_query
*/ */
batch = zink_batch_no_rp(ctx); batch = zink_batch_no_rp(ctx);
if (q->type != PIPE_QUERY_TIMESTAMP)
get_query_result(&ctx->base, (struct pipe_query*)q, false, &q->accumulated_result); get_query_result(&ctx->base, (struct pipe_query*)q, false, &q->accumulated_result);
vkCmdResetQueryPool(batch->cmdbuf, q->query_pool, 0, q->num_queries); vkCmdResetQueryPool(batch->cmdbuf, q->query_pool, 0, q->num_queries);
q->last_checked_query = q->curr_query = 0; q->last_checked_query = q->curr_query = 0;
@ -253,6 +284,10 @@ begin_query(struct zink_context *ctx, struct zink_batch *batch, struct zink_quer
if (q->needs_reset) if (q->needs_reset)
reset_pool(ctx, batch, q); reset_pool(ctx, batch, q);
assert(q->curr_query < q->num_queries); 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) if (q->precise)
flags |= VK_QUERY_CONTROL_PRECISE_BIT; flags |= VK_QUERY_CONTROL_PRECISE_BIT;
if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) { 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; q->xfb_running = true;
} else } else
vkCmdBeginQuery(batch->cmdbuf, q->query_pool, q->curr_query, flags); vkCmdBeginQuery(batch->cmdbuf, q->query_pool, q->curr_query, flags);
q->active = true;
if (!batch->active_queries) if (!batch->active_queries)
batch->active_queries = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); batch->active_queries = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
assert(batch->active_queries); 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_query *query = (struct zink_query *)q;
struct zink_batch *batch = zink_curr_batch(zink_context(pctx)); 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); util_query_clear_result(&query->accumulated_result, query->type);
begin_query(zink_context(pctx), batch, query); 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) end_query(struct zink_context *ctx, struct zink_batch *batch, struct zink_query *q)
{ {
struct zink_screen *screen = zink_screen(ctx->base.screen); struct zink_screen *screen = zink_screen(ctx->base.screen);
assert(q->type != PIPE_QUERY_TIMESTAMP); q->active = q->type == PIPE_QUERY_TIMESTAMP;
q->active = false; if (q->type == PIPE_QUERY_TIMESTAMP)
if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) 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); screen->vk_CmdEndQueryIndexedEXT(batch->cmdbuf, q->query_pool, q->curr_query, q->index);
else else
vkCmdEndQuery(batch->cmdbuf, q->query_pool, q->curr_query); 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_query *query = (struct zink_query *)q;
struct zink_batch *batch = zink_curr_batch(ctx); struct zink_batch *batch = zink_curr_batch(ctx);
if (query->type == PIPE_QUERY_TIMESTAMP) { if (query->active)
assert(query->curr_query == 0);
vkCmdWriteTimestamp(batch->cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
query->query_pool, 0);
} else if (query->active)
end_query(ctx, batch, query); end_query(ctx, batch, query);
return true; return true;