Allows memory info to be sent to Wine DXGI.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d.h | 12 ++++++++++++ libs/vkd3d/command.c | 5 +++-- libs/vkd3d/device.c | 32 +++++++++++++++++++++++++++++++- libs/vkd3d/resource.c | 20 ++++++++++++++++++-- libs/vkd3d/vkd3d_private.h | 18 ++++++++++++++++++ 5 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/include/vkd3d.h b/include/vkd3d.h index e2d9ec8..2b98a22 100644 --- a/include/vkd3d.h +++ b/include/vkd3d.h @@ -47,6 +47,7 @@ enum vkd3d_structure_type /* 1.2 */ VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO, VKD3D_STRUCTURE_TYPE_APPLICATION_INFO, + VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_CALLBACK_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE), }; @@ -129,6 +130,17 @@ struct vkd3d_optional_device_extensions_info uint32_t extension_count; };
+typedef void (STDMETHODCALLTYPE *PFN_vkd3d_memory_usage_callback)(IUnknown *adapter, + unsigned int non_local, UINT64 total, UINT64 usage); + +struct vkd3d_optional_device_callback_info +{ + enum vkd3d_structure_type type; + const void *next; + + PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback; +}; + /* 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 0532ec0..92aaf8d 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, @@ -3198,8 +3199,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 7421978..23f165e 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1682,6 +1682,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) { @@ -1720,6 +1734,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);
@@ -3425,6 +3443,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; @@ -3442,6 +3461,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;
@@ -3466,7 +3496,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 45a80af..27ed574 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -161,6 +161,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;
@@ -196,7 +197,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) @@ -206,6 +207,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;
@@ -223,6 +228,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;
@@ -258,7 +264,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) @@ -269,6 +275,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;
@@ -334,7 +344,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) @@ -632,6 +645,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 daa521d..d4394fc 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -814,6 +814,8 @@ struct vkd3d_buffer { VkBuffer vk_buffer; VkDeviceMemory vk_memory; + VkDeviceSize vk_memory_size; + uint32_t vk_memory_type; };
/* ID3D12CommandAllocator */ @@ -1072,6 +1074,9 @@ struct d3d12_device VkPipelineCache vk_pipeline_cache;
VkPhysicalDeviceMemoryProperties memory_properties; + uint64_t memory_total[2]; + uint64_t memory_usage[2]; + PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options;
@@ -1141,6 +1146,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(device->parent, non_local, + device->memory_total[non_local], device->memory_usage[non_local]); +} + /* utils */ enum vkd3d_format_type {
On Thu, 14 Nov 2019 at 17:14, Conor McCarthy cmccarthy@codeweavers.com wrote:
+typedef void (STDMETHODCALLTYPE *PFN_vkd3d_memory_usage_callback)(IUnknown *adapter,
unsigned int non_local, UINT64 total, UINT64 usage);
+struct vkd3d_optional_device_callback_info +{
- enum vkd3d_structure_type type;
- const void *next;
- PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
+};
Perhaps it makes sense to expose the totals in some form, but I'd argue that for wined3d the deltas would be more natural.
November 16, 2019 4:56 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
On Thu, 14 Nov 2019 at 17:14, Conor McCarthy cmccarthy@codeweavers.com wrote:
+typedef void (STDMETHODCALLTYPE *PFN_vkd3d_memory_usage_callback)(IUnknown *adapter,
- unsigned int non_local, UINT64 total, UINT64 usage);
+struct vkd3d_optional_device_callback_info +{
- enum vkd3d_structure_type type;
- const void *next;
- PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
+};
Perhaps it makes sense to expose the totals in some form, but I'd argue that for wined3d the deltas would be more natural.
In that case it may make more sense to remove the total from vkd3d for now, and warn about excessive allocation in wined3d instead. What do you think?
On Mon, 18 Nov 2019 at 11:38, Conor McCarthy cmccarthy@codeweavers.com wrote:
November 16, 2019 4:56 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
On Thu, 14 Nov 2019 at 17:14, Conor McCarthy cmccarthy@codeweavers.com wrote:
+typedef void (STDMETHODCALLTYPE *PFN_vkd3d_memory_usage_callback)(IUnknown *adapter,
- unsigned int non_local, UINT64 total, UINT64 usage);
+struct vkd3d_optional_device_callback_info +{
- enum vkd3d_structure_type type;
- const void *next;
- PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback;
+};
Perhaps it makes sense to expose the totals in some form, but I'd argue that for wined3d the deltas would be more natural.
In that case it may make more sense to remove the total from vkd3d for now, and warn about excessive allocation in wined3d instead. What do you think?
Sure.