From 32f37723f92352d784fa230b49a86ec956d86a3d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 5 Feb 2019 10:20:40 +0100 Subject: [PATCH] Properly use VK_KHR_dedicated_allocation to make some drivers extra happy --- Common/Vulkan/VulkanImage.cpp | 28 +++++++++- ext/native/thin3d/VulkanRenderManager.cpp | 68 ++++++++++++++++++----- 2 files changed, 79 insertions(+), 17 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 8344699157..68b1801f67 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -72,9 +72,27 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, } VkMemoryRequirements mem_reqs{}; - vkGetImageMemoryRequirements(vulkan_->GetDevice(), image_, &mem_reqs); - if (allocator_) { + bool dedicatedAllocation = false; + if (vulkan_->DeviceExtensions().KHR_dedicated_allocation) { + VkImageMemoryRequirementsInfo2KHR memReqInfo2{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR}; + memReqInfo2.image = image_; + + VkMemoryRequirements2KHR memReq2 = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR}; + VkMemoryDedicatedRequirementsKHR memDedicatedReq{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR}; + memReq2.pNext = &memDedicatedReq; + + vkGetImageMemoryRequirements2KHR(vulkan_->GetDevice(), &memReqInfo2, &memReq2); + + mem_reqs = memReq2.memoryRequirements; + dedicatedAllocation = + (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE) || + (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + } else { + vkGetImageMemoryRequirements(vulkan_->GetDevice(), image_, &mem_reqs); + } + + if (allocator_ && !dedicatedAllocation) { offset_ = allocator_->Allocate(mem_reqs, &mem_, Tag()); if (offset_ == VulkanDeviceAllocator::ALLOCATE_FAILED) { ELOG("Image memory allocation failed (mem_reqs.size=%d, typebits=%08x", (int)mem_reqs.size, (int)mem_reqs.memoryTypeBits); @@ -86,6 +104,12 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, mem_alloc.memoryTypeIndex = 0; mem_alloc.allocationSize = mem_reqs.size; + VkMemoryDedicatedAllocateInfoKHR dedicatedAllocateInfo{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR}; + if (dedicatedAllocation) { + dedicatedAllocateInfo.image = image_; + mem_alloc.pNext = &dedicatedAllocateInfo; + } + // Find memory type - don't specify any mapping requirements bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex); _assert_(pass); diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 7f3cb56715..c63e0dd412 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -42,24 +42,39 @@ void CreateImage(VulkanContext *vulkan, VkCommandBuffer cmd, VKRImage &img, int vkCreateImage(vulkan->GetDevice(), &ici, nullptr, &img.image); VkMemoryRequirements memreq; - vkGetImageMemoryRequirements(vulkan->GetDevice(), img.image, &memreq); + + bool dedicatedAllocation = false; + if (vulkan->DeviceExtensions().KHR_dedicated_allocation) { + VkImageMemoryRequirementsInfo2KHR memReqInfo2{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR}; + memReqInfo2.image = img.image; + + VkMemoryRequirements2KHR memReq2 = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR}; + VkMemoryDedicatedRequirementsKHR memDedicatedReq{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR}; + memReq2.pNext = &memDedicatedReq; + + vkGetImageMemoryRequirements2KHR(vulkan->GetDevice(), &memReqInfo2, &memReq2); + + memreq = memReq2.memoryRequirements; + dedicatedAllocation = + (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE) || + (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + } else { + vkGetImageMemoryRequirements(vulkan->GetDevice(), img.image, &memreq); + } VkMemoryAllocateInfo alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; alloc.allocationSize = memreq.size; - - /* - // Hint to the driver that this allocation is image-specific. Some drivers benefit. - // We only bother supporting the KHR extension, not the old NV one. - VkMemoryDedicatedAllocateInfoKHR dedicated{ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR }; - if (vulkan->DeviceExtensions().DEDICATED_ALLOCATION) { - alloc.pNext = &dedicated; - dedicated.image = img.image; + VkMemoryDedicatedAllocateInfoKHR dedicatedAllocateInfo{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR}; + if (dedicatedAllocation) { + dedicatedAllocateInfo.image = img.image; + alloc.pNext = &dedicatedAllocateInfo; } - */ vulkan->MemoryTypeFromProperties(memreq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &alloc.memoryTypeIndex); + VkResult res = vkAllocateMemory(vulkan->GetDevice(), &alloc, nullptr, &img.memory); assert(res == VK_SUCCESS); + res = vkBindImageMemory(vulkan->GetDevice(), img.image, img.memory, 0); assert(res == VK_SUCCESS); @@ -554,10 +569,6 @@ bool VulkanRenderManager::InitDepthStencilBuffer(VkCommandBuffer cmd) { image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; image_info.flags = 0; - VkMemoryAllocateInfo mem_alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - VkMemoryRequirements mem_reqs; depth_.format = depth_format; @@ -568,9 +579,36 @@ bool VulkanRenderManager::InitDepthStencilBuffer(VkCommandBuffer cmd) { if (res != VK_SUCCESS) return false; - vkGetImageMemoryRequirements(device, depth_.image, &mem_reqs); + bool dedicatedAllocation = false; + if (vulkan_->DeviceExtensions().KHR_dedicated_allocation) { + VkImageMemoryRequirementsInfo2KHR memReqInfo2{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR}; + memReqInfo2.image = depth_.image; + VkMemoryRequirements2KHR memReq2 = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR}; + VkMemoryDedicatedRequirementsKHR memDedicatedReq{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR}; + memReq2.pNext = &memDedicatedReq; + + vkGetImageMemoryRequirements2KHR(vulkan_->GetDevice(), &memReqInfo2, &memReq2); + + mem_reqs = memReq2.memoryRequirements; + dedicatedAllocation = + (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE) || + (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + } else { + vkGetImageMemoryRequirements(vulkan_->GetDevice(), depth_.image, &mem_reqs); + } + + + VkMemoryAllocateInfo mem_alloc = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; mem_alloc.allocationSize = mem_reqs.size; + mem_alloc.memoryTypeIndex = 0; + + VkMemoryDedicatedAllocateInfoKHR dedicatedAllocateInfo{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR}; + if (dedicatedAllocation) { + dedicatedAllocateInfo.image = depth_.image; + mem_alloc.pNext = &dedicatedAllocateInfo; + } + // Use the memory properties to determine the type of memory required pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, 0, /* No requirements */