VideoCommon: Rename Renderer to EFBInterface.

This commit is contained in:
Jordan Woyak
2025-03-11 21:12:06 -05:00
parent de997d616f
commit 5b36c13bfb
28 changed files with 281 additions and 333 deletions

View File

@ -9,7 +9,6 @@
#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/BPFunctions.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/ShaderCache.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoConfig.h"

View File

@ -8,9 +8,9 @@
#include "Core/System.h"
#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/EFBInterface.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/Present.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VideoBackendBase.h"
@ -102,26 +102,25 @@ void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
case Event::EFB_POKE_COLOR:
{
INCSTAT(g_stats.this_frame.num_efb_pokes);
g_renderer->PokeEFB(EFBAccessType::PokeColor, e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
g_efb_interface->PokeColor(e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
}
break;
case Event::EFB_POKE_Z:
{
INCSTAT(g_stats.this_frame.num_efb_pokes);
g_renderer->PokeEFB(EFBAccessType::PokeZ, e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
g_efb_interface->PokeDepth(e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
}
break;
case Event::EFB_PEEK_COLOR:
INCSTAT(g_stats.this_frame.num_efb_peeks);
*e.efb_peek.data =
g_renderer->AccessEFB(EFBAccessType::PeekColor, e.efb_peek.x, e.efb_peek.y, 0);
*e.efb_peek.data = g_efb_interface->PeekColor(e.efb_peek.x, e.efb_peek.y);
break;
case Event::EFB_PEEK_Z:
INCSTAT(g_stats.this_frame.num_efb_peeks);
*e.efb_peek.data = g_renderer->AccessEFB(EFBAccessType::PeekZ, e.efb_peek.x, e.efb_peek.y, 0);
*e.efb_peek.data = g_efb_interface->PeekDepth(e.efb_peek.x, e.efb_peek.y);
break;
case Event::SWAP_EVENT:

View File

@ -15,8 +15,8 @@
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/EFBInterface.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/RenderState.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VertexShaderManager.h"
@ -369,12 +369,12 @@ void OnPixelFormatChange()
if (new_format == PixelFormat::RGBA6_Z24)
{
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB8ToRGBA6);
g_efb_interface->ReinterpretPixelData(EFBReinterpretType::RGB8ToRGBA6);
return;
}
else if (new_format == PixelFormat::RGB565_Z16)
{
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB8ToRGB565);
g_efb_interface->ReinterpretPixelData(EFBReinterpretType::RGB8ToRGB565);
return;
}
}
@ -384,12 +384,12 @@ void OnPixelFormatChange()
{
if (new_format == PixelFormat::RGB8_Z24 || new_format == PixelFormat::Z24)
{
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGBA6ToRGB8);
g_efb_interface->ReinterpretPixelData(EFBReinterpretType::RGBA6ToRGB8);
return;
}
else if (new_format == PixelFormat::RGB565_Z16)
{
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGBA6ToRGB565);
g_efb_interface->ReinterpretPixelData(EFBReinterpretType::RGBA6ToRGB565);
return;
}
}
@ -399,12 +399,12 @@ void OnPixelFormatChange()
{
if (new_format == PixelFormat::RGB8_Z24 || new_format == PixelFormat::Z24)
{
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB565ToRGB8);
g_efb_interface->ReinterpretPixelData(EFBReinterpretType::RGB565ToRGB8);
return;
}
else if (new_format == PixelFormat::RGBA6_Z24)
{
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB565ToRGBA6);
g_efb_interface->ReinterpretPixelData(EFBReinterpretType::RGB565ToRGBA6);
return;
}
}

View File

