From 1f2d43c8709e5fab2f8c3c7de81bdf160b5f6363 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 26 Jun 2017 21:08:21 +0200 Subject: [PATCH] Vulkan: Implement Quad-Buffered stereoscopy support. --- Source/Core/VideoBackends/Vulkan/PostProcessing.cpp | 5 ++++- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 9 +++++++++ Source/Core/VideoBackends/Vulkan/SwapChain.cpp | 8 ++++++-- Source/Core/VideoBackends/Vulkan/SwapChain.h | 2 ++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp b/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp index db8da49499..971de51180 100644 --- a/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp +++ b/Source/Core/VideoBackends/Vulkan/PostProcessing.cpp @@ -41,11 +41,14 @@ void VulkanPostProcessing::BlitFromTexture(const TargetRectangle& dst, const Tar const Texture2D* src_tex, int src_layer, VkRenderPass render_pass) { + // If the source layer is negative we simply copy all available layers. + VkShaderModule geometry_shader = + src_layer < 0 ? g_object_cache->GetPassthroughGeometryShader() : VK_NULL_HANDLE; VkShaderModule fragment_shader = m_fragment_shader != VK_NULL_HANDLE ? m_fragment_shader : m_default_fragment_shader; UtilityShaderDraw draw(g_command_buffer_mgr->GetCurrentCommandBuffer(), g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass, - g_object_cache->GetPassthroughVertexShader(), VK_NULL_HANDLE, + g_object_cache->GetPassthroughVertexShader(), geometry_shader, fragment_shader); // Source is always bound. diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 4800d99424..9a26df8548 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -949,6 +949,10 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r post_processor->BlitFromTexture(left_rect, src_rect, src_tex, 0, render_pass); post_processor->BlitFromTexture(right_rect, src_rect, src_tex, 1, render_pass); } + else if (g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER) + { + post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, -1, render_pass); + } else { post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, 0, render_pass); @@ -1186,6 +1190,11 @@ void Renderer::CheckForConfigChanges() m_swap_chain->SetVSync(g_ActiveConfig.IsVSync()); } + // For quad-buffered stereo we need to change the layer count, so recreate the swap chain. + if (m_swap_chain && + (g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER) != m_swap_chain->IsStereoEnabled()) + ResizeSwapChain(); + // Wipe sampler cache if force texture filtering or anisotropy changes. if (anisotropy_changed || force_texture_filtering_changed) ResetSamplerStates(); diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp index d43a0e4499..21009510bb 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp @@ -320,6 +320,9 @@ bool SwapChain::CreateSwapChain() return false; } + // Select the number of image layers for Quad-Buffered stereoscopy + uint32_t image_layers = g_ActiveConfig.iStereoMode == STEREO_QUADBUFFER ? 2 : 1; + // Store the old/current swap chain when recreating for resize VkSwapchainKHR old_swap_chain = m_swap_chain; @@ -333,7 +336,7 @@ bool SwapChain::CreateSwapChain() m_surface_format.format, m_surface_format.colorSpace, size, - 1, + image_layers, image_usage, VK_SHARING_MODE_EXCLUSIVE, 0, @@ -359,6 +362,7 @@ bool SwapChain::CreateSwapChain() m_width = size.width; m_height = size.height; + m_layers = image_layers; return true; } @@ -400,7 +404,7 @@ bool SwapChain::SetupSwapChainImages() &view, m_width, m_height, - 1}; + m_layers}; res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr, &image.framebuffer); diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.h b/Source/Core/VideoBackends/Vulkan/SwapChain.h index 0ff480d64c..37c3460796 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.h +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.h @@ -32,6 +32,7 @@ public: VkSurfaceKHR GetSurface() const { return m_surface; } VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; } bool IsVSyncEnabled() const { return m_vsync_enabled; } + bool IsStereoEnabled() const { return m_layers == 2; } VkSwapchainKHR GetSwapChain() const { return m_swap_chain; } VkRenderPass GetRenderPass() const { return m_render_pass; } u32 GetWidth() const { return m_width; } @@ -94,6 +95,7 @@ private: u32 m_width = 0; u32 m_height = 0; + u32 m_layers = 0; }; } // namespace Vulkan