Only clean while the command buffer is running. A full cleanup is done after submitting to the queue. It can take a while, and we don't necessarily want to delay submitting.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com
From: Jan Sikorski jsikorski@codeweavers.com
Only clean while the command buffer is running. A full cleanup is done after submitting to the queue. It can take a while, and we don't necessarily want to delay submitting.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/context_vk.c | 65 +++++++++++++++++++++------------- dlls/wined3d/wined3d_private.h | 1 - 2 files changed, 40 insertions(+), 26 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index b19220c2e34..aa3b45d54fd 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1067,11 +1067,30 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id); }
-void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_vk) +static void wined3d_context_vk_remove_command_buffer(struct wined3d_context_vk *context_vk, + unsigned int submit_index) { + struct wined3d_command_buffer_vk *buffer = &context_vk->submitted.buffers[submit_index]; struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const struct wined3d_vk_info *vk_info = context_vk->vk_info; + + VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL)); + VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, + context_vk->vk_command_pool, 1, &buffer->vk_command_buffer)); + + if (buffer->id > context_vk->completed_command_buffer_id) + context_vk->completed_command_buffer_id = buffer->id; + *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count]; +} + +static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk, VkFence vk_fence) +{ + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + struct wined3d_retired_objects_vk *retired = &context_vk->retired; + const struct wined3d_vk_info *vk_info = context_vk->vk_info; struct wined3d_command_buffer_vk *buffer; + struct wined3d_retired_object_vk *o; + uint64_t command_buffer_id; SIZE_T i = 0;
while (i < context_vk->submitted.buffer_count) @@ -1085,26 +1104,11 @@ void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_
TRACE("Command buffer %p with id 0x%s has finished.\n", buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id)); - VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL)); - VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, - context_vk->vk_command_pool, 1, &buffer->vk_command_buffer)); - - if (buffer->id > context_vk->completed_command_buffer_id) - context_vk->completed_command_buffer_id = buffer->id; - *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count]; + if (buffer->vk_fence == vk_fence) + return; + wined3d_context_vk_remove_command_buffer(context_vk, i); } -}
-static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk) -{ - struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); - struct wined3d_retired_objects_vk *retired = &context_vk->retired; - const struct wined3d_vk_info *vk_info = context_vk->vk_info; - struct wined3d_retired_object_vk *o; - uint64_t command_buffer_id; - SIZE_T i = 0; - - wined3d_context_vk_poll_command_buffers(context_vk); command_buffer_id = context_vk->completed_command_buffer_id;
retired->free = NULL; @@ -1194,6 +1198,9 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont o->type = WINED3D_RETIRED_FREE_VK; o->u.next = retired->free; retired->free = o; + + if (vk_fence && VK_CALL(vkGetFenceStatus(device_vk->vk_device, vk_fence)) != VK_NOT_READY) + break; } }
@@ -1649,7 +1656,7 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL)); if (context_vk->vk_so_counter_bo.vk_buffer) wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo); - wined3d_context_vk_cleanup_resources(context_vk); + wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE); wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools); wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools); wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools); @@ -1820,13 +1827,14 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context buffer->id = 1; } context_vk->retired_bo_size = 0; - wined3d_context_vk_cleanup_resources(context_vk); + wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE); }
void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id) { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkFence vk_fence; SIZE_T i;
if (id <= context_vk->completed_command_buffer_id @@ -1838,10 +1846,17 @@ void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_v if (context_vk->submitted.buffers[i].id != id) continue;
- VK_CALL(vkWaitForFences(device_vk->vk_device, 1, - &context_vk->submitted.buffers[i].vk_fence, VK_TRUE, UINT64_MAX)); - wined3d_context_vk_cleanup_resources(context_vk); - return; + vk_fence = context_vk->submitted.buffers[i].vk_fence; + wined3d_context_vk_cleanup_resources(context_vk, vk_fence); + for (i = 0; i < context_vk->submitted.buffer_count; ++i) + { + if (context_vk->submitted.buffers[i].id != id) + continue; + + VK_CALL(vkWaitForFences(device_vk->vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX)); + wined3d_context_vk_remove_command_buffer(context_vk, i); + return; + } }
ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id)); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3a12f5ef261..385c84ffcbf 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2685,7 +2685,6 @@ void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk, VkImageLayout new_layout, VkImage image, const VkImageSubresourceRange *range) DECLSPEC_HIDDEN; HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk, unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages, unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores) DECLSPEC_HIDDEN;
On Wed, 4 May 2022 at 15:36, Jan Sikorski wine@gitlab.winehq.org wrote:
@@ -1838,10 +1846,17 @@ void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_v if (context_vk->submitted.buffers[i].id != id) continue;
VK_CALL(vkWaitForFences(device_vk->vk_device, 1,
&context_vk->submitted.buffers[i].vk_fence, VK_TRUE, UINT64_MAX));
wined3d_context_vk_cleanup_resources(context_vk);
return;
vk_fence = context_vk->submitted.buffers[i].vk_fence;
wined3d_context_vk_cleanup_resources(context_vk, vk_fence);
for (i = 0; i < context_vk->submitted.buffer_count; ++i)
{
if (context_vk->submitted.buffers[i].id != id)
continue;
VK_CALL(vkWaitForFences(device_vk->vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX));
wined3d_context_vk_remove_command_buffer(context_vk, i);
return;
}}
I suppose that works, although I think the double loop look a little awkward. It might be worth introducing a helper to lookup a command buffer by ID to avoid that at some point.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com