@ -49,6 +49,8 @@ add_library(videocommon
CPUCullImpl.h
DriverDetails.cpp
DriverDetails.h
EFBInterface.cpp
EFBInterface.h
Fifo.cpp
Fifo.h
FramebufferManager.cpp
@ -134,8 +136,6 @@ add_library(videocommon
PostProcessing.h
Present.cpp
Present.h
RenderBase.cpp
RenderBase.h
RenderState.cpp
RenderState.h
ShaderCache.cpp

View File

@ -0,0 +1,126 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoCommon/EFBInterface.h"
#include <algorithm>
#include <cmath>
#include <memory>
#include <fmt/format.h>
#include "Common/MsgHandler.h"
#include "Core/ConfigManager.h"
#include "Core/System.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
std::unique_ptr<EFBInterfaceBase> g_efb_interface;
EFBInterfaceBase::~EFBInterfaceBase() = default;
void HardwareEFBInterface::ReinterpretPixelData(EFBReinterpretType convtype)
{
g_framebuffer_manager->ReinterpretPixelData(convtype);
}
u32 HardwareEFBInterface::PeekColorInternal(u16 x, u16 y)
{
u32 color = g_framebuffer_manager->PeekEFBColor(x, y);
// a little-endian value is expected to be returned
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
if (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24)
{
color = RGBA8ToRGBA6ToRGBA8(color);
}
else if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
{
color = RGBA8ToRGB565ToRGBA8(color);
}
if (bpmem.zcontrol.pixel_format != PixelFormat::RGBA6_Z24)
{
color |= 0xFF000000;
}
return color;
}
u32 EFBInterfaceBase::PeekColor(u16 x, u16 y)
{
u32 color = PeekColorInternal(x, y);
// check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine::AlphaReadMode alpha_read_mode =
Core::System::GetInstance().GetPixelEngine().GetAlphaReadMode();
if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadNone)
{
return color;
}
else if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadFF)
{
return color | 0xFF000000;
}
else
{
if (alpha_read_mode != PixelEngine::AlphaReadMode::Read00)
{
PanicAlertFmt("Invalid PE alpha read mode: {}", static_cast<u16>(alpha_read_mode));
}
return color & 0x00FFFFFF;
}
}
u32 HardwareEFBInterface::PeekDepth(u16 x, u16 y)
{
// Depth buffer is inverted for improved precision near far plane
float depth = g_framebuffer_manager->PeekEFBDepth(x, y);
if (!g_backend_info.bSupportsReversedDepthRange)
depth = 1.0f - depth;
// Convert to 24bit depth
u32 z24depth = std::clamp<u32>(static_cast<u32>(depth * 16777216.0f), 0, 0xFFFFFF);
if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
{
// When in RGB565_Z16 mode, EFB Z peeks return a 16bit value, which is presumably a
// resolved sample from the MSAA buffer.
// Dolphin doesn't currently emulate the 3 sample MSAA mode (and potentially never will)
// it just transparently upgrades the framebuffer to 24bit depth and color and whatever
// level of MSAA and higher Internal Resolution the user has configured.
// This is mostly transparent, unless the game does an EFB read.
// But we can simply convert the 24bit depth on the fly to the 16bit depth the game expects.
return CompressZ16(z24depth, bpmem.zcontrol.zformat);
}
return z24depth;
}
void HardwareEFBInterface::PokeColor(u16 x, u16 y, u32 poke_data)
{
// Convert to expected format (BGRA->RGBA)
// TODO: Check alpha, depending on mode?
const u32 color =
((poke_data & 0xFF00FF00) | ((poke_data >> 16) & 0xFF) | ((poke_data << 16) & 0xFF0000));
g_framebuffer_manager->PokeEFBColor(x, y, color);
}
void HardwareEFBInterface::PokeDepth(u16 x, u16 y, u32 poke_data)
{
// Convert to floating-point depth.
float depth = float(poke_data & 0xFFFFFF) / 16777216.0f;
if (!g_backend_info.bSupportsReversedDepthRange)
depth = 1.0f - depth;
g_framebuffer_manager->PokeEFBDepth(x, y, depth);
}

View File

@ -0,0 +1,40 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "Common/CommonTypes.h"
enum class EFBReinterpretType;
class EFBInterfaceBase
{
public:
virtual ~EFBInterfaceBase();
virtual void ReinterpretPixelData(EFBReinterpretType convtype) = 0;
virtual void PokeColor(u16 x, u16 y, u32 color) = 0;
virtual void PokeDepth(u16 x, u16 y, u32 depth) = 0;
u32 PeekColor(u16 x, u16 y);
virtual u32 PeekDepth(u16 x, u16 y) = 0;
protected:
virtual u32 PeekColorInternal(u16 x, u16 y) = 0;
};
class HardwareEFBInterface final : public EFBInterfaceBase
{
void ReinterpretPixelData(EFBReinterpretType convtype) override;
void PokeColor(u16 x, u16 y, u32 color) override;
void PokeDepth(u16 x, u16 y, u32 depth) override;
u32 PeekColorInternal(u16 x, u16 y) override;
u32 PeekDepth(u16 x, u16 y) override;
};
extern std::unique_ptr<EFBInterfaceBase> g_efb_interface;

