This improves performance with Batman: Arkham Knight on NVidia drivers.
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/context_vk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 8c021a66bc7..e70e70f28ec 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1762,7 +1762,7 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.pNext = NULL; - begin_info.flags = 0; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; begin_info.pInheritanceInfo = NULL; if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0) {
From: Zebediah Figura zfigura@codeweavers.com
Allocating and freeing fences in particular can be expensive, as much as 250 µs per call (observed on an NVidia machine). --- dlls/wined3d/context_vk.c | 79 ++++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 2 +- 2 files changed, 58 insertions(+), 23 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index e70e70f28ec..bf2e527f566 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1109,19 +1109,31 @@ 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); }
-static void wined3d_context_vk_remove_command_buffer(struct wined3d_context_vk *context_vk, - unsigned int submit_index) +static void free_command_buffer(struct wined3d_context_vk *context_vk, struct wined3d_command_buffer_vk *buffer) { - 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)); + if (buffer->vk_fence) + 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)); +} + +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];
if (buffer->id > context_vk->completed_command_buffer_id) context_vk->completed_command_buffer_id = buffer->id; + + if (wined3d_array_reserve((void **)&context_vk->completed.buffers, &context_vk->completed.buffers_size, + context_vk->completed.buffer_count + 1, sizeof(*context_vk->completed.buffers))) + context_vk->completed.buffers[context_vk->completed.buffer_count++] = *buffer; + else + free_command_buffer(context_vk, buffer); + *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count]; }
@@ -1685,13 +1697,14 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
if (buffer->vk_command_buffer) { - VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, - context_vk->vk_command_pool, 1, &buffer->vk_command_buffer)); + free_command_buffer(context_vk, buffer); buffer->vk_command_buffer = VK_NULL_HANDLE; }
wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1); context_vk->completed_command_buffer_id = buffer->id; + for (i = 0; i < context_vk->completed.buffer_count; ++i) + free_command_buffer(context_vk, &context_vk->completed.buffers[i]);
heap_free(context_vk->compute.bindings.bindings); heap_free(context_vk->graphics.bindings.bindings); @@ -1713,6 +1726,7 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools); wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk); heap_free(context_vk->submitted.buffers); + heap_free(context_vk->completed.buffers); heap_free(context_vk->retired.objects);
wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes); @@ -1727,7 +1741,6 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const struct wined3d_vk_info *vk_info = context_vk->vk_info; - VkCommandBufferAllocateInfo command_buffer_info; struct wined3d_command_buffer_vk *buffer; VkCommandBufferBeginInfo begin_info; struct wined3d_query_vk *query_vk; @@ -1748,16 +1761,31 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk } }
- command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - command_buffer_info.pNext = NULL; - command_buffer_info.commandPool = context_vk->vk_command_pool; - command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - command_buffer_info.commandBufferCount = 1; - if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device, - &command_buffer_info, &buffer->vk_command_buffer))) < 0) + if (context_vk->completed.buffer_count) { - WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr)); - return VK_NULL_HANDLE; + const struct wined3d_command_buffer_vk *old_buffer; + + old_buffer = &context_vk->completed.buffers[--context_vk->completed.buffer_count]; + buffer->vk_command_buffer = old_buffer->vk_command_buffer; + buffer->vk_fence = old_buffer->vk_fence; + } + else + { + VkCommandBufferAllocateInfo command_buffer_info; + + command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buffer_info.pNext = NULL; + command_buffer_info.commandPool = context_vk->vk_command_pool; + command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buffer_info.commandBufferCount = 1; + if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device, + &command_buffer_info, &buffer->vk_command_buffer))) < 0) + { + WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr)); + return VK_NULL_HANDLE; + } + + buffer->vk_fence = VK_NULL_HANDLE; }
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -1842,11 +1870,18 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
- fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_desc.pNext = NULL; - fence_desc.flags = 0; - if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0) - ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr)); + if (buffer->vk_fence) + { + VK_CALL(vkResetFences(device_vk->vk_device, 1, &buffer->vk_fence)); + } + else + { + fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_desc.pNext = NULL; + fence_desc.flags = 0; + if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0) + ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr)); + }
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = NULL; @@ -3825,7 +3860,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi
command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; command_pool_info.pNext = NULL; - command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index; if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device, &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 001534e8c38..1ec76e19a4b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2729,7 +2729,7 @@ struct wined3d_context_vk struct wined3d_command_buffer_vk *buffers; SIZE_T buffers_size; SIZE_T buffer_count; - } submitted; + } submitted, completed;
struct wined3d_shader_descriptor_writes_vk descriptor_writes;
From: Zebediah Figura zfigura@codeweavers.com
This shouldn't really make a difference, but does make the code a bit conceptually simpler. --- dlls/wined3d/context_vk.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index bf2e527f566..097f8c7032c 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1114,8 +1114,7 @@ static void free_command_buffer(struct wined3d_context_vk *context_vk, struct wi struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const struct wined3d_vk_info *vk_info = context_vk->vk_info;
- if (buffer->vk_fence) - VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL)); + 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)); } @@ -1772,6 +1771,16 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk else { VkCommandBufferAllocateInfo command_buffer_info; + VkFenceCreateInfo fence_desc; + + fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_desc.pNext = NULL; + fence_desc.flags = 0; + if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0) + { + ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr)); + return VK_NULL_HANDLE; + }
command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; command_buffer_info.pNext = NULL; @@ -1782,10 +1791,9 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk &command_buffer_info, &buffer->vk_command_buffer))) < 0) { WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr)); + VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL)); return VK_NULL_HANDLE; } - - buffer->vk_fence = VK_NULL_HANDLE; }
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -1826,7 +1834,6 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context struct wined3d_query_pool_vk *pool_vk, *pool_vk_next; struct wined3d_command_buffer_vk *buffer; struct wined3d_query_vk *query_vk; - VkFenceCreateInfo fence_desc; VkSubmitInfo submit_info; VkResult vr;
@@ -1870,18 +1877,7 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
- if (buffer->vk_fence) - { - VK_CALL(vkResetFences(device_vk->vk_device, 1, &buffer->vk_fence)); - } - else - { - fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_desc.pNext = NULL; - fence_desc.flags = 0; - if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0) - ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr)); - } + VK_CALL(vkResetFences(device_vk->vk_device, 1, &buffer->vk_fence));
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = NULL;
This merge request was approved by Jan Sikorski.