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.
This commit is contained in:
Henri Verbeet 2016-10-05 15:11:15 +02:00
parent ee3c147f82
commit fb6071d108
3 changed files with 68 additions and 5 deletions

View File

@ -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;
}

View File

@ -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[] =

View File

@ -33,6 +33,7 @@
#include <assert.h>
#include <pthread.h>
#include <stdbool.h>
#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;