summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/FramebufferManager.cpp
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2023-02-09 19:59:16 +1300
committerGitHub <noreply@github.com>2023-02-09 19:59:16 +1300
commitccf92a3e56764d6378c436a8040519a5bffc3372 (patch)
treee2b330b225044e1901e77a6ed147cf21b9d7ac0e /Source/Core/VideoCommon/FramebufferManager.cpp
parent72b22ef0a54f841b1c52d49cf0e00d3b12c29ac7 (diff)
parent5c1b3ac61d7e660a9d1c206dbd0e615d637d3272 (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.cpp332
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();
}