From 887e3830bac95b0418201af337756564c89963d0 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 9 Feb 2018 21:41:31 +1000 Subject: VideoBackends: Restore the framebuffer as part of the API state It's not often we switch out to draw to the EFB anyway. --- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Source/Core/VideoBackends/Vulkan/Renderer.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index e4a7401c54..12de136162 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -1036,6 +1036,9 @@ void Renderer::ResetAPIState() void Renderer::RestoreAPIState() { + StateTracker::GetInstance()->EndRenderPass(); + BindEFBToStateTracker(); + // Instruct the state tracker to re-bind everything before the next draw StateTracker::GetInstance()->SetPendingRebind(); } -- cgit v1.2.3 From 4c24a697106471b33973da619a43167c947276aa Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 21 Jan 2018 20:22:45 +1000 Subject: VideoCommon: Add support for Abstract Framebuffers --- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 86 ++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/Renderer.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 12de136162..588e4b0919 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -192,6 +192,14 @@ std::unique_ptr Renderer::CreatePipeline(const AbstractPipelin return VKPipeline::Create(config); } +std::unique_ptr +Renderer::CreateFramebuffer(const AbstractTexture* color_attachment, + const AbstractTexture* depth_attachment) +{ + return VKFramebuffer::Create(static_cast(color_attachment), + static_cast(depth_attachment)); +} + std::tuple Renderer::UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size) { @@ -593,8 +601,9 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha // Fastest path: Use a render pass to clear the buffers. if (use_clear_render_pass) { - VkClearValue clear_values[2] = {clear_color_value, clear_depth_value}; - StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values); + const std::array clear_values = {{clear_color_value, clear_depth_value}}; + StateTracker::GetInstance()->BeginClearRenderPass(target_vk_rc, clear_values.data(), + static_cast(clear_values.size())); return; } @@ -743,6 +752,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region // Restore the EFB color texture to color attachment ready for rendering the next frame. FramebufferManager::GetInstance()->GetEFBColorTexture()->TransitionToLayout( g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + RestoreAPIState(); // Determine what (if anything) has changed in the config. CheckForConfigChanges(); @@ -792,6 +802,9 @@ void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region backbuffer->OverrideImageLayout(VK_IMAGE_LAYOUT_UNDEFINED); backbuffer->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + m_current_framebuffer = nullptr; + m_current_framebuffer_width = backbuffer->GetWidth(); + m_current_framebuffer_height = backbuffer->GetHeight(); // Begin render pass for rendering to the swap chain. VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; @@ -1010,6 +1023,9 @@ void Renderer::BindEFBToStateTracker() FramebufferManager::GetInstance()->GetEFBFramebuffer(), framebuffer_size); StateTracker::GetInstance()->SetMultisamplingstate( FramebufferManager::GetInstance()->GetEFBMultisamplingState()); + m_current_framebuffer = nullptr; + m_current_framebuffer_width = FramebufferManager::GetInstance()->GetEFBWidth(); + m_current_framebuffer_height = FramebufferManager::GetInstance()->GetEFBHeight(); } void Renderer::RecreateEFBFramebuffer() @@ -1037,12 +1053,78 @@ void Renderer::ResetAPIState() void Renderer::RestoreAPIState() { StateTracker::GetInstance()->EndRenderPass(); + if (m_current_framebuffer) + static_cast(m_current_framebuffer)->TransitionForSample(); + BindEFBToStateTracker(); // Instruct the state tracker to re-bind everything before the next draw StateTracker::GetInstance()->SetPendingRebind(); } +void Renderer::BindFramebuffer(const VKFramebuffer* fb) +{ + const VkRect2D render_area = {static_cast(fb->GetWidth()), + static_cast(fb->GetHeight())}; + + StateTracker::GetInstance()->EndRenderPass(); + if (m_current_framebuffer) + static_cast(m_current_framebuffer)->TransitionForSample(); + + fb->TransitionForRender(); + StateTracker::GetInstance()->SetFramebuffer(fb->GetFB(), render_area); + StateTracker::GetInstance()->SetRenderPass(fb->GetLoadRenderPass(), fb->GetClearRenderPass()); + m_current_framebuffer = fb; + m_current_framebuffer_width = fb->GetWidth(); + m_current_framebuffer_height = fb->GetHeight(); +} + +void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer) +{ + const VKFramebuffer* vkfb = static_cast(framebuffer); + BindFramebuffer(vkfb); + StateTracker::GetInstance()->BeginRenderPass(); +} + +void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) +{ + const VKFramebuffer* vkfb = static_cast(framebuffer); + BindFramebuffer(vkfb); + + // If we're discarding, begin the discard pass, then switch to a load pass. + // This way if the command buffer is flushed, we don't start another discard pass. + StateTracker::GetInstance()->SetRenderPass(vkfb->GetDiscardRenderPass(), + vkfb->GetClearRenderPass()); + StateTracker::GetInstance()->BeginRenderPass(); + StateTracker::GetInstance()->SetRenderPass(vkfb->GetLoadRenderPass(), vkfb->GetClearRenderPass()); +} + +void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer, + const ClearColor& color_value, float depth_value) +{ + const VKFramebuffer* vkfb = static_cast(framebuffer); + BindFramebuffer(vkfb); + + const VkRect2D render_area = {static_cast(vkfb->GetWidth()), + static_cast(vkfb->GetHeight())}; + std::array clear_values; + u32 num_clear_values = 0; + if (vkfb->GetColorFormat() != AbstractTextureFormat::Undefined) + { + std::memcpy(clear_values[num_clear_values].color.float32, color_value.data(), + sizeof(clear_values[num_clear_values].color.float32)); + num_clear_values++; + } + if (vkfb->GetDepthFormat() != AbstractTextureFormat::Undefined) + { + clear_values[num_clear_values].depthStencil.depth = depth_value; + clear_values[num_clear_values].depthStencil.stencil = 0; + num_clear_values++; + } + StateTracker::GetInstance()->BeginClearRenderPass(render_area, clear_values.data(), + num_clear_values); +} + void Renderer::SetRasterizationState(const RasterizationState& state) { StateTracker::GetInstance()->SetRasterizationState(state); -- cgit v1.2.3