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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user