From 2eabbbe57d1215695310ed8ce101be6a448a557e Mon Sep 17 00:00:00 2001 From: Ella Stanforth Date: Wed, 3 Dec 2025 09:59:04 +0000 Subject: [PATCH] pvr: use linked list to back deferred clears Signed-off-by: Ella Stanforth Acked-by: Erik Faye-Lund Part-of: --- src/imagination/vulkan/pvr_blit.c | 27 +++++++++---------------- src/imagination/vulkan/pvr_cmd_buffer.c | 23 ++++++++++++--------- src/imagination/vulkan/pvr_cmd_buffer.h | 7 +------ 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/imagination/vulkan/pvr_blit.c b/src/imagination/vulkan/pvr_blit.c index 8f33494918d..ff4c3be6895 100644 --- a/src/imagination/vulkan/pvr_blit.c +++ b/src/imagination/vulkan/pvr_blit.c @@ -1835,7 +1835,6 @@ static VkResult pvr_add_deferred_rta_clear(struct pvr_cmd_buffer *cmd_buffer, struct pvr_sub_cmd_gfx *sub_cmd = &cmd_buffer->state.current_sub_cmd->gfx; const struct pvr_renderpass_hwsetup_render *hw_render = &pass_info->pass->hw_setup->renders[sub_cmd->hw_render_idx]; - struct pvr_transfer_cmd *transfer_cmd_list; const struct pvr_image_view *image_view; const struct pvr_image *image; uint32_t base_layer; @@ -1854,14 +1853,6 @@ static VkResult pvr_add_deferred_rta_clear(struct pvr_cmd_buffer *cmd_buffer, assert( !PVR_HAS_FEATURE(&cmd_buffer->device->pdevice->dev_info, gs_rta_support)); - transfer_cmd_list = util_dynarray_grow(&cmd_buffer->deferred_clears, - struct pvr_transfer_cmd, - rect->layerCount); - if (!transfer_cmd_list) { - return vk_command_buffer_set_error(&cmd_buffer->vk, - VK_ERROR_OUT_OF_HOST_MEMORY); - } - /* From the Vulkan 1.3.229 spec VUID-VkClearAttachment-aspectMask-00019: * * "If aspectMask includes VK_IMAGE_ASPECT_COLOR_BIT, it must not @@ -1899,16 +1890,16 @@ static VkResult pvr_add_deferred_rta_clear(struct pvr_cmd_buffer *cmd_buffer, image = vk_to_pvr_image(image_view->vk.image); for (uint32_t i = 0; i < rect->layerCount; i++) { - struct pvr_transfer_cmd *transfer_cmd = &transfer_cmd_list[i]; + struct pvr_transfer_cmd *transfer_cmd = pvr_transfer_cmd_alloc(cmd_buffer); - /* TODO: Add an init function for when we don't want to use - * pvr_transfer_cmd_alloc()? And use it here. - */ - *transfer_cmd = (struct pvr_transfer_cmd){ - .flags = PVR_TRANSFER_CMD_FLAGS_FILL, - .cmd_buffer = cmd_buffer, - .is_deferred_clear = true, - }; + list_addtail(&transfer_cmd->link, &cmd_buffer->deferred_clears); + + if (!transfer_cmd) { + return vk_command_buffer_set_error(&cmd_buffer->vk, + VK_ERROR_OUT_OF_HOST_MEMORY); + } + + transfer_cmd->flags = PVR_TRANSFER_CMD_FLAGS_FILL; if (attachment->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { for (uint32_t j = 0; j < ARRAY_SIZE(transfer_cmd->clear_color); j++) { diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index a7918d7c10d..b2ac4b58ae7 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -126,8 +126,7 @@ static void pvr_cmd_buffer_free_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, sub_cmd->transfer.transfer_cmds, link) { list_del(&transfer_cmd->link); - if (!transfer_cmd->is_deferred_clear) - vk_free(&cmd_buffer->vk.pool->alloc, transfer_cmd); + vk_free(&cmd_buffer->vk.pool->alloc, transfer_cmd); } break; @@ -174,7 +173,9 @@ static void pvr_cmd_buffer_free_resources(struct pvr_cmd_buffer *cmd_buffer) pvr_bo_suballoc_free(suballoc_bo); } - util_dynarray_fini(&cmd_buffer->deferred_clears); + /* At the end of any graphics job, all of these get moved elsewhere */ + assert(list_is_empty(&cmd_buffer->deferred_clears)); + util_dynarray_fini(&cmd_buffer->deferred_csb_commands); util_dynarray_fini(&cmd_buffer->scissor_array); util_dynarray_fini(&cmd_buffer->depth_bias_array); @@ -241,8 +242,8 @@ static VkResult pvr_cmd_buffer_create(struct pvr_device *device, cmd_buffer->depth_bias_array = UTIL_DYNARRAY_INIT; cmd_buffer->scissor_array = UTIL_DYNARRAY_INIT; cmd_buffer->deferred_csb_commands = UTIL_DYNARRAY_INIT; - cmd_buffer->deferred_clears = UTIL_DYNARRAY_INIT; + list_inithead(&cmd_buffer->deferred_clears); list_inithead(&cmd_buffer->sub_cmds); list_inithead(&cmd_buffer->bo_list); @@ -2235,11 +2236,13 @@ void pvr_compute_generate_fence(struct pvr_cmd_buffer *cmd_buffer, static VkResult pvr_cmd_buffer_process_deferred_clears(struct pvr_cmd_buffer *cmd_buffer) { - util_dynarray_foreach (&cmd_buffer->deferred_clears, - struct pvr_transfer_cmd, - transfer_cmd) { + list_for_each_entry_safe (struct pvr_transfer_cmd, + transfer_cmd, + &cmd_buffer->deferred_clears, + link) { VkResult result; + list_del(&transfer_cmd->link); result = pvr_cmd_buffer_add_transfer_cmd(cmd_buffer, transfer_cmd); if (result != VK_SUCCESS) return result; @@ -7690,7 +7693,7 @@ static VkResult pvr_execute_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, static VkResult pvr_execute_graphics_cmd_buffer(struct pvr_cmd_buffer *cmd_buffer, - const struct pvr_cmd_buffer *sec_cmd_buffer) + struct pvr_cmd_buffer *sec_cmd_buffer) { const struct pvr_device_info *dev_info = &cmd_buffer->device->pdevice->dev_info; @@ -7833,8 +7836,8 @@ pvr_execute_graphics_cmd_buffer(struct pvr_cmd_buffer *cmd_buffer, } if (!PVR_HAS_FEATURE(dev_info, gs_rta_support)) { - util_dynarray_append_dynarray(&cmd_buffer->deferred_clears, - &sec_cmd_buffer->deferred_clears); + list_splicetail(&sec_cmd_buffer->deferred_clears, + &cmd_buffer->deferred_clears); } } diff --git a/src/imagination/vulkan/pvr_cmd_buffer.h b/src/imagination/vulkan/pvr_cmd_buffer.h index e9c345e93ac..a1cb5dcf2d9 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.h +++ b/src/imagination/vulkan/pvr_cmd_buffer.h @@ -111,11 +111,6 @@ struct pvr_transfer_cmd { * cmd_buffer::bo_list head. */ struct pvr_cmd_buffer *cmd_buffer; - - /* Deferred RTA clears are allocated from pvr_cmd_buffer->deferred_clears and - * cannot be freed directly. - */ - bool is_deferred_clear; }; struct pvr_sub_cmd_gfx { @@ -505,7 +500,7 @@ struct pvr_cmd_buffer { /* List of struct pvr_transfer_cmd used to emulate RTA clears on non RTA * capable cores. */ - struct util_dynarray deferred_clears; + struct list_head deferred_clears; /* List of pvr_bo structs associated with this cmd buffer. */ struct list_head bo_list;