From: Conor McCarthy Subject: [PATCH vkd3d 1/3] vkd3d: Track descriptor heaps to allow size querying by descriptor handle. Message-Id: <20210526080754.19362-1-cmccarthy@codeweavers.com> Date: Wed, 26 May 2021 18:07:52 +1000 Required for variable Vulkan bindings. The actual size must be specified when creating a Vulkan descriptor set. Signed-off-by: Conor McCarthy --- libs/vkd3d/device.c | 68 ++++++++++++++++++++++++++++++++++++++ libs/vkd3d/resource.c | 14 ++++++++ libs/vkd3d/vkd3d_private.h | 9 +++++ 3 files changed, 91 insertions(+) diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 877512e3..a4c8bca8 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2228,6 +2228,7 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface) vkd3d_fence_worker_stop(&device->fence_worker, device); d3d12_device_destroy_pipeline_cache(device); d3d12_device_destroy_vkd3d_queues(device); + vkd3d_free(device->descriptor_heaps); for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i) pthread_mutex_destroy(&device->desc_mutex[i]); VK_CALL(vkDestroyDevice(device->vk_device, NULL)); @@ -3727,6 +3728,10 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, if ((device->parent = create_info->parent)) IUnknown_AddRef(device->parent); + device->descriptor_heap_capacity = 0; + device->descriptor_heap_count = 0; + device->descriptor_heaps = NULL; + return S_OK; out_destroy_null_resources: @@ -3782,6 +3787,69 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, device->removed_reason = reason; } +void d3d12_device_track_descriptor_heap(struct d3d12_device *device, + const struct d3d12_descriptor_heap *heap) +{ + if (!device->vk_info.EXT_descriptor_indexing) + return; + + if (!vkd3d_array_reserve((void **)&device->descriptor_heaps, &device->descriptor_heap_capacity, + device->descriptor_heap_count + 1, sizeof(*device->descriptor_heaps))) + { + ERR("Cannot track descriptor heap for unbounded arrays. Out of memory.\n"); + return; + } + + device->descriptor_heaps[device->descriptor_heap_count++] = heap; + /* Do not increment the heap reference count. This reference is deleted on heap destruction. */ +} + +void d3d12_device_untrack_descriptor_heap(struct d3d12_device *device, + const struct d3d12_descriptor_heap *heap) +{ + size_t i; + + if (!device->vk_info.EXT_descriptor_indexing) + return; + + for (i = 0; i < device->descriptor_heap_count; ++i) + { + if (device->descriptor_heaps[i] != heap) + continue; + memmove(&device->descriptor_heaps[i], &device->descriptor_heaps[i + 1], + (device->descriptor_heap_count - i - 1) * sizeof(*device->descriptor_heaps)); + --device->descriptor_heap_count; + return; + } + + ERR("Attempted to untrack an already untracked heap.\n"); +} + +/* Return the available size from the specified descriptor to the heap end. */ +uint32_t d3d12_device_descriptor_heap_size_from_descriptor(struct d3d12_device *device, + const struct d3d12_desc *desc) +{ + size_t i; + + for (i = 0; i < device->descriptor_heap_count; ++i) + { + unsigned int size; + + if (device->descriptor_heaps[i]->descriptors > (const BYTE*)desc) + continue; + size = d3d12_device_get_descriptor_handle_increment_size(device, device->descriptor_heaps[i]->desc.Type); + if (device->descriptor_heaps[i]->descriptors + size * device->descriptor_heaps[i]->desc.NumDescriptors + <= (const BYTE*)desc) + continue; + + return device->descriptor_heaps[i]->desc.NumDescriptors + - (uint32_t)(((const BYTE*)desc - device->descriptor_heaps[i]->descriptors) / size); + } + + ERR("Failed to find descriptor heap size from descriptor pointer.\n"); + return 0; +} + HRESULT vkd3d_create_thread(struct vkd3d_instance *instance, PFN_vkd3d_thread thread_main, void *data, union vkd3d_thread_handle *thread) { diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index a9d4d464..f117efc8 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -3327,6 +3327,7 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea { struct d3d12_device *device = heap->device; unsigned int i; + int rc; vkd3d_private_store_destroy(&heap->private_store); @@ -3372,6 +3373,12 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea vkd3d_free(heap); + if ((rc = pthread_mutex_lock(&device->mutex))) + ERR("Failed to lock mutex, error %d.\n", rc); + d3d12_device_untrack_descriptor_heap(device, heap); + if (!rc) + pthread_mutex_unlock(&device->mutex); + d3d12_device_release(device); } @@ -3504,6 +3511,7 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, size_t max_descriptor_count, descriptor_size; struct d3d12_descriptor_heap *object; HRESULT hr; + int rc; if (!(descriptor_size = d3d12_device_get_descriptor_handle_increment_size(device, desc->Type))) { @@ -3537,6 +3545,12 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, memset(object->descriptors, 0, descriptor_size * desc->NumDescriptors); + if ((rc = pthread_mutex_lock(&device->mutex))) + ERR("Failed to lock mutex, error %d.\n", rc); + d3d12_device_track_descriptor_heap(device, object); + if (!rc) + pthread_mutex_unlock(&device->mutex); + TRACE("Created descriptor heap %p.\n", object); *descriptor_heap = object; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 02184c87..28742a8b 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1179,6 +1179,10 @@ struct d3d12_device const struct vkd3d_format_compatibility_list *format_compatibility_lists; struct vkd3d_null_resources null_resources; struct vkd3d_uav_clear_state uav_clear_state; + + size_t descriptor_heap_capacity; + size_t descriptor_heap_count; + const struct d3d12_descriptor_heap **descriptor_heaps; }; HRESULT d3d12_device_create(struct vkd3d_instance *instance, @@ -1190,6 +1194,11 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, const char *message, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN; struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface) DECLSPEC_HIDDEN; +void d3d12_device_track_descriptor_heap(struct d3d12_device *device, const struct d3d12_descriptor_heap *heap); +void d3d12_device_untrack_descriptor_heap(struct d3d12_device *device, const struct d3d12_descriptor_heap *heap); +uint32_t d3d12_device_descriptor_heap_size_from_descriptor(struct d3d12_device *device, + const struct d3d12_desc *desc); + static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object) { return ID3D12Device_QueryInterface(&device->ID3D12Device_iface, iid, object); -- 2.31.1