View File

@ -1,134 +0,0 @@
// Copyright 2010 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// ---------------------------------------------------------------------------------------------
// GC graphics pipeline
// ---------------------------------------------------------------------------------------------
// 3d commands are issued through the fifo. The GPU draws to the 2MB EFB.
// The efb can be copied back into ram in two forms: as textures or as XFB.
// The XFB is the region in RAM that the VI chip scans out to the television.
// So, after all rendering to EFB is done, the image is copied into one of two XFBs in RAM.
// Next frame, that one is scanned out and the other one gets the copy. = double buffering.
// ---------------------------------------------------------------------------------------------
#include "VideoCommon/RenderBase.h"
#include <algorithm>
#include <cmath>
#include <memory>
#include <tuple>
#include <fmt/format.h>
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Core/ConfigManager.h"
#include "Core/System.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
std::unique_ptr<Renderer> g_renderer;
Renderer::~Renderer() = default;
void Renderer::ReinterpretPixelData(EFBReinterpretType convtype)
{
g_framebuffer_manager->ReinterpretPixelData(convtype);
}
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
if (type == EFBAccessType::PeekColor)
{
u32 color = g_framebuffer_manager->PeekEFBColor(x, y);
// a little-endian value is expected to be returned
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
if (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24)
{
color = RGBA8ToRGBA6ToRGBA8(color);
}
else if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
{
color = RGBA8ToRGB565ToRGBA8(color);
}
if (bpmem.zcontrol.pixel_format != PixelFormat::RGBA6_Z24)
{
color |= 0xFF000000;
}
// check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine::AlphaReadMode alpha_read_mode =
Core::System::GetInstance().GetPixelEngine().GetAlphaReadMode();
if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadNone)
{
return color;
}
else if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadFF)
{
return color | 0xFF000000;
}
else
{
if (alpha_read_mode != PixelEngine::AlphaReadMode::Read00)
{
PanicAlertFmt("Invalid PE alpha read mode: {}", static_cast<u16>(alpha_read_mode));
}
return color & 0x00FFFFFF;
}
}
else // if (type == EFBAccessType::PeekZ)
{
// Depth buffer is inverted for improved precision near far plane
float depth = g_framebuffer_manager->PeekEFBDepth(x, y);
if (!g_backend_info.bSupportsReversedDepthRange)
depth = 1.0f - depth;
// Convert to 24bit depth
u32 z24depth = std::clamp<u32>(static_cast<u32>(depth * 16777216.0f), 0, 0xFFFFFF);
if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
{
// When in RGB565_Z16 mode, EFB Z peeks return a 16bit value, which is presumably a
// resolved sample from the MSAA buffer.
// Dolphin doesn't currently emulate the 3 sample MSAA mode (and potentially never will)
// it just transparently upgrades the framebuffer to 24bit depth and color and whatever
// level of MSAA and higher Internal Resolution the user has configured.
// This is mostly transparent, unless the game does an EFB read.
// But we can simply convert the 24bit depth on the fly to the 16bit depth the game expects.
return CompressZ16(z24depth, bpmem.zcontrol.zformat);
}
return z24depth;
}
}
void Renderer::PokeEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{
if (type == EFBAccessType::PokeColor)
{
// Convert to expected format (BGRA->RGBA)
// TODO: Check alpha, depending on mode?
const u32 color =
((poke_data & 0xFF00FF00) | ((poke_data >> 16) & 0xFF) | ((poke_data << 16) & 0xFF0000));
g_framebuffer_manager->PokeEFBColor(x, y, color);
}
else // if (type == EFBAccessType::PokeZ)
{
// Convert to floating-point depth.
float depth = float(poke_data & 0xFFFFFF) / 16777216.0f;
if (!g_backend_info.bSupportsReversedDepthRange)
depth = 1.0f - depth;
g_framebuffer_manager->PokeEFBDepth(x, y, depth);
}
}

View File

