[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