[PATCH vkd3d 3/3] vkd3d: Add optional memory info callback extension.

Conor McCarthy cmccarthy at codeweavers.com
Fri Nov 8 08:38:27 CST 2019


Allows memory info to be sent to Wine DXGI.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 include/vkd3d.h            | 14 ++++++++++++++
 libs/vkd3d/command.c       |  5 +++--
 libs/vkd3d/device.c        | 32 +++++++++++++++++++++++++++++++-
 libs/vkd3d/resource.c      | 20 ++++++++++++++++++--
 libs/vkd3d/vkd3d_private.h | 18 ++++++++++++++++++
 5 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/include/vkd3d.h b/include/vkd3d.h
index e2d9ec8..e694253 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -48,6 +48,9 @@ enum vkd3d_structure_type
     VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
     VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
 
+    /* 1.3 */
+    VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_CALLBACK_INFO,
+
     VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
 };
 
@@ -129,6 +132,17 @@ struct vkd3d_optional_device_extensions_info
     uint32_t extension_count;
 };
 
+typedef interface IWineDXGIAdapter IWineDXGIAdapter;
+
+struct vkd3d_optional_device_callback_info
+{
+    enum vkd3d_structure_type type;
+    const void *next;
+
+    void (STDMETHODCALLTYPE *pfn_memory_usage_callback)(IWineDXGIAdapter *adapter,
+            unsigned int non_local, UINT64 total, UINT64 usage);
+};
+
 /* vkd3d_image_resource_create_info flags */
 #define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
 #define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 12b773e..f3a09cf 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1418,6 +1418,7 @@ static void vkd3d_buffer_destroy(struct vkd3d_buffer *buffer, struct d3d12_devic
 
     VK_CALL(vkFreeMemory(device->vk_device, buffer->vk_memory, NULL));
     VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
+    d3d12_device_update_memory_usage(device, buffer->vk_memory_type, -(int64_t)buffer->vk_memory_size);
 }
 
 static void d3d12_command_allocator_free_resources(struct d3d12_command_allocator *allocator,
@@ -3199,8 +3200,8 @@ static HRESULT d3d12_command_list_allocate_transfer_buffer(struct d3d12_command_
     if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
             &buffer_desc, &buffer->vk_buffer)))
         return hr;
-    if (FAILED(hr = vkd3d_allocate_buffer_memory(device, buffer->vk_buffer,
-            &heap_properties, D3D12_HEAP_FLAG_NONE, &buffer->vk_memory, NULL, NULL)))
+    if (FAILED(hr = vkd3d_allocate_buffer_memory(device, buffer->vk_buffer, &heap_properties,
+            D3D12_HEAP_FLAG_NONE, &buffer->vk_memory, &buffer->vk_memory_type, &buffer->vk_memory_size)))
     {
         VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL));
         return hr;
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 996eda0..47c3745 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1684,6 +1684,20 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
     return S_OK;
 }
 
+static uint64_t vkd3d_compute_total_device_memory(struct d3d12_device *device, VkMemoryHeapFlags local_flag)
+{
+    uint64_t total = 0;
+    uint32_t i;
+
+    for (i = 0; i < device->memory_properties.memoryHeapCount; ++i)
+    {
+        const VkMemoryHeap *heap = &device->memory_properties.memoryHeaps[i];
+        if ((heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) == local_flag)
+            total += heap->size;
+    }
+    return total;
+}
+
 static HRESULT vkd3d_create_vk_device(struct d3d12_device *device,
         const struct vkd3d_device_create_info *create_info)
 {
@@ -1722,6 +1736,10 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device,
             device_queue_info.family_index[VKD3D_QUEUE_FAMILY_TRANSFER]);
 
     VK_CALL(vkGetPhysicalDeviceMemoryProperties(physical_device, &device->memory_properties));
+    device->memory_total[0] = vkd3d_compute_total_device_memory(device, VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
+    device->memory_total[1] = vkd3d_compute_total_device_memory(device, 0);
+    device->memory_usage[0] = 0;
+    device->memory_usage[1] = 0;
 
     vkd3d_physical_device_info_init(&physical_device_info, device);
 
@@ -3370,6 +3388,7 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device(ID3D12Device *iface)
 static HRESULT d3d12_device_init(struct d3d12_device *device,
         struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
 {
+    const struct vkd3d_optional_device_callback_info *optional_callback;
     const struct vkd3d_vk_device_procs *vk_procs;
     HRESULT hr;
     size_t i;
@@ -3387,6 +3406,17 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
 
     device->vk_device = VK_NULL_HANDLE;
 
+    device->parent = create_info->parent;
+
+    device->pfn_memory_usage_callback = NULL;
+    optional_callback = vkd3d_find_struct(create_info->next, OPTIONAL_DEVICE_CALLBACK_INFO);
+    if (optional_callback)
+    {
+        device->pfn_memory_usage_callback = optional_callback->pfn_memory_usage_callback;
+        if (device->pfn_memory_usage_callback)
+            TRACE("Found memory callback function %p.\n", device->pfn_memory_usage_callback);
+    }
+
     if (FAILED(hr = vkd3d_create_vk_device(device, create_info)))
         goto out_free_instance;
 
@@ -3411,7 +3441,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
     for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
         pthread_mutex_init(&device->desc_mutex[i], NULL);
 
-    if ((device->parent = create_info->parent))
+    if (device->parent)
         IUnknown_AddRef(device->parent);
 
     return S_OK;
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index d6e999e..00abc88 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -170,6 +170,7 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu
     VkMemoryRequirements2 memory_requirements2;
     VkMemoryRequirements *memory_requirements;
     VkBufferMemoryRequirementsInfo2 info;
+    uint32_t type;
     VkResult vr;
     HRESULT hr;
 
@@ -205,7 +206,7 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu
     }
 
     if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
-            memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
+            memory_requirements, dedicated_allocation, vk_memory, &type)))
         return hr;
 
     if ((vr = VK_CALL(vkBindBufferMemory(device->vk_device, vk_buffer, *vk_memory, 0))) < 0)
