vkd3d: Create separate descriptor pools for each vkd3d descriptor type.

Now that our Vulkan descriptor sets contain only a single vkd3d
descriptor type, we're able to create descriptor pools containing only a
single vkd3d descriptor type as well. This avoids wasting unallocated
descriptors of one type when we run out of descriptors of another type.
This commit is contained in:
Conor McCarthy
2024-10-25 12:57:25 +10:00
committed by Henri Verbeet
parent a97c7c1fda
commit e729ceeb1a
Notes: Henri Verbeet 2024-12-05 21:35:35 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1088
4 changed files with 115 additions and 97 deletions

View File

@@ -1463,23 +1463,33 @@ static bool d3d12_command_allocator_add_transfer_buffer(struct d3d12_command_all
}
static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
struct d3d12_command_allocator *allocator)
struct d3d12_command_allocator *allocator, enum vkd3d_shader_descriptor_type descriptor_type)
{
struct d3d12_device *device = allocator->device;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct VkDescriptorPoolCreateInfo pool_desc;
VkDevice vk_device = device->vk_device;
VkDescriptorPoolSize vk_pool_sizes[2];
VkDescriptorPool vk_pool;
VkResult vr;
if (!(vk_pool = vkd3d_vk_descriptor_pool_array_pop(&allocator->free_descriptor_pools)))
if (!(vk_pool = vkd3d_vk_descriptor_pool_array_pop(&allocator->free_descriptor_pools[descriptor_type])))
{
vk_pool_sizes[0].type = vk_descriptor_type_from_vkd3d_descriptor_type(descriptor_type, true);
vk_pool_sizes[0].descriptorCount = device->vk_pool_sizes[descriptor_type];
vk_pool_sizes[1].type = vk_descriptor_type_from_vkd3d_descriptor_type(descriptor_type, false);
vk_pool_sizes[1].descriptorCount = vk_pool_sizes[0].descriptorCount;
pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_desc.pNext = NULL;
pool_desc.flags = 0;
pool_desc.maxSets = 512;
pool_desc.poolSizeCount = device->vk_pool_count;
pool_desc.pPoolSizes = device->vk_pool_sizes;
pool_desc.poolSizeCount = 1;
if (vk_pool_sizes[1].type != vk_pool_sizes[0].type)
++pool_desc.poolSizeCount;
pool_desc.pPoolSizes = vk_pool_sizes;
if ((vr = VK_CALL(vkCreateDescriptorPool(vk_device, &pool_desc, NULL, &vk_pool))) < 0)
{
ERR("Failed to create descriptor pool, vr %d.\n", vr);
@@ -1487,7 +1497,7 @@ static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
}
}
if (!(vkd3d_vk_descriptor_pool_array_push(&allocator->descriptor_pools, vk_pool)))
if (!(vkd3d_vk_descriptor_pool_array_push(&allocator->descriptor_pools[descriptor_type], vk_pool)))
{
ERR("Failed to add descriptor pool.\n");
VK_CALL(vkDestroyDescriptorPool(vk_device, vk_pool, NULL));
@@ -1497,8 +1507,8 @@ static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
return vk_pool;
}
static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(
struct d3d12_command_allocator *allocator, VkDescriptorSetLayout vk_set_layout,
static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(struct d3d12_command_allocator *allocator,
enum vkd3d_shader_descriptor_type descriptor_type, VkDescriptorSetLayout vk_set_layout,
unsigned int variable_binding_size, bool unbounded)
{
struct d3d12_device *device = allocator->device;
@@ -1509,14 +1519,15 @@ static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(
VkDescriptorSet vk_descriptor_set;
VkResult vr;
if (!allocator->vk_descriptor_pool)
allocator->vk_descriptor_pool = d3d12_command_allocator_allocate_descriptor_pool(allocator);
if (!allocator->vk_descriptor_pool)
if (!allocator->vk_descriptor_pools[descriptor_type])
allocator->vk_descriptor_pools[descriptor_type] = d3d12_command_allocator_allocate_descriptor_pool(allocator,
descriptor_type);
if (!allocator->vk_descriptor_pools[descriptor_type])
return VK_NULL_HANDLE;
set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
set_desc.pNext = NULL;
set_desc.descriptorPool = allocator->vk_descriptor_pool;
set_desc.descriptorPool = allocator->vk_descriptor_pools[descriptor_type];
set_desc.descriptorSetCount = 1;
set_desc.pSetLayouts = &vk_set_layout;
if (unbounded)
@@ -1530,16 +1541,17 @@ static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(
if ((vr = VK_CALL(vkAllocateDescriptorSets(vk_device, &set_desc, &vk_descriptor_set))) >= 0)
return vk_descriptor_set;
allocator->vk_descriptor_pool = VK_NULL_HANDLE;
allocator->vk_descriptor_pools[descriptor_type] = VK_NULL_HANDLE;
if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY_KHR)
allocator->vk_descriptor_pool = d3d12_command_allocator_allocate_descriptor_pool(allocator);
if (!allocator->vk_descriptor_pool)
allocator->vk_descriptor_pools[descriptor_type] = d3d12_command_allocator_allocate_descriptor_pool(allocator,
descriptor_type);
if (!allocator->vk_descriptor_pools[descriptor_type])
{
ERR("Failed to allocate descriptor set, vr %d.\n", vr);
return VK_NULL_HANDLE;
}
set_desc.descriptorPool = allocator->vk_descriptor_pool;
set_desc.descriptorPool = allocator->vk_descriptor_pools[descriptor_type];
if ((vr = VK_CALL(vkAllocateDescriptorSets(vk_device, &set_desc, &vk_descriptor_set))) < 0)
{
FIXME("Failed to allocate descriptor set from a new pool, vr %d.\n", vr);
@@ -1565,6 +1577,26 @@ static void vkd3d_buffer_destroy(struct vkd3d_buffer *buffer, struct d3d12_devic
VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
}
static void d3d12_command_allocator_reset_descriptor_pool_array(struct d3d12_command_allocator *allocator,
enum vkd3d_shader_descriptor_type type)
{
struct vkd3d_vk_descriptor_pool_array *array = &allocator->descriptor_pools[type];
struct d3d12_device *device = allocator->device;
const struct vkd3d_vk_device_procs *vk_procs;
size_t i;
if (!vkd3d_vk_descriptor_pool_array_push_array(&allocator->free_descriptor_pools[type],
array->pools, array->count))
return;
vk_procs = &device->vk_procs;
for (i = 0; i < array->count; ++i)
{
VK_CALL(vkResetDescriptorPool(device->vk_device, array->pools[i], 0));
}
array->count = 0;
}
static void d3d12_command_allocator_free_resources(struct d3d12_command_allocator *allocator,
bool keep_reusable_resources)
{
@@ -1572,24 +1604,21 @@ static void d3d12_command_allocator_free_resources(struct d3d12_command_allocato
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
unsigned int i;
allocator->vk_descriptor_pool = VK_NULL_HANDLE;
memset(allocator->vk_descriptor_pools, 0, sizeof(allocator->vk_descriptor_pools));
if (keep_reusable_resources)
{
struct vkd3d_vk_descriptor_pool_array *array = &allocator->descriptor_pools;
if (vkd3d_vk_descriptor_pool_array_push_array(&allocator->free_descriptor_pools, array->pools, array->count))
for (i = 0; i < ARRAY_SIZE(allocator->descriptor_pools); ++i)
{
for (i = 0; i < array->count; ++i)
{
VK_CALL(vkResetDescriptorPool(device->vk_device, array->pools[i], 0));
}
array->count = 0;
d3d12_command_allocator_reset_descriptor_pool_array(allocator, i);
}
}
else
{
vkd3d_vk_descriptor_pool_array_destroy_pools(&allocator->free_descriptor_pools, device);
for (i = 0; i < ARRAY_SIZE(allocator->free_descriptor_pools); ++i)
{
vkd3d_vk_descriptor_pool_array_destroy_pools(&allocator->free_descriptor_pools[i], device);
}
}
for (i = 0; i < allocator->transfer_buffer_count; ++i)
@@ -1610,7 +1639,10 @@ static void d3d12_command_allocator_free_resources(struct d3d12_command_allocato
}
allocator->view_count = 0;
vkd3d_vk_descriptor_pool_array_destroy_pools(&allocator->descriptor_pools, device);
for (i = 0; i < ARRAY_SIZE(allocator->descriptor_pools); ++i)
{
vkd3d_vk_descriptor_pool_array_destroy_pools(&allocator->descriptor_pools[i], device);
}
for (i = 0; i < allocator->framebuffer_count; ++i)
{
@@ -1667,6 +1699,7 @@ static ULONG STDMETHODCALLTYPE d3d12_command_allocator_Release(ID3D12CommandAllo
{
struct d3d12_command_allocator *allocator = impl_from_ID3D12CommandAllocator(iface);
unsigned int refcount = vkd3d_atomic_decrement_u32(&allocator->refcount);
size_t i;
TRACE("%p decreasing refcount to %u.\n", allocator, refcount);
@@ -1684,8 +1717,11 @@ static ULONG STDMETHODCALLTYPE d3d12_command_allocator_Release(ID3D12CommandAllo
vkd3d_free(allocator->transfer_buffers);
vkd3d_free(allocator->buffer_views);
vkd3d_free(allocator->views);
vkd3d_vk_descriptor_pool_array_cleanup(&allocator->descriptor_pools);
vkd3d_vk_descriptor_pool_array_cleanup(&allocator->free_descriptor_pools);
for (i = 0; i < ARRAY_SIZE(allocator->free_descriptor_pools); ++i)
{
vkd3d_vk_descriptor_pool_array_cleanup(&allocator->descriptor_pools[i]);
vkd3d_vk_descriptor_pool_array_cleanup(&allocator->free_descriptor_pools[i]);
}
vkd3d_free(allocator->framebuffers);
vkd3d_free(allocator->passes);
@@ -1842,6 +1878,7 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
struct vkd3d_queue *queue;
VkResult vr;
HRESULT hr;
size_t i;
if (FAILED(hr = vkd3d_private_store_init(&allocator->private_store)))
return hr;
@@ -1871,9 +1908,12 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
return hresult_from_vk_result(vr);
}
allocator->vk_descriptor_pool = VK_NULL_HANDLE;
memset(allocator->vk_descriptor_pools, 0, sizeof(allocator->vk_descriptor_pools));
vkd3d_vk_descriptor_pool_array_init(&allocator->free_descriptor_pools);
for (i = 0; i < ARRAY_SIZE(allocator->free_descriptor_pools); ++i)
{
vkd3d_vk_descriptor_pool_array_init(&allocator->free_descriptor_pools[i]);
}
allocator->passes = NULL;
allocator->passes_size = 0;
@@ -1883,7 +1923,10 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
allocator->framebuffers_size = 0;
allocator->framebuffer_count = 0;
vkd3d_vk_descriptor_pool_array_init(&allocator->descriptor_pools);
for (i = 0; i < ARRAY_SIZE(allocator->descriptor_pools); ++i)
{
vkd3d_vk_descriptor_pool_array_init(&allocator->descriptor_pools[i]);
}
allocator->views = NULL;
allocator->views_size = 0;
@@ -2765,7 +2808,7 @@ static void d3d12_command_list_prepare_descriptors(struct d3d12_command_list *li
}
vk_descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator,
layout->vk_layout, variable_binding_size, unbounded_offset != UINT_MAX);
layout->descriptor_type, layout->vk_layout, variable_binding_size, unbounded_offset != UINT_MAX);
bindings->descriptor_sets[bindings->descriptor_set_count++] = vk_descriptor_set;
}
@@ -3050,8 +3093,8 @@ static void d3d12_command_list_update_uav_counter_descriptors(struct d3d12_comma
uav_counter_count = state->uav_counters.binding_count;
if (!(vk_descriptor_writes = vkd3d_calloc(uav_counter_count, sizeof(*vk_descriptor_writes))))
return;
if (!(vk_descriptor_set = d3d12_command_allocator_allocate_descriptor_set(
list->allocator, state->uav_counters.vk_set_layout, 0, false)))
if (!(vk_descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator,
VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, state->uav_counters.vk_set_layout, 0, false)))
goto done;
for (i = 0; i < uav_counter_count; ++i)
@@ -5380,8 +5423,8 @@ static void d3d12_command_list_clear_uav(struct d3d12_command_list *list,
view->info.texture.vk_view_type, view->format->type, &pipeline);
}
if (!(write_set.dstSet = d3d12_command_allocator_allocate_descriptor_set(
list->allocator, pipeline.vk_set_layout, 0, false)))
if (!(write_set.dstSet = d3d12_command_allocator_allocate_descriptor_set(list->allocator,
VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, pipeline.vk_set_layout, 0, false)))
{
ERR("Failed to allocate descriptor set.\n");
return;