From 42d49d7603401d662153b9fc4d94917f62c2bd92 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 20 Mar 2018 20:24:11 +0100 Subject: [PATCH] [dxvk] Respect bufferImageGranularity for non-linear images May fix aliasing issues on GPUs where the bufferImageGranularity limit is greater than the alignment requirement of non-linear resources. --- src/dxvk/dxvk_image.cpp | 11 +++++++++++ src/dxvk/dxvk_memory.cpp | 4 +++- src/dxvk/dxvk_memory.h | 13 +++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/dxvk/dxvk_image.cpp b/src/dxvk/dxvk_image.cpp index fb2e0352..f2d202cd 100644 --- a/src/dxvk/dxvk_image.cpp +++ b/src/dxvk/dxvk_image.cpp @@ -30,12 +30,23 @@ namespace dxvk { &info, nullptr, &m_image) != VK_SUCCESS) throw DxvkError("DxvkImage::DxvkImage: Failed to create image"); + // Get memory requirements for the image. We may enforce strict + // alignment on non-linear images in order not to violate the + // bufferImageGranularity limit, which may be greater than the + // required resource memory alignment on some GPUs. VkMemoryRequirements memReq; + m_vkd->vkGetImageMemoryRequirements( m_vkd->device(), m_image, &memReq); + if (info.tiling != VK_IMAGE_TILING_LINEAR) { + memReq.size = align(memReq.size, memAlloc.bufferImageGranularity()); + memReq.alignment = align(memReq.alignment , memAlloc.bufferImageGranularity()); + } + m_memory = memAlloc.alloc(memReq, memFlags); + // Try to bind the allocated memory slice to the image if (m_vkd->vkBindImageMemory(m_vkd->device(), m_image, m_memory.memory(), m_memory.offset()) != VK_SUCCESS) throw DxvkError("DxvkImage::DxvkImage: Failed to bind device memory"); diff --git a/src/dxvk/dxvk_memory.cpp b/src/dxvk/dxvk_memory.cpp index 28d7c52d..4a38c616 100644 --- a/src/dxvk/dxvk_memory.cpp +++ b/src/dxvk/dxvk_memory.cpp @@ -246,7 +246,9 @@ namespace dxvk { DxvkMemoryAllocator::DxvkMemoryAllocator( const Rc& adapter, const Rc& vkd) - : m_vkd(vkd), m_memProps(adapter->memoryProperties()) { + : m_vkd (vkd), + m_devProps(adapter->deviceProperties()), + m_memProps(adapter->memoryProperties()) { for (uint32_t i = 0; i < m_memProps.memoryTypeCount; i++) m_heaps[i] = new DxvkMemoryHeap(m_vkd, i, m_memProps.memoryTypes[i]); } diff --git a/src/dxvk/dxvk_memory.h b/src/dxvk/dxvk_memory.h index 3cbd052c..39f110d9 100644 --- a/src/dxvk/dxvk_memory.h +++ b/src/dxvk/dxvk_memory.h @@ -214,6 +214,18 @@ namespace dxvk { const Rc& vkd); ~DxvkMemoryAllocator(); + /** + * \brief Buffer-image granularity + * + * The granularity between linear and non-linear + * resources in adjacent memory locations. See + * section 11.6 of the Vulkan spec for details. + * \returns Buffer-image granularity + */ + VkDeviceSize bufferImageGranularity() const { + return m_devProps.limits.bufferImageGranularity; + } + /** * \brief Allocates device memory * @@ -228,6 +240,7 @@ namespace dxvk { private: const Rc m_vkd; + const VkPhysicalDeviceProperties m_devProps; const VkPhysicalDeviceMemoryProperties m_memProps; std::array, VK_MAX_MEMORY_TYPES> m_heaps;