@ -1,28 +0,0 @@
// Copyright 2010 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "Common/CommonTypes.h"
enum class EFBAccessType;
enum class EFBReinterpretType;
// Renderer really isn't a very good name for this class - it's more like "Misc".
// It used to be a massive mess, but almost everything has been refactored out.
//
// All that's left is a thin abstraction layer for VideoSoftware to intercept EFB accesses.
class Renderer
{
public:
virtual ~Renderer();
virtual void ReinterpretPixelData(EFBReinterpretType convtype);
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
virtual void PokeEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data);
};
extern std::unique_ptr<Renderer> g_renderer;

View File

@ -13,7 +13,6 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Event.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
@ -46,18 +45,16 @@
#include "VideoCommon/BoundingBox.h"
#include "VideoCommon/CPMemory.h"
#include "VideoCommon/CommandProcessor.h"
#include "VideoCommon/EFBInterface.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/FrameDumper.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h"
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/OpcodeDecoding.h"
#include "VideoCommon/PixelEngine.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/Present.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/TMEM.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/VertexLoaderManager.h"
@ -325,11 +322,11 @@ bool VideoBackendBase::InitializeShared(std::unique_ptr<AbstractGfx> gfx,
std::unique_ptr<PerfQueryBase> perf_query,
std::unique_ptr<BoundingBox> bounding_box)
{
// All hardware backends use the default RendererBase and TextureCacheBase.
// All hardware backends use the default EFBInterface and TextureCacheBase.
// Only Null and Software backends override them
return InitializeShared(std::move(gfx), std::move(vertex_manager), std::move(perf_query),
std::move(bounding_box), std::make_unique<Renderer>(),
std::move(bounding_box), std::make_unique<HardwareEFBInterface>(),
std::make_unique<TextureCacheBase>());
}
@ -337,7 +334,7 @@ bool VideoBackendBase::InitializeShared(std::unique_ptr<AbstractGfx> gfx,
std::unique_ptr<VertexManagerBase> vertex_manager,
std::unique_ptr<PerfQueryBase> perf_query,
std::unique_ptr<BoundingBox> bounding_box,
std::unique_ptr<Renderer> renderer,
std::unique_ptr<EFBInterfaceBase> efb_interface,
std::unique_ptr<TextureCacheBase> texture_cache)
{
memset(reinterpret_cast<u8*>(&g_main_cp_state), 0, sizeof(g_main_cp_state));
@ -352,9 +349,9 @@ bool VideoBackendBase::InitializeShared(std::unique_ptr<AbstractGfx> gfx,
g_perf_query = std::move(perf_query);
g_bounding_box = std::move(bounding_box);
// Null and Software Backends supply their own derived Renderer and Texture Cache
// Null and Software Backends supply their own derived EFBInterface and TextureCache
g_texture_cache = std::move(texture_cache);
g_renderer = std::move(renderer);
g_efb_interface = std::move(efb_interface);
g_presenter = std::make_unique<VideoCommon::Presenter>();
g_frame_dumper = std::make_unique<FrameDumper>();
@ -418,7 +415,7 @@ void VideoBackendBase::ShutdownShared()
g_framebuffer_manager.reset();
g_shader_cache.reset();
g_vertex_manager.reset();
g_renderer.reset();
g_efb_interface.reset();
g_widescreen.reset();
g_presenter.reset();
g_gfx.reset();

View File

@ -20,9 +20,9 @@ class PointerWrap;
class AbstractGfx;
class BoundingBox;
class Renderer;
class TextureCacheBase;
class VertexManagerBase;
class EFBInterfaceBase;
enum class FieldType
{
@ -80,12 +80,12 @@ protected:
std::unique_ptr<PerfQueryBase> perf_query,
std::unique_ptr<BoundingBox> bounding_box);
// For software and null backends. Allows overriding the default Renderer and Texture Cache
// For software and null backends. Allows overriding the default EFBInterface and TextureCache
bool InitializeShared(std::unique_ptr<AbstractGfx> gfx,
std::unique_ptr<VertexManagerBase> vertex_manager,
std::unique_ptr<PerfQueryBase> perf_query,
std::unique_ptr<BoundingBox> bounding_box,
std::unique_ptr<Renderer> renderer,
std::unique_ptr<EFBInterfaceBase> efb_interface,
std::unique_ptr<TextureCacheBase> texture_cache);
void ShutdownShared();