vkd3d: Use a binary search for matching a descriptor to an allocation.

The performance improvement will be useful for Vulkan-backed heaps,
where descriptor heaps must be found more often.

Signed-off-by: Conor McCarthy <cmccarthy@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Conor McCarthy 2022-01-05 14:54:50 +10:00 committed by Alexandre Julliard
parent 2edec69da4
commit 67ee837f2b

View File

@ -2179,6 +2179,33 @@ static void vkd3d_gpu_va_allocator_cleanup(struct vkd3d_gpu_va_allocator *alloca
pthread_mutex_destroy(&allocator->mutex); pthread_mutex_destroy(&allocator->mutex);
} }
/* We could use bsearch() or recursion here, but it probably helps to omit
* all the extra function calls. */
static struct vkd3d_gpu_descriptor_allocation *vkd3d_gpu_descriptor_allocator_binary_search(
const struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{
struct vkd3d_gpu_descriptor_allocation *allocations = allocator->allocations;
const struct d3d12_desc *base;
size_t centre, count;
for (count = allocator->allocation_count; count > 1; )
{
centre = count >> 1;
base = allocations[centre].base;
if (base <= desc)
{
allocations += centre;
count -= centre;
}
else
{
count = centre;
}
}
return allocations;
}
bool vkd3d_gpu_descriptor_allocator_register_range(struct vkd3d_gpu_descriptor_allocator *allocator, bool vkd3d_gpu_descriptor_allocator_register_range(struct vkd3d_gpu_descriptor_allocator *allocator,
const struct d3d12_desc *base, size_t count) const struct d3d12_desc *base, size_t count)
{ {
@ -2198,7 +2225,14 @@ bool vkd3d_gpu_descriptor_allocator_register_range(struct vkd3d_gpu_descriptor_a
return false; return false;
} }
allocation = &allocator->allocations[allocator->allocation_count++]; if (allocator->allocation_count > 1)
allocation = vkd3d_gpu_descriptor_allocator_binary_search(allocator, base);
else
allocation = allocator->allocations;
allocation += allocator->allocation_count && base > allocation->base;
memmove(&allocation[1], allocation, (allocator->allocation_count++ - (allocation - allocator->allocations))
* sizeof(*allocation));
allocation->base = base; allocation->base = base;
allocation->count = count; allocation->count = count;
@ -2225,8 +2259,8 @@ bool vkd3d_gpu_descriptor_allocator_unregister_range(
if (allocator->allocations[i].base != base) if (allocator->allocations[i].base != base)
continue; continue;
if (i != --allocator->allocation_count) memmove(&allocator->allocations[i], &allocator->allocations[i + 1],
allocator->allocations[i] = allocator->allocations[allocator->allocation_count]; (--allocator->allocation_count - i) * sizeof(allocator->allocations[0]));
found = true; found = true;
break; break;
@ -2237,34 +2271,34 @@ bool vkd3d_gpu_descriptor_allocator_unregister_range(
return found; return found;
} }
static inline const struct vkd3d_gpu_descriptor_allocation *vkd3d_gpu_descriptor_allocator_allocation_from_descriptor(
const struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{
const struct vkd3d_gpu_descriptor_allocation *allocation;
allocation = vkd3d_gpu_descriptor_allocator_binary_search(allocator, desc);
return (desc >= allocation->base && desc - allocation->base < allocation->count) ? allocation : NULL;
}
/* Return the available size from the specified descriptor to the heap end. */ /* Return the available size from the specified descriptor to the heap end. */
size_t vkd3d_gpu_descriptor_allocator_range_size_from_descriptor( size_t vkd3d_gpu_descriptor_allocator_range_size_from_descriptor(
struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc) struct vkd3d_gpu_descriptor_allocator *allocator, const struct d3d12_desc *desc)
{ {
struct vkd3d_gpu_descriptor_allocation *allocation; const struct vkd3d_gpu_descriptor_allocation *allocation;
size_t remaining, offset, i; size_t remaining;
int rc; int rc;
assert(allocator->allocation_count);
if ((rc = pthread_mutex_lock(&allocator->mutex))) if ((rc = pthread_mutex_lock(&allocator->mutex)))
{ {
ERR("Failed to lock mutex, error %d.\n", rc); ERR("Failed to lock mutex, error %d.\n", rc);
return 0; return 0;
} }
for (i = 0, remaining = 0; i < allocator->allocation_count; ++i) remaining = 0;
{ if ((allocation = vkd3d_gpu_descriptor_allocator_allocation_from_descriptor(allocator, desc)))
allocation = &allocator->allocations[i]; remaining = allocation->count - (desc - allocation->base);
if (desc < allocation->base)
continue;
offset = desc - allocation->base;
if (offset >= allocation->count)
continue;
remaining = allocation->count - offset;
break;
}
pthread_mutex_unlock(&allocator->mutex); pthread_mutex_unlock(&allocator->mutex);