From fb6071d1087d29cb9165f0168525c585302a10ce Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 5 Oct 2016 15:11:15 +0200 Subject: [PATCH] libs/vkd3d: Delay destroying render passes until the command list is destroyed. Render passes should only be destroyed after all submitted commands referring to them have completed execution. --- libs/vkd3d/command.c | 37 ++++++++++++++++++++++++++++++++----- libs/vkd3d/utils.c | 28 ++++++++++++++++++++++++++++ libs/vkd3d/vkd3d_private.h | 8 ++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 3ec0a19f..1c45f114 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -656,6 +656,17 @@ static inline struct d3d12_command_list *impl_from_ID3D12GraphicsCommandList(ID3 return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList_iface); } +static bool d3d12_command_list_add_render_pass(struct d3d12_command_list *list, VkRenderPass pass) +{ + if (!vkd3d_array_reserve((void **)&list->passes, &list->passes_size, + list->pass_count + 1, sizeof(*list->passes))) + return false; + + list->passes[list->pass_count++] = pass; + + return true; +} + static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(ID3D12GraphicsCommandList *iface, REFIID riid, void **object) { @@ -698,11 +709,20 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandL if (!refcount) { struct d3d12_device *device = list->device; + struct vkd3d_vk_device_procs *vk_procs; + unsigned int i; + + vk_procs = &device->vk_procs; /* When command pool is destroyed, all command buffers are implicitly freed. */ if (list->allocator) vkd3d_command_allocator_free_command_list(list->allocator, list); + for (i = 0; i < list->pass_count; ++i) + { + VK_CALL(vkDestroyRenderPass(device->vk_device, list->passes[i], NULL)); + } + vkd3d_free(list); ID3D12Device_Release(&device->ID3D12Device_iface); @@ -1211,6 +1231,13 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra return; } + if (!d3d12_command_list_add_render_pass(list, vk_render_pass)) + { + WARN("Failed to add render pass,\n"); + VK_CALL(vkDestroyRenderPass(list->device->vk_device, vk_render_pass, NULL)); + return; + } + fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; fb_desc.pNext = NULL; fb_desc.flags = 0; @@ -1223,7 +1250,6 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra if ((vr = VK_CALL(vkCreateFramebuffer(list->device->vk_device, &fb_desc, NULL, &vk_framebuffer))) < 0) { WARN("Failed to create Vulkan framebuffer, vr %d.\n", vr); - VK_CALL(vkDestroyRenderPass(list->device->vk_device, vk_render_pass, NULL)); return; } @@ -1245,8 +1271,6 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra } VK_CALL(vkDestroyFramebuffer(list->device->vk_device, vk_framebuffer, NULL)); - - VK_CALL(vkDestroyRenderPass(list->device->vk_device, vk_render_pass, NULL)); } static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList *iface, @@ -1407,16 +1431,19 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d list->type = type; list->device = device; + ID3D12Device_AddRef(&device->ID3D12Device_iface); list->allocator = allocator; if (FAILED(hr = vkd3d_command_allocator_allocate_command_list(allocator, list))) return hr; + list->passes = NULL; + list->passes_size = 0; + list->pass_count = 0; + if (initial_pipeline_state) FIXME("Ignoring initial pipeline state %p.\n", initial_pipeline_state); - ID3D12Device_AddRef(&device->ID3D12Device_iface); - return S_OK; } diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index c438ccaf..38d5a668 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -22,6 +22,34 @@ #include "vkd3d_private.h" +bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size) +{ + size_t new_capacity, max_capacity; + void *new_elements; + + if (element_count <= *capacity) + return true; + + max_capacity = ~(size_t)0 / element_size; + if (max_capacity < element_count) + return false; + + new_capacity = max(*capacity, 4); + while (new_capacity < element_count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + + if (new_capacity < element_count) + new_capacity = element_count; + + if (!(new_elements = vkd3d_realloc(*elements, new_capacity * element_size))) + return false; + + *elements = new_elements; + *capacity = new_capacity; + + return true; +} + BOOL is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) { static const D3D_FEATURE_LEVEL valid_feature_levels[] = diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 58150988..fbbec1ea 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -33,6 +33,7 @@ #include #include +#include #define VKD3D_DESCRIPTOR_MAGIC_FREE 0x00000000u #define VKD3D_DESCRIPTOR_MAGIC_RTV 0x00565452u @@ -205,6 +206,10 @@ struct d3d12_command_list VkCommandBuffer vk_command_buffer; BOOL is_recording; + VkRenderPass *passes; + size_t passes_size; + size_t pass_count; + struct d3d12_command_allocator *allocator; struct d3d12_device *device; }; @@ -261,6 +266,9 @@ const char *debug_vk_queue_flags(VkQueueFlags flags) DECLSPEC_HIDDEN; VkFormat vk_format_from_dxgi_format(DXGI_FORMAT format) DECLSPEC_HIDDEN; +bool vkd3d_array_reserve(void **elements, size_t *capacity, + size_t element_count, size_t element_size) DECLSPEC_HIDDEN; + static inline void *vkd3d_malloc(size_t size) { void *ptr;