@@ -215,6 +216,10 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu
         *vk_memory = VK_NULL_HANDLE;
     }
 
+    d3d12_device_update_memory_usage(device, type, memory_requirements->size);
+
+    if (vk_memory_type)
+        *vk_memory_type = type;
     if (vk_memory_size)
         *vk_memory_size = memory_requirements->size;
 
@@ -232,6 +237,7 @@ static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage
     VkMemoryRequirements2 memory_requirements2;
     VkMemoryRequirements *memory_requirements;
     VkImageMemoryRequirementsInfo2 info;
+    uint32_t type;
     VkResult vr;
     HRESULT hr;
 
@@ -267,7 +273,7 @@ static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage
     }
 
     if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
-            memory_requirements, dedicated_allocation, vk_memory, vk_memory_type)))
+            memory_requirements, dedicated_allocation, vk_memory, &type)))
         return hr;
 
     if ((vr = VK_CALL(vkBindImageMemory(device->vk_device, vk_image, *vk_memory, 0))) < 0)
@@ -278,6 +284,10 @@ static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage
         return hresult_from_vk_result(vr);
     }
 
+    d3d12_device_update_memory_usage(device, type, memory_requirements->size);
+
+    if (vk_memory_type)
+        *vk_memory_type = type;
     if (vk_memory_size)
         *vk_memory_size = memory_requirements->size;
 
@@ -343,7 +353,10 @@ static void d3d12_heap_destroy(struct d3d12_heap *heap)
     vkd3d_free(heap);
 
     if (device)
+    {
+        d3d12_device_update_memory_usage(device, heap->vk_memory_type, -(INT64)heap->desc.SizeInBytes);
         d3d12_device_release(device);
+    }
 }
 
 static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface)
@@ -641,6 +654,9 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
         hr = vkd3d_allocate_device_memory(device, &heap->desc.Properties,
                 heap->desc.Flags, &memory_requirements, NULL,
                 &heap->vk_memory, &heap->vk_memory_type);
+
+        if (SUCCEEDED(hr))
+            d3d12_device_update_memory_usage(device, heap->vk_memory_type, memory_requirements.size);
     }
     if (FAILED(hr))
     {
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 9cab193..10a202b 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -817,6 +817,8 @@ struct vkd3d_buffer
 {
     VkBuffer vk_buffer;
     VkDeviceMemory vk_memory;
+    VkDeviceSize vk_memory_size;
+    uint32_t vk_memory_type;
 };
 
 /* ID3D12CommandAllocator */
@@ -1075,6 +1077,9 @@ struct d3d12_device
     VkPipelineCache vk_pipeline_cache;
 
     VkPhysicalDeviceMemoryProperties memory_properties;
+    uint64_t memory_total[2];
+    uint64_t memory_usage[2];
+    void (STDMETHODCALLTYPE *pfn_memory_usage_callback)(IWineDXGIAdapter *adapter, unsigned int non_local, UINT64 total, UINT64 usage);
 
     D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
 
@@ -1143,6 +1148,19 @@ static inline pthread_mutex_t *d3d12_device_get_descriptor_mutex(struct d3d12_de
     return &device->desc_mutex[idx & (ARRAY_SIZE(device->desc_mutex) - 1)];
 }
 
+static inline void d3d12_device_update_memory_usage(struct d3d12_device *device, uint32_t vk_memory_type, int64_t change)
+{
+    unsigned int non_local = !(device->memory_properties.memoryTypes[vk_memory_type].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+    device->memory_usage[non_local] += change;
+    if (device->memory_usage[non_local] > device->memory_total[non_local])
+        WARN("Current type %u usage estimate 0x%"PRIx64" exceeds 0x%"PRIx64" available.\n",
+                vk_memory_type, device->memory_usage[non_local], device->memory_total[non_local]);
+
+    if (device->pfn_memory_usage_callback)
+        device->pfn_memory_usage_callback((IWineDXGIAdapter *)device->parent, non_local,
+                device->memory_total[non_local], device->memory_usage[non_local]);
+}
+
 /* utils */
 enum vkd3d_format_type
 {
-- 
2.23.0




More information about the wine-devel mailing list