From 236f3717c76bf02fb94c6c5dc45e3dcb71ed48e3 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Tue, 19 Mar 2019 00:32:11 -0700 Subject: Fixed issue with staging allocations in Vulkan backend on Integrated GPUs --- .../include/VulkanUtilities/VulkanMemoryManager.h | 28 +++++++++++++++++++++- .../src/VulkanUtilities/VulkanMemoryManager.cpp | 12 ++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.h index 45806642..4092db05 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.h +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanMemoryManager.h @@ -33,6 +33,7 @@ #include "VulkanUtilities/VulkanPhysicalDevice.h" #include "VulkanUtilities/VulkanLogicalDevice.h" #include "VulkanUtilities/VulkanObjectWrappers.h" +#include "HashUtils.h" namespace VulkanUtilities { @@ -199,7 +200,32 @@ protected: Diligent::IMemoryAllocator& m_Allocator; std::mutex m_PagesMtx; - std::unordered_multimap m_Pages; + struct MemoryPageIndex + { + const uint32_t MemoryTypeIndex; + const bool IsHostVisible; + + MemoryPageIndex(uint32_t _MemoryTypeIndex, + bool _IsHostVisible) : + MemoryTypeIndex(_MemoryTypeIndex), + IsHostVisible (_IsHostVisible) + {} + + bool operator == (const MemoryPageIndex& rhs)const + { + return MemoryTypeIndex == rhs.MemoryTypeIndex && + IsHostVisible == rhs.IsHostVisible; + } + + struct Hasher + { + size_t operator()(const MemoryPageIndex& PageIndex)const + { + return Diligent::ComputeHash(PageIndex.MemoryTypeIndex, PageIndex.IsHostVisible); + } + }; + }; + std::unordered_multimap m_Pages; const VkDeviceSize m_DeviceLocalPageSize; const VkDeviceSize m_HostVisiblePageSize; diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp index fd597327..870b00cb 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanMemoryManager.cpp @@ -135,8 +135,16 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice { VulkanMemoryAllocation Allocation; + // On integrated GPUs, there is no difference between host-visible and GPU-only + // memory, so MemoryTypeIndex is the same. As GPU-only pages do not have CPU address, + // we need to use HostVisible flag to differentiate the two. + // It is likely a good idea to always keep staging pages separate to reduce fragmenation + // even though on integrated GPUs same pages can be used for both GPU-only and staging + // allocations. Staging allocations are short-living and will be released when upload is + // complete, while GPU-only allocations are expected to be long-living. + MemoryPageIndex PageIdx{MemoryTypeIndex, HostVisible}; std::lock_guard Lock(m_PagesMtx); - auto range = m_Pages.equal_range(MemoryTypeIndex); + auto range = m_Pages.equal_range(PageIdx); for(auto page_it = range.first; page_it != range.second; ++page_it) { Allocation = page_it->second.Allocate(Size, Alignment); @@ -154,7 +162,7 @@ VulkanMemoryAllocation VulkanMemoryManager::Allocate(VkDeviceSize Size, VkDevice m_CurrAllocatedSize[stat_ind] += PageSize; m_PeakAllocatedSize[stat_ind] = std::max(m_PeakAllocatedSize[stat_ind], m_CurrAllocatedSize[stat_ind]); - auto it = m_Pages.emplace(MemoryTypeIndex, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible}); + auto it = m_Pages.emplace(PageIdx, VulkanMemoryPage{*this, PageSize, MemoryTypeIndex, HostVisible}); LOG_INFO_MESSAGE("VulkanMemoryManager '", m_MgrName, "': created new ", (HostVisible ? "host-visible" : "device-local"), " page. (", Diligent::FormatMemorySize(PageSize, 2), ", type idx: ", MemoryTypeIndex, "). Current allocated size: ", Diligent::FormatMemorySize(m_CurrAllocatedSize[stat_ind], 2)); -- cgit v1.2.3