venus: batch query feedback and defer until after render pass

vkCmdCopyQueryPoolResults cannot be called within a render pass so batch
and defer the query feedback copies until after the render pass.

Secondary command buffers inside render passes also have their query
feedback copies batched when recorded. When the secondary command buffer
is recorded via vkCmdExecuteCommands, it's batch is merged into the
primary command buffer's batch and is defered until the render pass ends.

If multiview is enabled, vkCmdCopyQueryPoolResults needs to copy
additional queries matching the number of bits set in viewMask.

Signed-off-by: Juston Li <justonli@google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23348>
This commit is contained in:
Juston Li
2023-06-30 08:37:30 -07:00
committed by Marge Bot
parent e96428d588
commit 38b1c39b59
2 changed files with 133 additions and 0 deletions
+132
View File
@@ -16,8 +16,18 @@
#include "vn_descriptor_set.h"
#include "vn_device.h"
#include "vn_image.h"
#include "vn_query_pool.h"
#include "vn_render_pass.h"
/* query feedback batch for deferred recording */
struct vn_command_buffer_query_batch {
struct vn_query_pool *query_pool;
uint32_t query;
uint32_t query_count;
struct list_head head;
};
static void
vn_cmd_submit(struct vn_command_buffer *cmd);
@@ -504,6 +514,45 @@ vn_cmd_transfer_present_src_images(
count, img_barriers);
}
static void
vn_cmd_record_batched_query_feedback(struct vn_command_buffer *cmd)
{
list_for_each_entry_safe(struct vn_command_buffer_query_batch, batch,
&cmd->query_batches, head) {
vn_feedback_query_copy_cmd_record(
vn_command_buffer_to_handle(cmd),
vn_query_pool_to_handle(batch->query_pool), batch->query,
batch->query_count);
list_del(&batch->head);
vk_free(&cmd->allocator, batch);
}
}
static void
vn_cmd_merge_batched_query_feedback(struct vn_command_buffer *primary_cmd,
struct vn_command_buffer *secondary_cmd)
{
list_for_each_entry_safe(struct vn_command_buffer_query_batch,
secondary_batch, &secondary_cmd->query_batches,
head) {
/* TODO: add a cache for batch allocs inside cmd pool */
struct vn_command_buffer_query_batch *primary_batch =
vk_zalloc(&primary_cmd->allocator, sizeof(*primary_batch),
VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!primary_batch) {
primary_cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return;
}
primary_batch->query_pool = secondary_batch->query_pool;
primary_batch->query = secondary_batch->query;
primary_batch->query_count = secondary_batch->query_count;
list_add(&primary_batch->head, &primary_cmd->query_batches);
}
}
static void
vn_cmd_begin_render_pass(struct vn_command_buffer *cmd,
const struct vn_render_pass *pass,
@@ -570,6 +619,7 @@ vn_cmd_end_render_pass(struct vn_command_buffer *cmd)
cmd->builder.render_pass = NULL;
cmd->builder.framebuffer = NULL;
vn_cmd_record_batched_query_feedback(cmd);
cmd->in_render_pass = false;
cmd->render_pass = NULL;
cmd->subpass_index = 0;
@@ -650,6 +700,13 @@ vn_DestroyCommandPool(VkDevice device,
&pool->command_buffers, head) {
vn_cs_encoder_fini(&cmd->cs);
vn_object_base_fini(&cmd->base);
list_for_each_entry_safe(struct vn_command_buffer_query_batch, batch,
&cmd->query_batches, head) {
list_del(&batch->head);
vk_free(&cmd->allocator, batch);
}
vk_free(alloc, cmd);
}
@@ -669,6 +726,11 @@ vn_cmd_reset(struct vn_command_buffer *cmd)
cmd->render_pass = NULL;
cmd->subpass_index = 0;
cmd->view_mask = 0;
list_for_each_entry_safe(struct vn_command_buffer_query_batch, batch,
&cmd->query_batches, head) {
list_del(&batch->head);
vk_free(&cmd->allocator, batch);
}
}
VkResult
@@ -744,6 +806,8 @@ vn_AllocateCommandBuffers(VkDevice device,
vn_cs_encoder_init(&cmd->cs, dev->instance,
VN_CS_ENCODER_STORAGE_SHMEM_POOL, 16 * 1024);
list_inithead(&cmd->query_batches);
VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd);
pCommandBuffers[i] = cmd_handle;
}
@@ -781,6 +845,12 @@ vn_FreeCommandBuffers(VkDevice device,
vn_cs_encoder_fini(&cmd->cs);
list_del(&cmd->head);
list_for_each_entry_safe(struct vn_command_buffer_query_batch, batch,
&cmd->query_batches, head) {
list_del(&batch->head);
vk_free(&cmd->allocator, batch);
}
vn_object_base_fini(&cmd->base);
vk_free(alloc, cmd);
}
@@ -1183,6 +1253,7 @@ vn_CmdEndRendering(VkCommandBuffer commandBuffer)
* so defer until it actually ends.
*/
if (!cmd->suspends) {
vn_cmd_record_batched_query_feedback(cmd);
cmd->in_render_pass = false;
cmd->view_mask = 0;
}
@@ -1677,6 +1748,56 @@ vn_CmdBeginQuery(VkCommandBuffer commandBuffer,
VN_CMD_ENQUEUE(vkCmdBeginQuery, commandBuffer, queryPool, query, flags);
}
static void
vn_cmd_add_query_feedback(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
uint32_t query,
uint32_t queryCount)
{
struct vn_command_buffer *cmd =
vn_command_buffer_from_handle(commandBuffer);
struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool);
if (!pool->feedback)
return;
/* vkCmdCopyQueryPoolResults cannot be called within a render pass so batch
* and defer the query feedback copies until after the render pass
*/
if (cmd->in_render_pass) {
/* Per 1.3.255 spec "If queries are used while executing a render pass
* instance that has multiview enabled, the query uses N consecutive
* query indices in the query pool (starting at query) where N is the
* number of bits set in the view mask in the subpass the query is used
* in."
*
* viewMask is passed in for `vkCmdBeginRendering` but for
* `vkCmdBeginRenderPass/2` they are set by `vkCreateRenderPass` per
* subpass
*/
uint32_t num_queries =
cmd->view_mask ? util_bitcount(cmd->view_mask) : 1;
/* TODO: add a cache for batch allocs inside cmd pool */
struct vn_command_buffer_query_batch *batch =
vk_zalloc(&cmd->allocator, sizeof(*batch), VN_DEFAULT_ALIGN,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!batch) {
cmd->state = VN_COMMAND_BUFFER_STATE_INVALID;
return;
}
batch->query_pool = vn_query_pool_from_handle(queryPool);
batch->query = query;
batch->query_count = num_queries;
list_add(&batch->head, &cmd->query_batches);
} else {
vn_feedback_query_copy_cmd_record(commandBuffer, queryPool, query,
queryCount);
}
}
void
vn_CmdEndQuery(VkCommandBuffer commandBuffer,
VkQueryPool queryPool,
@@ -1829,8 +1950,19 @@ vn_CmdExecuteCommands(VkCommandBuffer commandBuffer,
uint32_t commandBufferCount,
const VkCommandBuffer *pCommandBuffers)
{
struct vn_command_buffer *primary_cmd =
vn_command_buffer_from_handle(commandBuffer);
VN_CMD_ENQUEUE(vkCmdExecuteCommands, commandBuffer, commandBufferCount,
pCommandBuffers);
if (primary_cmd->in_render_pass) {
for (uint32_t i = 0; i < commandBufferCount; i++) {
struct vn_command_buffer *secondary_cmd =
vn_command_buffer_from_handle(pCommandBuffers[i]);
if (secondary_cmd->in_render_pass)
vn_cmd_merge_batched_query_feedback(primary_cmd, secondary_cmd);
}
}
}
void
+1
View File
@@ -80,6 +80,7 @@ struct vn_command_buffer {
* the above variables.
*/
uint32_t view_mask;
struct list_head query_batches;
};
VK_DEFINE_HANDLE_CASTS(vn_command_buffer,
base.base,