diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 933ec1512..b2a4ed7c8 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1372,6 +1372,9 @@ bool WrappedVulkan::Serialise_BeginCaptureFrame(SerialiserType &ser) // PREINIT as if it was GENERAL. for(auto it = m_ImageLayouts.begin(); it != m_ImageLayouts.end(); ++it) { + if(!it->second.memoryBound) + continue; + for(auto stit = it->second.subresourceStates.begin(); stit != it->second.subresourceStates.end(); ++stit) { diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index 3a0c92805..b50272c5f 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -123,6 +123,10 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) return true; } + // if the image has no memory bound, nothing is to be fetched + if(!layout->memoryBound) + return true; + VkDevice d = GetDev(); // INITSTATEBATCH VkCommandBuffer cmd = GetNextCmd(); diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp index c2f1b7124..b60bd6f09 100644 --- a/renderdoc/driver/vulkan/vk_manager.cpp +++ b/renderdoc/driver/vulkan/vk_manager.cpp @@ -331,6 +331,8 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser, t.image = Unwrap(GetCurrentHandle(liveid)); t.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + if(it->second.initialLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) + t.oldLayout = state.newLayout; state.newLayout = t.newLayout = it->second.initialLayout; t.subresourceRange = state.subresourceRange; @@ -351,7 +353,10 @@ void VulkanResourceManager::SerialiseImageStates(SerialiserType &ser, ApplyBarriers(VK_QUEUE_FAMILY_IGNORED, vec, states); for(size_t i = 0; i < vec.size(); i++) - barriers[i].oldLayout = vec[i].second.oldLayout; + { + if(barriers[i].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) + barriers[i].oldLayout = vec[i].second.oldLayout; + } // erase any do-nothing barriers for(auto it = barriers.begin(); it != barriers.end();) diff --git a/renderdoc/driver/vulkan/vk_rendertexture.cpp b/renderdoc/driver/vulkan/vk_rendertexture.cpp index a80516fa8..4f187cfa2 100644 --- a/renderdoc/driver/vulkan/vk_rendertexture.cpp +++ b/renderdoc/driver/vulkan/vk_rendertexture.cpp @@ -166,6 +166,9 @@ bool VulkanReplay::RenderTextureInternal(TextureDisplay cfg, VkRenderPassBeginIn VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle(cfg.resourceId); const ImageInfo &imageInfo = layouts.imageInfo; + if(!layouts.memoryBound) + return false; + CreateTexImageView(liveIm, iminfo, cfg.typeHint, texviews); int displayformat = 0; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 84771000f..4243c8117 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -2172,6 +2172,9 @@ bool VulkanReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, TextureDisplayViews &texviews = m_TexRender.TextureViews[texid]; VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle(texid); + if(!layouts.memoryBound) + return false; + if(!IsStencilFormat(iminfo.format)) stencil = false; @@ -2491,6 +2494,9 @@ bool VulkanReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t m TextureDisplayViews &texviews = m_TexRender.TextureViews[texid]; VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle(texid); + if(!layouts.memoryBound) + return false; + bool stencil = false; // detect if stencil is selected if(IsStencilFormat(iminfo.format) && !channels[0] && channels[1] && !channels[2] && !channels[3]) @@ -2808,6 +2814,9 @@ void VulkanReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mi ImageLayouts &layouts = m_pDriver->m_ImageLayouts[tex]; + if(!layouts.memoryBound) + return; + VkImageCreateInfo imCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, NULL, diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index c5a6ee419..4c03f574b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -1012,6 +1012,10 @@ VkResult WrappedVulkan::vkBindImageMemory(VkDevice device, VkImage image, VkDevi // than the image. record->baseResource = GetResID(mem); } + else + { + m_ImageLayouts[GetResID(image)].memoryBound = true; + } return ret; } @@ -2092,6 +2096,11 @@ VkResult WrappedVulkan::vkBindImageMemory2(VkDevice device, uint32_t bindInfoCou imgrecord->baseResource = memrecord->GetResourceID(); } } + else + { + for(uint32_t i = 0; i < bindInfoCount; i++) + m_ImageLayouts[GetResID(pBindInfos[i].image)].memoryBound = true; + } return ret; } diff --git a/util/test/demos/vk/vk_image_layouts.cpp b/util/test/demos/vk/vk_image_layouts.cpp index d6aa752ee..d60a27131 100644 --- a/util/test/demos/vk/vk_image_layouts.cpp +++ b/util/test/demos/vk/vk_image_layouts.cpp @@ -115,6 +115,10 @@ void main() const VkPhysicalDeviceMemoryProperties *props = NULL; vmaGetMemoryProperties(allocator, &props); + VkImage unboundImg = VK_NULL_HANDLE; + vkCreateImage(device, preinitInfo, NULL, &unboundImg); + setName(unboundImg, "Unbound image"); + while(Running()) { VkImage preinitImg = VK_NULL_HANDLE; diff --git a/util/test/rdtest/testcase.py b/util/test/rdtest/testcase.py index ac3da9599..bd182260b 100644 --- a/util/test/rdtest/testcase.py +++ b/util/test/rdtest/testcase.py @@ -178,6 +178,15 @@ class TestCase: return rd.ReplayOptions() + def get_capture_options(self): + """ + Method to overload if you want to override the capture options used. + + :return: The renderdoc.CaptureOptions to use. + """ + + return rd.CaptureOptions() + def get_capture(self): """ Method to overload if not implementing a run(), using the default run which @@ -188,7 +197,7 @@ class TestCase: """ if self.demos_test_name != '': - return capture.run_and_capture(util.get_demos_binary(), self.demos_test_name, self.demos_frame_cap) + return capture.run_and_capture(util.get_demos_binary(), self.demos_test_name, self.demos_frame_cap, opts=self.get_capture_options()) raise NotImplementedError("If run() is not implemented in a test, then" "get_capture() and check_capture() must be.") diff --git a/util/test/tests/Vulkan/VK_Image_Layouts.py b/util/test/tests/Vulkan/VK_Image_Layouts.py index 45446e04b..8c6aea9fa 100644 --- a/util/test/tests/Vulkan/VK_Image_Layouts.py +++ b/util/test/tests/Vulkan/VK_Image_Layouts.py @@ -5,6 +5,14 @@ import renderdoc as rd class VK_Image_Layouts(rdtest.TestCase): demos_test_name = 'VK_Image_Layouts' + def get_capture_options(self): + opts = rd.CaptureOptions() + + # Ref all resources to pull in the image with unbound data + opts.refAllResources = True + + return opts + def check_capture(self): self.controller.SetFrameEvent(0, False)