From 4950bd2d60d9dbaf37f47cfd7bd76e00462b3057 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Mon, 3 Sep 2018 10:34:30 -0700 Subject: Added alignment parameter to VulkanUploadHeap::Allocate() --- .../include/VulkanUploadHeap.h | 20 ++++++------- .../src/DeviceContextVkImpl.cpp | 11 +++---- .../GraphicsEngineVulkan/src/VulkanUploadHeap.cpp | 34 +++++++++++++++------- 3 files changed, 39 insertions(+), 26 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUploadHeap.h b/Graphics/GraphicsEngineVulkan/include/VulkanUploadHeap.h index 006ccf4a..3e29b87b 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUploadHeap.h +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUploadHeap.h @@ -34,21 +34,21 @@ class RenderDeviceVkImpl; struct VulkanUploadAllocation { VulkanUploadAllocation(){} - VulkanUploadAllocation(void* _CPUAddress, VkDeviceSize _Size, VkDeviceSize _Offset, VkBuffer _vkBuffer) : - CPUAddress(_CPUAddress), - Size (_Size), - Offset (_Offset), - vkBuffer (_vkBuffer) + VulkanUploadAllocation(void* _CPUAddress, VkDeviceSize _Size, VkDeviceSize _AlignedOffset, VkBuffer _vkBuffer) : + CPUAddress (_CPUAddress), + Size (_Size), + AlignedOffset(_AlignedOffset), + vkBuffer (_vkBuffer) {} VulkanUploadAllocation (const VulkanUploadAllocation&) = delete; VulkanUploadAllocation& operator = (const VulkanUploadAllocation&) = delete; VulkanUploadAllocation (VulkanUploadAllocation&&) = default; VulkanUploadAllocation& operator = (VulkanUploadAllocation&&) = default; - VkBuffer vkBuffer = VK_NULL_HANDLE; // Vulkan buffer associated with this memory. - void* CPUAddress = nullptr; - VkDeviceSize Size = 0; - VkDeviceSize Offset = 0; + VkBuffer vkBuffer = VK_NULL_HANDLE; // Vulkan buffer associated with this memory. + void* CPUAddress = nullptr; + VkDeviceSize Size = 0; + VkDeviceSize AlignedOffset = 0; }; class VulkanUploadHeap @@ -65,7 +65,7 @@ public: ~VulkanUploadHeap(); - VulkanUploadAllocation Allocate(size_t SizeInBytes); + VulkanUploadAllocation Allocate(size_t SizeInBytes, size_t Alignment); void DiscardAllocations(uint64_t FenceValue); size_t GetStaleAllocationsCount()const diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 647e210c..1a0a3d41 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -1074,9 +1074,9 @@ namespace Diligent #endif VERIFY_EXPR( static_cast(NumBytes) == NumBytes ); - auto TmpSpace = m_UploadHeap.Allocate(static_cast(NumBytes)); + auto TmpSpace = m_UploadHeap.Allocate(static_cast(NumBytes), 0); memcpy(TmpSpace.CPUAddress, pData, static_cast(NumBytes)); - UpdateBufferRegion(pBuffVk, DstOffset, NumBytes, TmpSpace.vkBuffer, TmpSpace.Offset); + UpdateBufferRegion(pBuffVk, DstOffset, NumBytes, TmpSpace.vkBuffer, TmpSpace.AlignedOffset); // The allocation will stay in the upload heap until the end of the frame at which point all upload // pages will be discarded } @@ -1183,10 +1183,11 @@ namespace Diligent const auto UpdateRegionDepth = CopyInfo.Region.MaxZ - CopyInfo.Region.MinZ; // For UpdateTextureRegion(), use UploadHeap, not dynamic heap - auto Allocation = m_UploadHeap.Allocate(CopyInfo.MemorySize); + static constexpr const size_t BufferOffsetAlignment = 4; // bufferOffset of VkBufferImageCopy must be a multiple of 4 (18.4) + auto Allocation = m_UploadHeap.Allocate(CopyInfo.MemorySize, BufferOffsetAlignment); // The allocation will stay in the upload heap until the end of the frame at which point all upload // pages will be discarded - VERIFY( (Allocation.Offset % 4) == 0, "Allocation offset must be at least 32-bit algined"); + VERIFY( (Allocation.AlignedOffset % BufferOffsetAlignment) == 0, "Allocation offset must be at least 32-bit algined"); #ifdef _DEBUG VERIFY(SrcStride >= CopyInfo.RowSize, "Source data stride (", SrcStride, ") is below the image row size (", CopyInfo.RowSize, ")"); @@ -1210,7 +1211,7 @@ namespace Diligent } } CopyBufferToTexture(Allocation.vkBuffer, - static_cast(Allocation.Offset), + static_cast(Allocation.AlignedOffset), CopyInfo.Region, TextureVk, MipLevel, diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp index 53d35753..aba420e8 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUploadHeap.cpp @@ -79,10 +79,14 @@ VulkanUploadHeap::UploadPageInfo VulkanUploadHeap::CreateNewPage(VkDeviceSize Si return UploadPageInfo{std::move(MemAllocation), std::move(NewBuffer), CPUAddress}; } -VulkanUploadAllocation VulkanUploadHeap::Allocate(size_t SizeInBytes) +VulkanUploadAllocation VulkanUploadHeap::Allocate(size_t SizeInBytes, size_t Alignment) { - static constexpr const size_t MinimumAlignment = 4; - SizeInBytes = (SizeInBytes + MinimumAlignment-1) & ~(MinimumAlignment-1); + VERIFY((Alignment & (Alignment-1)) == 0, "Alignment (", Alignment, ") must be power of two"); + if (Alignment == 0) + { + static constexpr const size_t MinimumAlignment = 4; + Alignment = MinimumAlignment; + } VulkanUploadAllocation Allocation; if(SizeInBytes >= m_PageSize/2) @@ -92,30 +96,38 @@ VulkanUploadAllocation VulkanUploadHeap::Allocate(size_t SizeInBytes) Allocation.vkBuffer = NewPage.Buffer; Allocation.CPUAddress = NewPage.CPUAddress; Allocation.Size = SizeInBytes; - Allocation.Offset = 0; - m_CurrAllocatedSize += NewPage.MemAllocation.Size; + VERIFY(Alignment < SizeInBytes, "Alignment must be smaller than the page size"); + Allocation.AlignedOffset = 0; + m_CurrAllocatedSize += NewPage.MemAllocation.Size; m_Pages.emplace_back(std::move(NewPage)); } else { - if(m_CurrPage.AvailableSize < SizeInBytes) + auto AlignmentOffset = ((m_CurrPage.CurrOffset + (Alignment-1)) & ~(Alignment-1)) - m_CurrPage.CurrOffset; + if(m_CurrPage.AvailableSize < SizeInBytes + AlignmentOffset) { + // Allocate new page auto NewPage = CreateNewPage(m_PageSize); m_CurrPage.Reset(NewPage, m_PageSize); m_CurrAllocatedSize += NewPage.MemAllocation.Size; m_Pages.emplace_back(std::move(NewPage)); + VERIFY_EXPR((m_CurrPage.CurrOffset & (Alignment-1)) == 0); + AlignmentOffset = 0; } - Allocation.vkBuffer = m_CurrPage.vkBuffer; - Allocation.CPUAddress = m_CurrPage.CurrCPUAddress; - Allocation.Size = SizeInBytes; - Allocation.Offset = m_CurrPage.CurrOffset; + m_CurrPage.Advance(AlignmentOffset); + VERIFY_EXPR((m_CurrPage.CurrOffset & (Alignment-1)) == 0); + Allocation.vkBuffer = m_CurrPage.vkBuffer; + Allocation.CPUAddress = m_CurrPage.CurrCPUAddress; + Allocation.Size = SizeInBytes; + Allocation.AlignedOffset = m_CurrPage.CurrOffset; m_CurrPage.Advance(SizeInBytes); } - m_CurrFrameSize += SizeInBytes; + m_CurrFrameSize += SizeInBytes; // Count unaligned size m_PeakFrameSize = std::max(m_CurrFrameSize, m_PeakFrameSize); m_PeakAllocatedSize = std::max(m_CurrAllocatedSize, m_PeakAllocatedSize); + VERIFY_EXPR((Allocation.AlignedOffset & (Alignment-1)) == 0); return Allocation; } -- cgit v1.2.3