From: Conor McCarthy Subject: [PATCH vkd3d v3] vkd3d: Add a memory usage info callback optional extension. Message-Id: <20191205112951.17626-1-cmccarthy@codeweavers.com> Date: Thu, 5 Dec 2019 21:29:51 +1000 Allows memory usage info to be sent to Wine DXGI. Signed-off-by: Conor McCarthy --- Supersedes 173692. v3: Remove total memory from the function parameters. --- include/vkd3d.h | 12 ++++++++++++ libs/vkd3d/command.c | 6 +++--- libs/vkd3d/device.c | 14 +++++++++++++- libs/vkd3d/resource.c | 19 +++++++++++++------ libs/vkd3d/vkd3d_private.h | 20 ++++++++++++++++++++ 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/include/vkd3d.h b/include/vkd3d.h index e2d9ec8..17c07d1 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, INT64 change); + +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 75af27d..1b62f9a 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -1416,7 +1416,7 @@ static void vkd3d_buffer_destroy(struct vkd3d_buffer *buffer, struct d3d12_devic { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - VK_CALL(vkFreeMemory(device->vk_device, buffer->vk_memory, NULL)); + vkd3d_free_device_memory(device, buffer->vk_memory_type, buffer->vk_memory_size, buffer->vk_memory); VK_CALL(vkDestroyBuffer(device->vk_device, buffer->vk_buffer, NULL)); } @@ -3232,8 +3232,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 e3bb2aa..fd593bc 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -3390,6 +3390,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; @@ -3407,6 +3408,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; @@ -3434,7 +3446,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 f40d986..f5fccfa 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -147,6 +147,8 @@ static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device, if (vk_memory_type) *vk_memory_type = allocate_info.memoryTypeIndex; + d3d12_device_update_memory_usage(device, allocate_info.memoryTypeIndex, allocate_info.allocationSize); + return S_OK; } @@ -161,6 +163,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,16 +199,18 @@ 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) { WARN("Failed to bind memory, vr %d.\n", vr); - VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL)); + vkd3d_free_device_memory(device, type, memory_requirements->size, *vk_memory); *vk_memory = VK_NULL_HANDLE; } + 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,17 +264,19 @@ 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) { WARN("Failed to bind memory, vr %d.\n", vr); - VK_CALL(vkFreeMemory(device->vk_device, *vk_memory, NULL)); + vkd3d_free_device_memory(device, type, memory_requirements->size, *vk_memory); *vk_memory = VK_NULL_HANDLE; return hresult_from_vk_result(vr); } + if (vk_memory_type) + *vk_memory_type = type; if (vk_memory_size) *vk_memory_size = memory_requirements->size; @@ -318,13 +326,12 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface) static void d3d12_heap_destroy(struct d3d12_heap *heap) { struct d3d12_device *device = heap->device; - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; TRACE("Destroying heap %p.\n", heap); vkd3d_private_store_destroy(&heap->private_store); - VK_CALL(vkFreeMemory(device->vk_device, heap->vk_memory, NULL)); + vkd3d_free_device_memory(device, heap->vk_memory_type, heap->desc.SizeInBytes, heap->vk_memory); pthread_mutex_destroy(&heap->mutex); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 9ff6bba..28801ba 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -839,6 +839,8 @@ struct vkd3d_buffer { VkBuffer vk_buffer; VkDeviceMemory vk_memory; + VkDeviceSize vk_memory_size; + uint32_t vk_memory_type; }; /* ID3D12CommandAllocator */ @@ -1129,6 +1131,7 @@ struct d3d12_device VkPipelineCache vk_pipeline_cache; VkPhysicalDeviceMemoryProperties memory_properties; + PFN_vkd3d_memory_usage_callback pfn_memory_usage_callback; D3D12_FEATURE_DATA_D3D12_OPTIONS feature_options; @@ -1199,6 +1202,23 @@ 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); + + if (device->pfn_memory_usage_callback) + device->pfn_memory_usage_callback(device->parent, non_local, change); +} + +static inline void vkd3d_free_device_memory(struct d3d12_device *device, + uint32_t type, VkDeviceSize size, VkDeviceMemory vk_memory) +{ + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + + VK_CALL(vkFreeMemory(device->vk_device, vk_memory, NULL)); + d3d12_device_update_memory_usage(device, type, -(int64_t)size); +} + /* utils */ enum vkd3d_format_type { -- 2.24.0