diff options
| author | Scott Mansell <phiren@gmail.com> | 2023-02-09 19:59:16 +1300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-09 19:59:16 +1300 |
| commit | ccf92a3e56764d6378c436a8040519a5bffc3372 (patch) | |
| tree | e2b330b225044e1901e77a6ed147cf21b9d7ac0e /Source/Core/VideoCommon/FramebufferManager.cpp | |
| parent | 72b22ef0a54f841b1c52d49cf0e00d3b12c29ac7 (diff) | |
| parent | 5c1b3ac61d7e660a9d1c206dbd0e615d637d3272 (diff) | |
Merge pull request #11522 from phire/KillRendererWithFire
Kill Renderer (with phire)
Diffstat (limited to 'Source/Core/VideoCommon/FramebufferManager.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/FramebufferManager.cpp | 332 |
1 files changed, 198 insertions, 134 deletions
diff --git a/Source/Core/VideoCommon/FramebufferManager.cpp b/Source/Core/VideoCommon/FramebufferManager.cpp index f025b2dfde..4bdc3616a9 100644 --- a/Source/Core/VideoCommon/FramebufferManager.cpp +++ b/Source/Core/VideoCommon/FramebufferManager.cpp @@ -10,14 +10,18 @@ #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Core/Config/GraphicsSettings.h" +#include "Core/System.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractShader.h" #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/AbstractTexture.h" +#include "VideoCommon/BPFunctions.h" #include "VideoCommon/DriverDetails.h" #include "VideoCommon/FramebufferShaderGen.h" -#include "VideoCommon/RenderBase.h" +#include "VideoCommon/PixelShaderManager.h" +#include "VideoCommon/Present.h" #include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoConfig.h" @@ -27,7 +31,9 @@ constexpr size_t MAX_POKE_VERTICES = 32768; std::unique_ptr<FramebufferManager> g_framebuffer_manager; -FramebufferManager::FramebufferManager() = default; +FramebufferManager::FramebufferManager() : m_prev_efb_format(PixelFormat::INVALID_FMT) +{ +} FramebufferManager::~FramebufferManager() { @@ -78,6 +84,8 @@ bool FramebufferManager::Initialize() return false; } + m_end_of_frame_event = AfterFrameEvent::Register([this] { EndOfFrame(); }, "FramebufferManager"); + return true; } @@ -141,18 +149,16 @@ static u32 CalculateEFBLayers() return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? 2 : 1; } -TextureConfig FramebufferManager::GetEFBColorTextureConfig() +TextureConfig FramebufferManager::GetEFBColorTextureConfig(u32 width, u32 height) { - return TextureConfig(g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), 1, - CalculateEFBLayers(), g_ActiveConfig.iMultisamples, GetEFBColorFormat(), - AbstractTextureFlag_RenderTarget); + return TextureConfig(width, height, 1, CalculateEFBLayers(), g_ActiveConfig.iMultisamples, + GetEFBColorFormat(), AbstractTextureFlag_RenderTarget); } -TextureConfig FramebufferManager::GetEFBDepthTextureConfig() +TextureConfig FramebufferManager::GetEFBDepthTextureConfig(u32 width, u32 height) { - return TextureConfig(g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(), 1, - CalculateEFBLayers(), g_ActiveConfig.iMultisamples, GetEFBDepthFormat(), - AbstractTextureFlag_RenderTarget); + return TextureConfig(width, height, 1, CalculateEFBLayers(), g_ActiveConfig.iMultisamples, + GetEFBDepthFormat(), AbstractTextureFlag_RenderTarget); } FramebufferState FramebufferManager::GetEFBFramebufferState() const @@ -165,23 +171,78 @@ FramebufferState FramebufferManager::GetEFBFramebufferState() const return ret; } +MathUtil::Rectangle<int> +FramebufferManager::ConvertEFBRectangle(const MathUtil::Rectangle<int>& rc) const +{ + MathUtil::Rectangle<int> result; + result.left = EFBToScaledX(rc.left); + result.top = EFBToScaledY(rc.top); + result.right = EFBToScaledX(rc.right); + result.bottom = EFBToScaledY(rc.bottom); + return result; +} + +unsigned int FramebufferManager::GetEFBScale() const +{ + return m_efb_scale; +} + +int FramebufferManager::EFBToScaledX(int x) const +{ + return x * static_cast<int>(m_efb_scale); +} + +int FramebufferManager::EFBToScaledY(int y) const +{ + return y * static_cast<int>(m_efb_scale); +} + +float FramebufferManager::EFBToScaledXf(float x) const +{ + return x * ((float)GetEFBWidth() / (float)EFB_WIDTH); +} + +float FramebufferManager::EFBToScaledYf(float y) const +{ + return y * ((float)GetEFBHeight() / (float)EFB_HEIGHT); +} + +std::tuple<u32, u32> FramebufferManager::CalculateTargetSize() +{ + if (g_ActiveConfig.iEFBScale == EFB_SCALE_AUTO_INTEGRAL) + m_efb_scale = g_presenter->AutoIntegralScale(); + else + m_efb_scale = g_ActiveConfig.iEFBScale; + + const u32 max_size = g_ActiveConfig.backend_info.MaxTextureSize; + if (max_size < EFB_WIDTH * m_efb_scale) + m_efb_scale = max_size / EFB_WIDTH; + + u32 new_efb_width = std::max(EFB_WIDTH * static_cast<int>(m_efb_scale), 1u); + u32 new_efb_height = std::max(EFB_HEIGHT * static_cast<int>(m_efb_scale), 1u); + + return std::make_tuple(new_efb_width, new_efb_height); +} + bool FramebufferManager::CreateEFBFramebuffer() { - const TextureConfig efb_color_texture_config = GetEFBColorTextureConfig(); - const TextureConfig efb_depth_texture_config = GetEFBDepthTextureConfig(); + auto [width, height] = CalculateTargetSize(); + + const TextureConfig efb_color_texture_config = GetEFBColorTextureConfig(width, height); + const TextureConfig efb_depth_texture_config = GetEFBDepthTextureConfig(width, height); // We need a second texture to swap with for changing pixel formats - m_efb_color_texture = g_renderer->CreateTexture(efb_color_texture_config, "EFB color texture"); - m_efb_depth_texture = g_renderer->CreateTexture(efb_depth_texture_config, "EFB depth texture"); + m_efb_color_texture = g_gfx->CreateTexture(efb_color_texture_config, "EFB color texture"); + m_efb_depth_texture = g_gfx->CreateTexture(efb_depth_texture_config, "EFB depth texture"); m_efb_convert_color_texture = - g_renderer->CreateTexture(efb_color_texture_config, "EFB convert color texture"); + g_gfx->CreateTexture(efb_color_texture_config, "EFB convert color texture"); if (!m_efb_color_texture || !m_efb_depth_texture || !m_efb_convert_color_texture) return false; m_efb_framebuffer = - g_renderer->CreateFramebuffer(m_efb_color_texture.get(), m_efb_depth_texture.get()); + g_gfx->CreateFramebuffer(m_efb_color_texture.get(), m_efb_depth_texture.get()); m_efb_convert_framebuffer = - g_renderer->CreateFramebuffer(m_efb_convert_color_texture.get(), m_efb_depth_texture.get()); + g_gfx->CreateFramebuffer(m_efb_convert_color_texture.get(), m_efb_depth_texture.get()); if (!m_efb_framebuffer || !m_efb_convert_framebuffer) return false; @@ -191,7 +252,7 @@ bool FramebufferManager::CreateEFBFramebuffer() u32 flags = 0; if (!g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve) flags |= AbstractTextureFlag_RenderTarget; - m_efb_resolve_color_texture = g_renderer->CreateTexture( + m_efb_resolve_color_texture = g_gfx->CreateTexture( TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1, efb_color_texture_config.layers, 1, efb_color_texture_config.format, flags), "EFB color resolve texture"); @@ -201,7 +262,7 @@ bool FramebufferManager::CreateEFBFramebuffer() if (!g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve) { m_efb_color_resolve_framebuffer = - g_renderer->CreateFramebuffer(m_efb_resolve_color_texture.get(), nullptr); + g_gfx->CreateFramebuffer(m_efb_resolve_color_texture.get(), nullptr); if (!m_efb_color_resolve_framebuffer) return false; } @@ -210,7 +271,7 @@ bool FramebufferManager::CreateEFBFramebuffer() // We also need one to convert the D24S8 to R32F if that is being used (Adreno). if (g_ActiveConfig.MultisamplingEnabled() || GetEFBDepthFormat() != AbstractTextureFormat::R32F) { - m_efb_depth_resolve_texture = g_renderer->CreateTexture( + m_efb_depth_resolve_texture = g_gfx->CreateTexture( TextureConfig(efb_depth_texture_config.width, efb_depth_texture_config.height, 1, efb_depth_texture_config.layers, 1, GetEFBDepthCopyFormat(), AbstractTextureFlag_RenderTarget), @@ -219,15 +280,15 @@ bool FramebufferManager::CreateEFBFramebuffer() return false; m_efb_depth_resolve_framebuffer = - g_renderer->CreateFramebuffer(m_efb_depth_resolve_texture.get(), nullptr); + g_gfx->CreateFramebuffer(m_efb_depth_resolve_texture.get(), nullptr); if (!m_efb_depth_resolve_framebuffer) return false; } // Clear the renderable textures out. - g_renderer->SetAndClearFramebuffer( - m_efb_framebuffer.get(), {{0.0f, 0.0f, 0.0f, 0.0f}}, - g_ActiveConfig.backend_info.bSupportsReversedDepthRange ? 1.0f : 0.0f); + g_gfx->SetAndClearFramebuffer(m_efb_framebuffer.get(), {{0.0f, 0.0f, 0.0f, 0.0f}}, + g_ActiveConfig.backend_info.bSupportsReversedDepthRange ? 1.0f : + 0.0f); return true; } @@ -245,7 +306,7 @@ void FramebufferManager::DestroyEFBFramebuffer() void FramebufferManager::BindEFBFramebuffer() { - g_renderer->SetFramebuffer(m_efb_framebuffer.get()); + g_gfx->SetFramebuffer(m_efb_framebuffer.get()); } AbstractTexture* FramebufferManager::ResolveEFBColorTexture(const MathUtil::Rectangle<int>& region) @@ -270,15 +331,15 @@ AbstractTexture* FramebufferManager::ResolveEFBColorTexture(const MathUtil::Rect else { m_efb_color_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); - g_renderer->SetAndDiscardFramebuffer(m_efb_color_resolve_framebuffer.get()); - g_renderer->SetPipeline(m_efb_color_resolve_pipeline.get()); - g_renderer->SetTexture(0, m_efb_color_texture.get()); - g_renderer->SetSamplerState(0, RenderState::GetPointSamplerState()); - g_renderer->SetViewportAndScissor(clamped_region); - g_renderer->Draw(0, 3); + g_gfx->BeginUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(m_efb_color_resolve_framebuffer.get()); + g_gfx->SetPipeline(m_efb_color_resolve_pipeline.get()); + g_gfx->SetTexture(0, m_efb_color_texture.get()); + g_gfx->SetSamplerState(0, RenderState::GetPointSamplerState()); + g_gfx->SetViewportAndScissor(clamped_region); + g_gfx->Draw(0, 3); m_efb_resolve_color_texture->FinishedRendering(); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); } m_efb_resolve_color_texture->FinishedRendering(); return m_efb_resolve_color_texture.get(); @@ -298,16 +359,16 @@ AbstractTexture* FramebufferManager::ResolveEFBDepthTexture(const MathUtil::Rect clamped_region.ClampUL(0, 0, GetEFBWidth(), GetEFBHeight()); m_efb_depth_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); - g_renderer->SetAndDiscardFramebuffer(m_efb_depth_resolve_framebuffer.get()); - g_renderer->SetPipeline(IsEFBMultisampled() ? m_efb_depth_resolve_pipeline.get() : - m_efb_depth_cache.copy_pipeline.get()); - g_renderer->SetTexture(0, m_efb_depth_texture.get()); - g_renderer->SetSamplerState(0, RenderState::GetPointSamplerState()); - g_renderer->SetViewportAndScissor(clamped_region); - g_renderer->Draw(0, 3); + g_gfx->BeginUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(m_efb_depth_resolve_framebuffer.get()); + g_gfx->SetPipeline(IsEFBMultisampled() ? m_efb_depth_resolve_pipeline.get() : + m_efb_depth_cache.copy_pipeline.get()); + g_gfx->SetTexture(0, m_efb_depth_texture.get()); + g_gfx->SetSamplerState(0, RenderState::GetPointSamplerState()); + g_gfx->SetViewportAndScissor(clamped_region); + g_gfx->Draw(0, 3); m_efb_depth_resolve_texture->FinishedRendering(); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); return m_efb_depth_resolve_texture.get(); } @@ -322,17 +383,17 @@ bool FramebufferManager::ReinterpretPixelData(EFBReinterpretType convtype) // buffer, which we want to preserve. If we find this to be hindering performance in the // future (e.g. on mobile/tilers), it may be worth discarding only the color buffer. m_efb_color_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); - g_renderer->SetFramebuffer(m_efb_convert_framebuffer.get()); - g_renderer->SetViewportAndScissor(m_efb_framebuffer->GetRect()); - g_renderer->SetPipeline(m_format_conversion_pipelines[static_cast<u32>(convtype)].get()); - g_renderer->SetTexture(0, m_efb_color_texture.get()); - g_renderer->Draw(0, 3); + g_gfx->BeginUtilityDrawing(); + g_gfx->SetFramebuffer(m_efb_convert_framebuffer.get()); + g_gfx->SetViewportAndScissor(m_efb_framebuffer->GetRect()); + g_gfx->SetPipeline(m_format_conversion_pipelines[static_cast<u32>(convtype)].get()); + g_gfx->SetTexture(0, m_efb_color_texture.get()); + g_gfx->Draw(0, 3); // And swap the framebuffers around, so we do new drawing to the converted framebuffer. std::swap(m_efb_color_texture, m_efb_convert_color_texture); std::swap(m_efb_framebuffer, m_efb_convert_framebuffer); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); InvalidatePeekCache(true); return true; } @@ -342,7 +403,7 @@ bool FramebufferManager::CompileConversionPipelines() for (u32 i = 0; i < NUM_EFB_REINTERPRET_TYPES; i++) { EFBReinterpretType convtype = static_cast<EFBReinterpretType>(i); - std::unique_ptr<AbstractShader> pixel_shader = g_renderer->CreateShaderFromSource( + std::unique_ptr<AbstractShader> pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateFormatConversionShader(convtype, GetEFBSamples()), fmt::format("Framebuffer conversion pixel shader {}", convtype)); @@ -358,7 +419,7 @@ bool FramebufferManager::CompileConversionPipelines() config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = GetEFBFramebufferState(); config.usage = AbstractPipelineUsage::Utility; - m_format_conversion_pipelines[i] = g_renderer->CreatePipeline(config); + m_format_conversion_pipelines[i] = g_gfx->CreatePipeline(config); if (!m_format_conversion_pipelines[i]) return false; } @@ -493,7 +554,7 @@ void FramebufferManager::RefreshPeekCache() if (flush_command_buffer) { - g_renderer->Flush(); + g_gfx->Flush(); } } @@ -562,33 +623,33 @@ bool FramebufferManager::CompileReadbackPipelines() config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = RenderState::GetColorFramebufferState(GetEFBColorFormat()); config.usage = AbstractPipelineUsage::Utility; - m_efb_color_cache.copy_pipeline = g_renderer->CreatePipeline(config); + m_efb_color_cache.copy_pipeline = g_gfx->CreatePipeline(config); if (!m_efb_color_cache.copy_pipeline) return false; // same for depth, except different format config.framebuffer_state.color_texture_format = GetEFBDepthCopyFormat(); - m_efb_depth_cache.copy_pipeline = g_renderer->CreatePipeline(config); + m_efb_depth_cache.copy_pipeline = g_gfx->CreatePipeline(config); if (!m_efb_depth_cache.copy_pipeline) return false; if (IsEFBMultisampled()) { - auto depth_resolve_shader = g_renderer->CreateShaderFromSource( + auto depth_resolve_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateResolveDepthPixelShader(GetEFBSamples()), "Depth resolve pixel shader"); if (!depth_resolve_shader) return false; config.pixel_shader = depth_resolve_shader.get(); - m_efb_depth_resolve_pipeline = g_renderer->CreatePipeline(config); + m_efb_depth_resolve_pipeline = g_gfx->CreatePipeline(config); if (!m_efb_depth_resolve_pipeline) return false; if (!g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve) { config.framebuffer_state.color_texture_format = GetEFBColorFormat(); - auto color_resolve_shader = g_renderer->CreateShaderFromSource( + auto color_resolve_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateResolveColorPixelShader(GetEFBSamples()), "Color resolve pixel shader"); @@ -596,14 +657,14 @@ bool FramebufferManager::CompileReadbackPipelines() return false; config.pixel_shader = color_resolve_shader.get(); - m_efb_color_resolve_pipeline = g_renderer->CreatePipeline(config); + m_efb_color_resolve_pipeline = g_gfx->CreatePipeline(config); if (!m_efb_color_resolve_pipeline) return false; } } // EFB restore pipeline - auto restore_shader = g_renderer->CreateShaderFromSource( + auto restore_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateEFBRestorePixelShader(), "EFB restore pixel shader"); if (!restore_shader) @@ -614,7 +675,7 @@ bool FramebufferManager::CompileReadbackPipelines() config.framebuffer_state.per_sample_shading = false; config.vertex_shader = g_shader_cache->GetScreenQuadVertexShader(); config.pixel_shader = restore_shader.get(); - m_efb_restore_pipeline = g_renderer->CreatePipeline(config); + m_efb_restore_pipeline = g_gfx->CreatePipeline(config); if (!m_efb_restore_pipeline) return false; @@ -630,17 +691,17 @@ void FramebufferManager::DestroyReadbackPipelines() bool FramebufferManager::CreateReadbackFramebuffer() { - if (g_renderer->GetEFBScale() != 1) + if (GetEFBScale() != 1) { const TextureConfig color_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), AbstractTextureFlag_RenderTarget); - m_efb_color_cache.texture = g_renderer->CreateTexture(color_config, "EFB color cache"); + m_efb_color_cache.texture = g_gfx->CreateTexture(color_config, "EFB color cache"); if (!m_efb_color_cache.texture) return false; m_efb_color_cache.framebuffer = - g_renderer->CreateFramebuffer(m_efb_color_cache.texture.get(), nullptr); + g_gfx->CreateFramebuffer(m_efb_color_cache.texture.get(), nullptr); if (!m_efb_color_cache.framebuffer) return false; } @@ -651,27 +712,27 @@ bool FramebufferManager::CreateReadbackFramebuffer() (IsUsingTiledEFBCache() && !g_ActiveConfig.backend_info.bSupportsPartialDepthCopies) || !AbstractTexture::IsCompatibleDepthAndColorFormats(m_efb_depth_texture->GetFormat(), GetEFBDepthCopyFormat()) || - g_renderer->GetEFBScale() != 1) + GetEFBScale() != 1) { const TextureConfig depth_config(IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_WIDTH, IsUsingTiledEFBCache() ? m_efb_cache_tile_size : EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), AbstractTextureFlag_RenderTarget); - m_efb_depth_cache.texture = g_renderer->CreateTexture(depth_config, "EFB depth cache"); + m_efb_depth_cache.texture = g_gfx->CreateTexture(depth_config, "EFB depth cache"); if (!m_efb_depth_cache.texture) return false; m_efb_depth_cache.framebuffer = - g_renderer->CreateFramebuffer(m_efb_depth_cache.texture.get(), nullptr); + g_gfx->CreateFramebuffer(m_efb_depth_cache.texture.get(), nullptr); if (!m_efb_depth_cache.framebuffer) return false; } // Staging texture use the full EFB dimensions, as this is the buffer for the whole cache. - m_efb_color_cache.readback_texture = g_renderer->CreateStagingTexture( + m_efb_color_cache.readback_texture = g_gfx->CreateStagingTexture( StagingTextureType::Mutable, TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBColorFormat(), 0)); - m_efb_depth_cache.readback_texture = g_renderer->CreateStagingTexture( + m_efb_depth_cache.readback_texture = g_gfx->CreateStagingTexture( StagingTextureType::Mutable, TextureConfig(EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, GetEFBDepthCopyFormat(), 0)); if (!m_efb_color_cache.readback_texture || !m_efb_depth_cache.readback_texture) @@ -728,16 +789,16 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index, bool async // Issue a copy from framebuffer -> copy texture if we have >1xIR or MSAA on. EFBCacheData& data = depth ? m_efb_depth_cache : m_efb_color_cache; const MathUtil::Rectangle<int> rect = GetEFBCacheTileRect(tile_index); - const MathUtil::Rectangle<int> native_rect = g_renderer->ConvertEFBRectangle(rect); + const MathUtil::Rectangle<int> native_rect = ConvertEFBRectangle(rect); AbstractTexture* src_texture = depth ? ResolveEFBDepthTexture(native_rect) : ResolveEFBColorTexture(native_rect); - if (g_renderer->GetEFBScale() != 1 || force_intermediate_copy) + if (GetEFBScale() != 1 || force_intermediate_copy) { // Downsample from internal resolution to 1x. // TODO: This won't produce correct results at IRs above 2x. More samples are required. // This is the same issue as with EFB copies. src_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); const float rcp_src_width = 1.0f / m_efb_framebuffer->GetWidth(); const float rcp_src_height = 1.0f / m_efb_framebuffer->GetHeight(); @@ -748,14 +809,13 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index, bool async // Viewport will not be TILE_SIZExTILE_SIZE for the last row of tiles, assuming a tile size of // 64, because 528 is not evenly divisible by 64. - g_renderer->SetAndDiscardFramebuffer(data.framebuffer.get()); - g_renderer->SetViewportAndScissor( - MathUtil::Rectangle<int>(0, 0, rect.GetWidth(), rect.GetHeight())); - g_renderer->SetPipeline(data.copy_pipeline.get()); - g_renderer->SetTexture(0, src_texture); - g_renderer->SetSamplerState(0, depth ? RenderState::GetPointSamplerState() : - RenderState::GetLinearSamplerState()); - g_renderer->Draw(0, 3); + g_gfx->SetAndDiscardFramebuffer(data.framebuffer.get()); + g_gfx->SetViewportAndScissor(MathUtil::Rectangle<int>(0, 0, rect.GetWidth(), rect.GetHeight())); + g_gfx->SetPipeline(data.copy_pipeline.get()); + g_gfx->SetTexture(0, src_texture); + g_gfx->SetSamplerState(0, depth ? RenderState::GetPointSamplerState() : + RenderState::GetLinearSamplerState()); + g_gfx->Draw(0, 3); // Copy from EFB or copy texture to staging texture. // No need to call FinishedRendering() here because CopyFromTexture() transitions. @@ -763,7 +823,7 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index, bool async data.texture.get(), MathUtil::Rectangle<int>(0, 0, rect.GetWidth(), rect.GetHeight()), 0, 0, rect); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); } else { @@ -785,41 +845,39 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index, bool async data.tiles[tile_index].present = true; } -void FramebufferManager::ClearEFB(const MathUtil::Rectangle<int>& rc, bool clear_color, - bool clear_alpha, bool clear_z, u32 color, u32 z) +void FramebufferManager::ClearEFB(const MathUtil::Rectangle<int>& rc, bool color_enable, + bool alpha_enable, bool z_enable, u32 color, u32 z) { FlushEFBPokes(); FlagPeekCacheAsOutOfDate(); - g_renderer->BeginUtilityDrawing(); - // Set up uniforms. - struct Uniforms + // Native -> EFB coordinates + MathUtil::Rectangle<int> target_rc = ConvertEFBRectangle(rc); + target_rc = g_gfx->ConvertFramebufferRectangle(target_rc, m_efb_framebuffer.get()); + target_rc.ClampUL(0, 0, m_efb_framebuffer->GetWidth(), m_efb_framebuffer->GetWidth()); + + // Determine whether the EFB has an alpha channel. If it doesn't, we can clear the alpha + // channel to 0xFF. + // On backends that don't allow masking Alpha clears, this allows us to use the fast path + // almost all the time + if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16 || + bpmem.zcontrol.pixel_format == PixelFormat::RGB8_Z24 || + bpmem.zcontrol.pixel_format == PixelFormat::Z24) { - float clear_color[4]; - float clear_depth; - float padding1, padding2, padding3; - }; - static_assert(std::is_standard_layout<Uniforms>::value); - Uniforms uniforms = {{static_cast<float>((color >> 16) & 0xFF) / 255.0f, - static_cast<float>((color >> 8) & 0xFF) / 255.0f, - static_cast<float>((color >> 0) & 0xFF) / 255.0f, - static_cast<float>((color >> 24) & 0xFF) / 255.0f}, - static_cast<float>(z & 0xFFFFFF) / 16777216.0f}; - if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange) - uniforms.clear_depth = 1.0f - uniforms.clear_depth; - g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - - const auto target_rc = g_renderer->ConvertFramebufferRectangle( - g_renderer->ConvertEFBRectangle(rc), m_efb_framebuffer.get()); - g_renderer->SetPipeline(m_efb_clear_pipelines[clear_color][clear_alpha][clear_z].get()); - g_renderer->SetViewportAndScissor(target_rc); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + // Force alpha writes, and clear the alpha channel. + alpha_enable = true; + color &= 0x00FFFFFF; + } + + g_gfx->ClearRegion(target_rc, color_enable, alpha_enable, z_enable, color, z); + + // Scissor rect must be restored. + BPFunctions::SetScissorAndViewport(); } bool FramebufferManager::CompileClearPipelines() { - auto vertex_shader = g_renderer->CreateShaderFromSource( + auto vertex_shader = g_gfx->CreateShaderFromSource( ShaderStage::Vertex, FramebufferShaderGen::GenerateClearVertexShader(), "Clear vertex shader"); if (!vertex_shader) @@ -847,9 +905,8 @@ bool FramebufferManager::CompileClearPipelines() config.depth_state.testenable = depth_enable != 0; config.depth_state.updateenable = depth_enable != 0; - m_efb_clear_pipelines[color_enable][alpha_enable][depth_enable] = - g_renderer->CreatePipeline(config); - if (!m_efb_clear_pipelines[color_enable][alpha_enable][depth_enable]) + m_clear_pipelines[color_enable][alpha_enable][depth_enable] = g_gfx->CreatePipeline(config); + if (!m_clear_pipelines[color_enable][alpha_enable][depth_enable]) return false; } } @@ -866,12 +923,18 @@ void FramebufferManager::DestroyClearPipelines() { for (u32 depth_enable = 0; depth_enable < 2; depth_enable++) { - m_efb_clear_pipelines[color_enable][alpha_enable][depth_enable].reset(); + m_clear_pipelines[color_enable][alpha_enable][depth_enable].reset(); } } } } +AbstractPipeline* FramebufferManager::GetClearPipeline(bool colorEnable, bool alphaEnable, + bool zEnable) const +{ + return m_clear_pipelines[colorEnable][alphaEnable][zEnable].get(); +} + void FramebufferManager::PokeEFBColor(u32 x, u32 y, u32 color) { // Flush if we exceeded the number of vertices per batch. @@ -918,7 +981,7 @@ void FramebufferManager::CreatePokeVertices(std::vector<EFBPokeVertex>* destinat // GPU will expand the point to a quad. const float cs_x = (static_cast<float>(x) + 0.5f) * cs_pixel_width - 1.0f; const float cs_y = 1.0f - (static_cast<float>(y) + 0.5f) * cs_pixel_height; - const float point_size = static_cast<float>(g_renderer->GetEFBScale()); + const float point_size = static_cast<float>(GetEFBScale()); destination_list->push_back({{cs_x, cs_y, z, point_size}, color}); return; } @@ -957,17 +1020,17 @@ void FramebufferManager::DrawPokeVertices(const EFBPokeVertex* vertices, u32 ver const AbstractPipeline* pipeline) { // Copy to vertex buffer. - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); u32 base_vertex, base_index; g_vertex_manager->UploadUtilityVertices(vertices, sizeof(EFBPokeVertex), static_cast<u32>(vertex_count), nullptr, 0, &base_vertex, &base_index); // Now we can draw. - g_renderer->SetViewportAndScissor(m_efb_framebuffer->GetRect()); - g_renderer->SetPipeline(pipeline); - g_renderer->Draw(base_vertex, vertex_count); - g_renderer->EndUtilityDrawing(); + g_gfx->SetViewportAndScissor(m_efb_framebuffer->GetRect()); + g_gfx->SetPipeline(pipeline); + g_gfx->Draw(base_vertex, vertex_count); + g_gfx->EndUtilityDrawing(); } bool FramebufferManager::CompilePokePipelines() @@ -985,11 +1048,11 @@ bool FramebufferManager::CompilePokePipelines() vtx_decl.colors[0].offset = offsetof(EFBPokeVertex, color); vtx_decl.stride = sizeof(EFBPokeVertex); - m_poke_vertex_format = g_renderer->CreateNativeVertexFormat(vtx_decl); + m_poke_vertex_format = g_gfx->CreateNativeVertexFormat(vtx_decl); if (!m_poke_vertex_format) return false; - auto poke_vertex_shader = g_renderer->CreateShaderFromSource( + auto poke_vertex_shader = g_gfx->CreateShaderFromSource( ShaderStage::Vertex, FramebufferShaderGen::GenerateEFBPokeVertexShader(), "EFB poke vertex shader"); if (!poke_vertex_shader) @@ -1007,14 +1070,14 @@ bool FramebufferManager::CompilePokePipelines() config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = GetEFBFramebufferState(); config.usage = AbstractPipelineUsage::Utility; - m_color_poke_pipeline = g_renderer->CreatePipeline(config); + m_color_poke_pipeline = g_gfx->CreatePipeline(config); if (!m_color_poke_pipeline) return false; // Turn off color writes, depth writes on for depth pokes. config.depth_state = RenderState::GetAlwaysWriteDepthState(); config.blending_state = RenderState::GetNoColorWriteBlendState(); - m_depth_poke_pipeline = g_renderer->CreatePipeline(config); + m_depth_poke_pipeline = g_gfx->CreatePipeline(config); if (!m_depth_poke_pipeline) return false; @@ -1031,6 +1094,7 @@ void FramebufferManager::DestroyPokePipelines() void FramebufferManager::DoState(PointerWrap& p) { FlushEFBPokes(); + p.Do(m_prev_efb_format); bool save_efb_state = Config::Get(Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE); p.Do(save_efb_state); @@ -1077,9 +1141,9 @@ void FramebufferManager::DoLoadState(PointerWrap& p) color_tex->texture->GetLayers() != m_efb_color_texture->GetLayers()) { WARN_LOG_FMT(VIDEO, "Failed to deserialize EFB contents. Clearing instead."); - g_renderer->SetAndClearFramebuffer( - m_efb_framebuffer.get(), {{0.0f, 0.0f, 0.0f, 0.0f}}, - g_ActiveConfig.backend_info.bSupportsReversedDepthRange ? 1.0f : 0.0f); + g_gfx->SetAndClearFramebuffer(m_efb_framebuffer.get(), {{0.0f, 0.0f, 0.0f, 0.0f}}, + g_ActiveConfig.backend_info.bSupportsReversedDepthRange ? 1.0f : + 0.0f); return; } @@ -1089,15 +1153,15 @@ void FramebufferManager::DoLoadState(PointerWrap& p) color_tex->texture->GetHeight() != m_efb_color_texture->GetHeight(); // Draw the deserialized textures over the EFB. - g_renderer->BeginUtilityDrawing(); - g_renderer->SetAndDiscardFramebuffer(m_efb_framebuffer.get()); - g_renderer->SetViewportAndScissor(m_efb_framebuffer->GetRect()); - g_renderer->SetPipeline(m_efb_restore_pipeline.get()); - g_renderer->SetTexture(0, color_tex->texture.get()); - g_renderer->SetTexture(1, depth_tex->texture.get()); - g_renderer->SetSamplerState(0, rescale ? RenderState::GetLinearSamplerState() : - RenderState::GetPointSamplerState()); - g_renderer->SetSamplerState(1, RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(m_efb_framebuffer.get()); + g_gfx->SetViewportAndScissor(m_efb_framebuffer->GetRect()); + g_gfx->SetPipeline(m_efb_restore_pipeline.get()); + g_gfx->SetTexture(0, color_tex->texture.get()); + g_gfx->SetTexture(1, depth_tex->texture.get()); + g_gfx->SetSamplerState(0, rescale ? RenderState::GetLinearSamplerState() : + RenderState::GetPointSamplerState()); + g_gfx->SetSamplerState(1, RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); } |
