From eac86fab1536e070c9af703de3c4140069c20a61 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 17 Sep 2018 09:08:00 +0200 Subject: [PATCH] [dxvk] Do not map allocations that don't need a HOST_VISIBLE memory type Should reduce the amount of virtual memory used on systems without dedicated VRAM. Refs #640. --- src/dxvk/dxvk_memory.cpp | 28 ++++++++++++++++++++-------- src/dxvk/dxvk_memory.h | 17 +++++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/dxvk/dxvk_memory.cpp b/src/dxvk/dxvk_memory.cpp index b8db2fae..fdfaa70e 100644 --- a/src/dxvk/dxvk_memory.cpp +++ b/src/dxvk/dxvk_memory.cpp @@ -72,7 +72,15 @@ namespace dxvk { } - DxvkMemory DxvkMemoryChunk::alloc(VkDeviceSize size, VkDeviceSize align) { + DxvkMemory DxvkMemoryChunk::alloc( + VkMemoryPropertyFlags flags, + VkDeviceSize size, + VkDeviceSize align) { + // Property flags must be compatible. This could + // be refined a bit in the future if necessary. + if (m_memory.memFlags != flags) + return DxvkMemory(); + // If the chunk is full, return if (m_freeList.size() == 0) return DxvkMemory(); @@ -219,7 +227,7 @@ namespace dxvk { if (supported && adequate) { result = this->tryAllocFromType(&m_memTypes[i], - req->size, req->alignment, dedAllocInfo); + flags, req->size, req->alignment, dedAllocInfo); } } @@ -229,29 +237,31 @@ namespace dxvk { DxvkMemory DxvkMemoryAllocator::tryAllocFromType( DxvkMemoryType* type, + VkMemoryPropertyFlags flags, VkDeviceSize size, VkDeviceSize align, const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo) { DxvkMemory memory; if ((size >= type->heap->chunkSize / 4) || dedAllocInfo) { - DxvkDeviceMemory devMem = this->tryAllocDeviceMemory(type, size, dedAllocInfo); + DxvkDeviceMemory devMem = this->tryAllocDeviceMemory( + type, flags, size, dedAllocInfo); if (devMem.memHandle != VK_NULL_HANDLE) memory = DxvkMemory(this, nullptr, type, devMem.memHandle, 0, size, devMem.memPointer); } else { for (uint32_t i = 0; i < type->chunks.size() && !memory; i++) - memory = type->chunks[i]->alloc(size, align); + memory = type->chunks[i]->alloc(flags, size, align); if (!memory) { DxvkDeviceMemory devMem = tryAllocDeviceMemory( - type, type->heap->chunkSize, nullptr); + type, flags, type->heap->chunkSize, nullptr); if (devMem.memHandle == VK_NULL_HANDLE) return DxvkMemory(); Rc chunk = new DxvkMemoryChunk(this, type, devMem); - memory = chunk->alloc(size, align); + memory = chunk->alloc(flags, size, align); type->chunks.push_back(std::move(chunk)); } @@ -266,6 +276,7 @@ namespace dxvk { DxvkDeviceMemory DxvkMemoryAllocator::tryAllocDeviceMemory( DxvkMemoryType* type, + VkMemoryPropertyFlags flags, VkDeviceSize size, const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo) { if ((type->memType.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) @@ -274,7 +285,8 @@ namespace dxvk { return DxvkDeviceMemory(); DxvkDeviceMemory result; - result.memSize = size; + result.memSize = size; + result.memFlags = flags; VkMemoryAllocateInfo info; info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -285,7 +297,7 @@ namespace dxvk { if (m_vkd->vkAllocateMemory(m_vkd->device(), &info, nullptr, &result.memHandle) != VK_SUCCESS) return DxvkDeviceMemory(); - if (type->memType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { VkResult status = m_vkd->vkMapMemory(m_vkd->device(), result.memHandle, 0, VK_WHOLE_SIZE, 0, &result.memPointer); if (status != VK_SUCCESS) { diff --git a/src/dxvk/dxvk_memory.h b/src/dxvk/dxvk_memory.h index 129db1d7..540a1a33 100644 --- a/src/dxvk/dxvk_memory.h +++ b/src/dxvk/dxvk_memory.h @@ -27,9 +27,10 @@ namespace dxvk { * be persistently mapped. */ struct DxvkDeviceMemory { - VkDeviceMemory memHandle = VK_NULL_HANDLE; - void* memPointer = nullptr; - VkDeviceSize memSize = 0; + VkDeviceMemory memHandle = VK_NULL_HANDLE; + void* memPointer = nullptr; + VkDeviceSize memSize = 0; + VkMemoryPropertyFlags memFlags = 0; }; @@ -159,19 +160,21 @@ namespace dxvk { DxvkDeviceMemory memory); ~DxvkMemoryChunk(); - + /** * \brief Allocates memory from the chunk * * On failure, this returns a slice with * \c VK_NULL_HANDLE as the memory handle. + * \param [in] flags Requested memory flags * \param [in] size Number of bytes to allocate * \param [in] align Required alignment * \returns The allocated memory slice */ DxvkMemory alloc( - VkDeviceSize size, - VkDeviceSize align); + VkMemoryPropertyFlags flags, + VkDeviceSize size, + VkDeviceSize align); /** * \brief Frees memory @@ -267,12 +270,14 @@ namespace dxvk { DxvkMemory tryAllocFromType( DxvkMemoryType* type, + VkMemoryPropertyFlags flags, VkDeviceSize size, VkDeviceSize align, const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo); DxvkDeviceMemory tryAllocDeviceMemory( DxvkMemoryType* type, + VkMemoryPropertyFlags flags, VkDeviceSize size, const VkMemoryDedicatedAllocateInfoKHR* dedAllocInfo);