[PATCH vkd3d 1/3] vkd3d: Track descriptor heaps to allow size querying by descriptor handle.

Conor McCarthy cmccarthy at codeweavers.com
Wed May 26 03:07:52 CDT 2021


Required for variable Vulkan bindings. The actual size must be specified
when creating a Vulkan descriptor set.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 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




More information about the wine-devel mailing list