From 01eb50089ce1a638726d4823510da6ebbad76d25 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 6 Jul 2017 16:03:30 +0100 Subject: [PATCH] Make sure pipelines are used with the right subpass in a partial replay * When we do a partial replay we truncate the render pass to only have one subpass, but pipelines are created for a particular subpass. So at creation time we create a new pipeline that points to subpass 0 so we can use it later together with the truncated render passes. --- renderdoc/driver/vulkan/vk_core.cpp | 2 +- renderdoc/driver/vulkan/vk_debug.cpp | 4 ++-- renderdoc/driver/vulkan/vk_info.h | 4 ++++ renderdoc/driver/vulkan/vk_state.cpp | 13 ++++++++----- renderdoc/driver/vulkan/vk_state.h | 2 +- .../driver/vulkan/wrappers/vk_misc_funcs.cpp | 3 ++- .../vulkan/wrappers/vk_shader_funcs.cpp | 19 ++++++++++++++++++- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index bf3ab20ef..93173b610 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -2437,7 +2437,7 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay else if(m_RenderState.compute.pipeline != ResourceId()) { // if we had a compute pipeline, need to bind that - m_RenderState.BindPipeline(cmd, VulkanRenderState::BindCompute); + m_RenderState.BindPipeline(cmd, VulkanRenderState::BindCompute, false); } } diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 3997ef25b..cb5de2e46 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -4982,7 +4982,7 @@ struct VulkanQuadOverdrawCallback : public VulkanDrawcallCallback pipestate.graphics.descSets[pipe.first].descSet = GetResID(m_pDebug->m_QuadDescSet); if(cmd) - pipestate.BindPipeline(cmd, VulkanRenderState::BindGraphics); + pipestate.BindPipeline(cmd, VulkanRenderState::BindGraphics, false); } bool PostDraw(uint32_t eid, VkCommandBuffer cmd) @@ -4994,7 +4994,7 @@ struct VulkanQuadOverdrawCallback : public VulkanDrawcallCallback m_pDriver->GetRenderState() = m_PrevState; RDCASSERT(cmd); - m_pDriver->GetRenderState().BindPipeline(cmd, VulkanRenderState::BindGraphics); + m_pDriver->GetRenderState().BindPipeline(cmd, VulkanRenderState::BindGraphics, false); return true; } diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 447721164..20c072a2b 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -89,6 +89,10 @@ struct VulkanCreationInfo ResourceId renderpass; uint32_t subpass; + // a variant of the pipeline that uses subpass 0, used for when we are replaying in isolation. + // See loadRPs in the RenderPass info + VkPipeline subpass0pipe; + // VkGraphicsPipelineCreateInfo VkPipelineCreateFlags flags; diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index 30d8bb0e2..269e4c90b 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -106,7 +106,7 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, Pipeli }; ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); - BindPipeline(cmd, binding); + BindPipeline(cmd, binding, true); if(ibuffer.buf != ResourceId()) ObjDisp(cmd)->CmdBindIndexBuffer( @@ -120,13 +120,16 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, Pipeli &vbuffers[i].offs); } -void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding binding) +void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0) { if(graphics.pipeline != ResourceId() && binding == BindGraphics) { - ObjDisp(cmd)->CmdBindPipeline( - Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, - Unwrap(GetResourceManager()->GetCurrentHandle(graphics.pipeline))); + VkPipeline pipe = GetResourceManager()->GetCurrentHandle(graphics.pipeline); + + if(subpass0 && m_CreationInfo->m_Pipeline[graphics.pipeline].subpass0pipe != VK_NULL_HANDLE) + pipe = m_CreationInfo->m_Pipeline[graphics.pipeline].subpass0pipe; + + ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(pipe)); ResourceId pipeLayoutId = m_CreationInfo->m_Pipeline[graphics.pipeline].layout; VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle(pipeLayoutId); diff --git a/renderdoc/driver/vulkan/vk_state.h b/renderdoc/driver/vulkan/vk_state.h index 5223ad177..c379eb758 100644 --- a/renderdoc/driver/vulkan/vk_state.h +++ b/renderdoc/driver/vulkan/vk_state.h @@ -44,7 +44,7 @@ struct VulkanRenderState VulkanRenderState &operator=(const VulkanRenderState &o); void BeginRenderPassAndApplyState(VkCommandBuffer cmd, PipelineBinding binding); void EndRenderPass(VkCommandBuffer cmd); - void BindPipeline(VkCommandBuffer cmd, PipelineBinding binding); + void BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0); // dynamic state vector views; diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index 5f86b8505..96db7c52e 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -656,7 +656,8 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass(Serialiser *localSerialiser, Vk { MakeSubpassLoadRP(loadInfo, &info, s); - ret = ObjDisp(device)->CreateRenderPass(Unwrap(device), &info, NULL, &rpinfo.loadRPs[s]); + ret = + ObjDisp(device)->CreateRenderPass(Unwrap(device), &loadInfo, NULL, &rpinfo.loadRPs[s]); RDCASSERTEQUAL(ret, VK_SUCCESS); // handle the loadRP being a duplicate diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index 6a494c661..e3aa7e807 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -342,7 +342,24 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( live = GetResourceManager()->WrapResource(Unwrap(device), pipe); GetResourceManager()->AddLiveResource(id, pipe); - m_CreationInfo.m_Pipeline[live].Init(GetResourceManager(), m_CreationInfo, &info); + VulkanCreationInfo::Pipeline &pipeInfo = m_CreationInfo.m_Pipeline[live]; + + pipeInfo.Init(GetResourceManager(), m_CreationInfo, &info); + + ResourceId renderPassID = GetResourceManager()->GetNonDispWrapper(info.renderPass)->id; + + info.renderPass = Unwrap(m_CreationInfo.m_RenderPass[renderPassID].loadRPs[info.subpass]); + info.subpass = 0; + + ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, + &info, NULL, &pipeInfo.subpass0pipe); + RDCASSERTEQUAL(ret, VK_SUCCESS); + + ResourceId subpass0id = + GetResourceManager()->WrapResource(Unwrap(device), pipeInfo.subpass0pipe); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(subpass0id, pipeInfo.subpass0pipe); } } }