From e77f3ad8d10268c7b4268614139730b5c6bbb599 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 17 Aug 2017 13:06:22 +0100 Subject: [PATCH] Create an equivalent 'loadFB' framebuffer for every 'loadRP' renderpass * In order to be able to split apart and partially replay every render pass, we change them to always STORE instead of DONT_CARE, and then create a patched version that only has a single subpass (for each subpass in the original) and has LOAD/STORE semantics. * However because of the requirements for framebuffer <-> renderpass we have to now multiply up the framebuffer to make a patched fb to correspond to each patched renderpass. --- renderdoc/driver/vulkan/vk_info.h | 3 + renderdoc/driver/vulkan/vk_state.cpp | 2 +- .../driver/vulkan/wrappers/vk_misc_funcs.cpp | 66 ++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 20c072a2b..5e4b0cec8 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -254,6 +254,9 @@ struct VulkanCreationInfo vector attachments; uint32_t width, height, layers; + + // See above in loadRPs - we need to duplicate and make framebuffer equivalents for each + vector loadFBs; }; map m_Framebuffer; diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index f4a186e41..0e6efabb0 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -99,7 +99,7 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, Pipeli VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL, Unwrap(m_CreationInfo->m_RenderPass[renderPass].loadRPs[subpass]), - Unwrap(GetResourceManager()->GetCurrentHandle(framebuffer)), + Unwrap(m_CreationInfo->m_Framebuffer[framebuffer].loadFBs[subpass]), renderArea, (uint32_t)m_CreationInfo->m_RenderPass[renderPass].attachments.size(), empty, diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index 44749ff18..682b61145 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -497,7 +497,46 @@ bool WrappedVulkan::Serialise_vkCreateFramebuffer(Serialiser *localSerialiser, V live = GetResourceManager()->WrapResource(Unwrap(device), fb); GetResourceManager()->AddLiveResource(id, fb); - m_CreationInfo.m_Framebuffer[live].Init(GetResourceManager(), m_CreationInfo, &info); + VulkanCreationInfo::Framebuffer fbinfo; + fbinfo.Init(GetResourceManager(), m_CreationInfo, &info); + + const VulkanCreationInfo::RenderPass &rpinfo = + m_CreationInfo.m_RenderPass[GetResourceManager()->GetNonDispWrapper(info.renderPass)->id]; + + fbinfo.loadFBs.resize(rpinfo.loadRPs.size()); + + // create a render pass for each subpass that maintains attachment layouts + for(size_t s = 0; s < fbinfo.loadFBs.size(); s++) + { + info.renderPass = Unwrap(rpinfo.loadRPs[s]); + + ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &info, NULL, &fbinfo.loadFBs[s]); + RDCASSERTEQUAL(ret, VK_SUCCESS); + + // handle the loadRP being a duplicate + if(GetResourceManager()->HasWrapper(ToTypedHandle(fbinfo.loadFBs[s]))) + { + // just fetch the existing wrapped object + fbinfo.loadFBs[s] = + (VkFramebuffer)(uint64_t)GetResourceManager()->GetNonDispWrapper(fbinfo.loadFBs[s]); + + // destroy this instance of the duplicate, as we must have matching create/destroy + // calls and there won't be a wrapped resource hanging around to destroy this one. + ObjDisp(device)->DestroyFramebuffer(Unwrap(device), fbinfo.loadFBs[s], NULL); + + // don't need to ReplaceResource as no IDs are involved + } + else + { + ResourceId loadFBid = + GetResourceManager()->WrapResource(Unwrap(device), fbinfo.loadFBs[s]); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(loadFBid, fbinfo.loadFBs[s]); + } + } + + m_CreationInfo.m_Framebuffer[live] = fbinfo; } } } @@ -567,7 +606,30 @@ VkResult WrappedVulkan::vkCreateFramebuffer(VkDevice device, { GetResourceManager()->AddLiveResource(id, *pFramebuffer); - m_CreationInfo.m_Framebuffer[id].Init(GetResourceManager(), m_CreationInfo, &unwrappedInfo); + VulkanCreationInfo::Framebuffer fbinfo; + fbinfo.Init(GetResourceManager(), m_CreationInfo, &unwrappedInfo); + + const VulkanCreationInfo::RenderPass &rpinfo = + m_CreationInfo.m_RenderPass[GetResID(pCreateInfo->renderPass)]; + + fbinfo.loadFBs.resize(rpinfo.loadRPs.size()); + + // create a render pass for each subpass that maintains attachment layouts + for(size_t s = 0; s < fbinfo.loadFBs.size(); s++) + { + unwrappedInfo.renderPass = Unwrap(rpinfo.loadRPs[s]); + + ret = ObjDisp(device)->CreateFramebuffer(Unwrap(device), &unwrappedInfo, NULL, + &fbinfo.loadFBs[s]); + RDCASSERTEQUAL(ret, VK_SUCCESS); + + ResourceId loadFBid = GetResourceManager()->WrapResource(Unwrap(device), fbinfo.loadFBs[s]); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(loadFBid, fbinfo.loadFBs[s]); + } + + m_CreationInfo.m_Framebuffer[id] = fbinfo; } }