summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/Vulkan/Renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/Renderer.cpp')
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.cpp191
1 files changed, 48 insertions, 143 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index 718bdec8d7..dffe3fdd3c 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -21,7 +21,6 @@
#include "VideoBackends/Vulkan/FramebufferManager.h"
#include "VideoBackends/Vulkan/ObjectCache.h"
#include "VideoBackends/Vulkan/PostProcessing.h"
-#include "VideoBackends/Vulkan/RasterFont.h"
#include "VideoBackends/Vulkan/Renderer.h"
#include "VideoBackends/Vulkan/StateTracker.h"
#include "VideoBackends/Vulkan/StreamBuffer.h"
@@ -47,9 +46,9 @@
namespace Vulkan
{
-Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain)
+Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain, float backbuffer_scale)
: ::Renderer(swap_chain ? static_cast<int>(swap_chain->GetWidth()) : 1,
- swap_chain ? static_cast<int>(swap_chain->GetHeight()) : 0,
+ swap_chain ? static_cast<int>(swap_chain->GetHeight()) : 0, backbuffer_scale,
swap_chain ? swap_chain->GetTextureFormat() : AbstractTextureFormat::Undefined),
m_swap_chain(std::move(swap_chain))
{
@@ -89,13 +88,6 @@ bool Renderer::Initialize()
return false;
}
- m_raster_font = std::make_unique<RasterFont>();
- if (!m_raster_font->Initialize())
- {
- PanicAlert("Failed to initialize raster font.");
- return false;
- }
-
// Swap chain render pass.
if (m_swap_chain)
{
@@ -130,8 +122,7 @@ bool Renderer::Initialize()
// Initialize post processing.
m_post_processor = std::make_unique<VulkanPostProcessing>();
- if (!static_cast<VulkanPostProcessing*>(m_post_processor.get())
- ->Initialize(m_raster_font->GetTexture()))
+ if (!static_cast<VulkanPostProcessing*>(m_post_processor.get())->Initialize())
{
PanicAlert("failed to initialize post processor.");
return false;
@@ -232,44 +223,11 @@ Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
static_cast<const VKTexture*>(depth_attachment));
}
-std::tuple<VkBuffer, u32> Renderer::UpdateUtilityUniformBuffer(const void* uniforms,
- u32 uniforms_size)
-{
- StreamBuffer* ubo_buf = g_object_cache->GetUtilityShaderUniformBuffer();
- if (!ubo_buf->ReserveMemory(uniforms_size, g_vulkan_context->GetUniformBufferAlignment()))
- {
- Util::ExecuteCurrentCommandsAndRestoreState(false, true);
- if (!ubo_buf->ReserveMemory(uniforms_size, g_vulkan_context->GetUniformBufferAlignment()))
- {
- PanicAlert("Failed to reserve uniform buffer space for utility draw.");
- return {};
- }
- }
-
- VkBuffer ubo = ubo_buf->GetBuffer();
- u32 ubo_offset = static_cast<u32>(ubo_buf->GetCurrentOffset());
- std::memcpy(ubo_buf->GetCurrentHostPointer(), uniforms, uniforms_size);
- ubo_buf->CommitMemory(uniforms_size);
-
- return std::tie(ubo, ubo_offset);
-}
-
void Renderer::SetPipeline(const AbstractPipeline* pipeline)
{
StateTracker::GetInstance()->SetPipeline(static_cast<const VKPipeline*>(pipeline));
}
-void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
-{
- u32 backbuffer_width = m_swap_chain->GetWidth();
- u32 backbuffer_height = m_swap_chain->GetHeight();
-
- m_raster_font->PrintMultiLineText(m_swap_chain_render_pass, text,
- left * 2.0f / static_cast<float>(backbuffer_width) - 1,
- 1 - top * 2.0f / static_cast<float>(backbuffer_height),
- backbuffer_width, backbuffer_height, color);
-}
-
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
if (type == EFBAccessType::PeekColor)
@@ -577,76 +535,24 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
BindEFBToStateTracker();
}
-void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks)
+void Renderer::Flush()
{
- // Pending/batched EFB pokes should be included in the final image.
- FramebufferManager::GetInstance()->FlushEFBPokes();
-
- auto* xfb_texture = static_cast<VKTexture*>(texture);
+ Util::ExecuteCurrentCommandsAndRestoreState(true, false);
+}
- // End the current render pass.
+void Renderer::BindBackbuffer(const ClearColor& clear_color)
+{
StateTracker::GetInstance()->EndRenderPass();
- StateTracker::GetInstance()->OnEndFrame();
// Handle host window resizes.
CheckForSurfaceChange();
CheckForSurfaceResize();
- // There are a few variables which can alter the final window draw rectangle, and some of them
- // are determined by guest state. Currently, the only way to catch these is to update every frame.
- UpdateDrawRectangle();
-
// Ensure the worker thread is not still submitting a previous command buffer.
// In other words, the last frame has been submitted (otherwise the next call would
// be a race, as the image may not have been consumed yet).
g_command_buffer_mgr->PrepareToSubmitCommandBuffer();
- // Draw to the screen if we have a swap chain.
- if (m_swap_chain)
- {
- DrawScreen(xfb_texture, xfb_region);
-
- // Submit the current command buffer, signaling rendering finished semaphore when it's done
- // Because this final command buffer is rendering to the swap chain, we need to wait for
- // the available semaphore to be signaled before executing the buffer. This final submission
- // can happen off-thread in the background while we're preparing the next frame.
- g_command_buffer_mgr->SubmitCommandBuffer(
- true, m_image_available_semaphore, m_rendering_finished_semaphore,
- m_swap_chain->GetSwapChain(), m_swap_chain->GetCurrentImageIndex());
- }
- else
- {
- // No swap chain, just execute command buffer.
- g_command_buffer_mgr->SubmitCommandBuffer(true);
- }
-
- // NOTE: It is important that no rendering calls are made to the EFB between submitting the
- // (now-previous) frame and after the below config checks are completed. If the target size
- // changes, as the resize methods to not defer the destruction of the framebuffer, the current
- // command buffer will contain references to a now non-existent framebuffer.
-
- // Prep for the next frame (get command buffer ready) before doing anything else.
- BeginFrame();
-
- // 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();
-
- // Clean up stale textures.
- TextureCache::GetInstance()->Cleanup(frameCount);
-}
-
-void Renderer::Flush()
-{
- Util::ExecuteCurrentCommandsAndRestoreState(true, false);
-}
-
-void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region)
-{
VkResult res;
if (!g_command_buffer_mgr->CheckLastPresentFail())
{
@@ -696,49 +602,65 @@ void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region
// Begin render pass for rendering to the swap chain.
VkClearValue clear_value = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
StateTracker::GetInstance()->BeginClearRenderPass(region, &clear_value, 1);
+}
- // Draw
- BlitScreen(m_swap_chain_render_pass, GetTargetRectangle(), xfb_region,
- xfb_texture->GetRawTexIdentifier());
-
- // Draw OSD
- Util::SetViewportAndScissor(g_command_buffer_mgr->GetCurrentCommandBuffer(), 0, 0,
- backbuffer->GetWidth(), backbuffer->GetHeight());
- DrawDebugText();
- OSD::DoCallbacks(OSD::CallbackType::OnFrame);
- OSD::DrawMessages();
-
+void Renderer::PresentBackbuffer()
+{
// End drawing to backbuffer
StateTracker::GetInstance()->EndRenderPass();
+ StateTracker::GetInstance()->OnEndFrame();
// Transition the backbuffer to PRESENT_SRC to ensure all commands drawing
// to it have finished before present.
+ Texture2D* backbuffer = m_swap_chain->GetCurrentTexture();
backbuffer->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
+
+ // Submit the current command buffer, signaling rendering finished semaphore when it's done
+ // Because this final command buffer is rendering to the swap chain, we need to wait for
+ // the available semaphore to be signaled before executing the buffer. This final submission
+ // can happen off-thread in the background while we're preparing the next frame.
+ g_command_buffer_mgr->SubmitCommandBuffer(
+ true, m_image_available_semaphore, m_rendering_finished_semaphore,
+ m_swap_chain->GetSwapChain(), m_swap_chain->GetCurrentImageIndex());
+
+ BeginFrame();
}
-void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_rect,
- const TargetRectangle& src_rect, const Texture2D* src_tex)
+void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc)
{
+ const TargetRectangle target_rc = GetTargetRectangle();
+
VulkanPostProcessing* post_processor = static_cast<VulkanPostProcessing*>(m_post_processor.get());
if (g_ActiveConfig.stereo_mode == StereoMode::SBS ||
g_ActiveConfig.stereo_mode == StereoMode::TAB)
{
TargetRectangle left_rect;
TargetRectangle right_rect;
- std::tie(left_rect, right_rect) = ConvertStereoRectangle(dst_rect);
+ std::tie(left_rect, right_rect) = ConvertStereoRectangle(target_rc);
- post_processor->BlitFromTexture(left_rect, src_rect, src_tex, 0, render_pass);
- post_processor->BlitFromTexture(right_rect, src_rect, src_tex, 1, render_pass);
+ post_processor->BlitFromTexture(left_rect, rc,
+ static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
+ 0, m_swap_chain_render_pass);
+ post_processor->BlitFromTexture(right_rect, rc,
+ static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
+ 1, m_swap_chain_render_pass);
}
else if (g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer)
{
- post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, -1, render_pass);
+ post_processor->BlitFromTexture(target_rc, rc,
+ static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
+ -1, m_swap_chain_render_pass);
}
else
{
- post_processor->BlitFromTexture(dst_rect, src_rect, src_tex, 0, render_pass);
+ post_processor->BlitFromTexture(target_rc, rc,
+ static_cast<const VKTexture*>(texture)->GetRawTexIdentifier(),
+ 0, m_swap_chain_render_pass);
}
+
+ // The post-processor uses the old-style Vulkan draws, which mess with the tracked state.
+ StateTracker::GetInstance()->SetPendingRebind();
}
void Renderer::CheckForSurfaceChange()
@@ -787,36 +709,20 @@ void Renderer::CheckForSurfaceResize()
OnSwapChainResized();
}
-void Renderer::CheckForConfigChanges()
+void Renderer::OnConfigChanged(u32 bits)
{
- // Save the video config so we can compare against to determine which settings have changed.
- const u32 old_multisamples = g_ActiveConfig.iMultisamples;
- const int old_anisotropy = g_ActiveConfig.iMaxAnisotropy;
- const bool old_force_filtering = g_ActiveConfig.bForceFiltering;
-
- // Copy g_Config to g_ActiveConfig.
- // NOTE: This can potentially race with the UI thread, however if it does, the changes will be
- // delayed until the next time CheckForConfigChanges is called.
- UpdateActiveConfig();
-
- // Determine which (if any) settings have changed.
- const bool multisamples_changed = old_multisamples != g_ActiveConfig.iMultisamples;
- const bool anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy;
- const bool force_texture_filtering_changed =
- old_force_filtering != g_ActiveConfig.bForceFiltering;
-
// Update texture cache settings with any changed options.
TextureCache::GetInstance()->OnConfigChanged(g_ActiveConfig);
// Handle settings that can cause the EFB framebuffer to change.
- if (CalculateTargetSize() || multisamples_changed)
+ if (bits & CONFIG_CHANGE_BIT_TARGET_SIZE)
RecreateEFBFramebuffer();
// MSAA samples changed, we need to recreate the EFB render pass.
// If the stereoscopy mode changed, we need to recreate the buffers as well.
// SSAA changed on/off, we have to recompile shaders.
// Changing stereoscopy from off<->on also requires shaders to be recompiled.
- if (CheckForHostConfigChanges())
+ if (bits & (CONFIG_CHANGE_BIT_HOST_CONFIG | CONFIG_CHANGE_BIT_MULTISAMPLES))
{
RecreateEFBFramebuffer();
RecompileShaders();
@@ -826,22 +732,21 @@ void Renderer::CheckForConfigChanges()
}
// For vsync, we need to change the present mode, which means recreating the swap chain.
- if (m_swap_chain && g_ActiveConfig.IsVSync() != m_swap_chain->IsVSyncEnabled())
+ if (m_swap_chain && bits & CONFIG_CHANGE_BIT_VSYNC)
{
g_command_buffer_mgr->WaitForGPUIdle();
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.stereo_mode == StereoMode::QuadBuffer) != m_swap_chain->IsStereoEnabled())
+ if (m_swap_chain && bits & CONFIG_CHANGE_BIT_STEREO_MODE)
{
g_command_buffer_mgr->WaitForGPUIdle();
m_swap_chain->RecreateSwapChain();
}
// Wipe sampler cache if force texture filtering or anisotropy changes.
- if (anisotropy_changed || force_texture_filtering_changed)
+ if (bits & (CONFIG_CHANGE_BIT_ANISOTROPY | CONFIG_CHANGE_BIT_FORCE_TEXTURE_FILTERING))
ResetSamplerStates();
// Check for a changed post-processing shader and recompile if needed.