From: Conor McCarthy Subject: [PATCH vkd3d v2] vkd3d: Add an optional memory info callback extension. Message-Id: <20191114134234.7806-1-cmccarthy@codeweavers.com> Date: Thu, 14 Nov 2019 23:42:34 +1000 Allows memory info to be sent to Wine DXGI. Signed-off-by: Conor McCarthy --- 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 { -- 2.23.0