From 8a236293455e9a71aa6fb400a6253c27540e403b Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Fri, 27 Jan 2023 11:34:59 +1300 Subject: [PATCH] Split AbstractGfx out of Renderer Almost all the virtual functions in Renderer are part of dolphin's "graphics api abstraction layer", which has slowly formed over the last decade or two. Most of the work was done previously with the introduction of the various "AbstractX" classes, associated with texture cache cleanups and implementation of newer graphics APIs (Direct3D 12, Vulkan, Metal). We are simply taking the last step and yeeting these functions out of Renderer. This "AbstractGfx" class is now completely agnostic of any details from the flipper/hollywood GPU we are emulating, though somewhat specialized. (Will not build, this commit only contains changes outside VideoBackends) --- Source/Core/DolphinLib.props | 2 + Source/Core/DolphinQt/Host.cpp | 11 +- Source/Core/VideoCommon/AbstractGfx.cpp | 138 +++++++++++++ Source/Core/VideoCommon/AbstractGfx.h | 174 ++++++++++++++++ Source/Core/VideoCommon/AbstractTexture.cpp | 4 +- Source/Core/VideoCommon/BPFunctions.cpp | 10 +- Source/Core/VideoCommon/BoundingBox.h | 3 + Source/Core/VideoCommon/CMakeLists.txt | 2 + Source/Core/VideoCommon/FrameDumper.cpp | 11 +- .../Core/VideoCommon/FramebufferManager.cpp | 192 +++++++++--------- Source/Core/VideoCommon/OnScreenUI.cpp | 36 ++-- Source/Core/VideoCommon/PostProcessing.cpp | 30 +-- Source/Core/VideoCommon/Present.cpp | 51 ++--- Source/Core/VideoCommon/Present.h | 4 +- Source/Core/VideoCommon/RenderBase.cpp | 176 ++++------------ Source/Core/VideoCommon/RenderBase.h | 129 +----------- Source/Core/VideoCommon/ShaderCache.cpp | 68 +++---- Source/Core/VideoCommon/TextureCacheBase.cpp | 110 +++++----- .../Core/VideoCommon/VertexLoaderManager.cpp | 4 +- Source/Core/VideoCommon/VertexManagerBase.cpp | 11 +- Source/Core/VideoCommon/VideoBackendBase.cpp | 10 +- 21 files changed, 645 insertions(+), 531 deletions(-) create mode 100644 Source/Core/VideoCommon/AbstractGfx.cpp create mode 100644 Source/Core/VideoCommon/AbstractGfx.h diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 80daf63a32..bc0f486082 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -618,6 +618,7 @@ + @@ -1219,6 +1220,7 @@ + diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp index 5eb2055486..036dc2cffa 100644 --- a/Source/Core/DolphinQt/Host.cpp +++ b/Source/Core/DolphinQt/Host.cpp @@ -36,9 +36,9 @@ #include "UICommon/DiscordPresence.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/Fifo.cpp" #include "VideoCommon/Present.h" -#include "VideoCommon/RenderBase.h" #include "VideoCommon/VideoConfig.h" static thread_local bool tls_is_host_thread = false; @@ -150,11 +150,11 @@ bool Host::GetRenderFullFocus() void Host::SetRenderFocus(bool focus) { m_render_focus = focus; - if (g_renderer && m_render_fullscreen && g_ActiveConfig.ExclusiveFullscreenEnabled()) + if (g_gfx && m_render_fullscreen && g_ActiveConfig.ExclusiveFullscreenEnabled()) { RunWithGPUThreadInactive([focus] { if (!Config::Get(Config::MAIN_RENDER_TO_MAIN)) - g_renderer->SetFullscreen(focus); + g_gfx->SetFullscreen(focus); }); } } @@ -182,10 +182,9 @@ void Host::SetRenderFullscreen(bool fullscreen) { m_render_fullscreen = fullscreen; - if (g_renderer && g_renderer->IsFullscreen() != fullscreen && - g_ActiveConfig.ExclusiveFullscreenEnabled()) + if (g_gfx && g_gfx->IsFullscreen() != fullscreen && g_ActiveConfig.ExclusiveFullscreenEnabled()) { - RunWithGPUThreadInactive([fullscreen] { g_renderer->SetFullscreen(fullscreen); }); + RunWithGPUThreadInactive([fullscreen] { g_gfx->SetFullscreen(fullscreen); }); } } diff --git a/Source/Core/VideoCommon/AbstractGfx.cpp b/Source/Core/VideoCommon/AbstractGfx.cpp new file mode 100644 index 0000000000..4406cd46b6 --- /dev/null +++ b/Source/Core/VideoCommon/AbstractGfx.cpp @@ -0,0 +1,138 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "VideoCommon/AbstractGfx.h" + +#include "Common/Assert.h" + +#include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractTexture.h" +#include "VideoCommon/FramebufferManager.h" +#include "VideoCommon/RenderBase.h" +#include "VideoCommon/ShaderCache.h" +#include "VideoCommon/VertexManagerBase.h" +#include "VideoCommon/VideoConfig.h" + +bool AbstractGfx::IsHeadless() const +{ + return true; +} + +void AbstractGfx::BeginUtilityDrawing() +{ + if (g_renderer) + g_renderer->BeginUtilityDrawing(); +} + +void AbstractGfx::EndUtilityDrawing() +{ + if (g_renderer) + g_renderer->EndUtilityDrawing(); +} + +void AbstractGfx::SetFramebuffer(AbstractFramebuffer* framebuffer) +{ + m_current_framebuffer = framebuffer; +} + +void AbstractGfx::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) +{ + m_current_framebuffer = framebuffer; +} + +void AbstractGfx::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, + const ClearColor& color_value, float depth_value) +{ + m_current_framebuffer = framebuffer; +} + +void AbstractGfx::ClearRegion(const MathUtil::Rectangle& rc, + const MathUtil::Rectangle& target_rc, bool colorEnable, + bool alphaEnable, bool zEnable, u32 color, u32 z) +{ + g_framebuffer_manager->ClearEFB(rc, colorEnable, alphaEnable, zEnable, color, z); +} + +void AbstractGfx::SetViewportAndScissor(const MathUtil::Rectangle& rect, float min_depth, + float max_depth) +{ + SetViewport(static_cast(rect.left), static_cast(rect.top), + static_cast(rect.GetWidth()), static_cast(rect.GetHeight()), min_depth, + max_depth); + SetScissorRect(rect); +} + +void AbstractGfx::ScaleTexture(AbstractFramebuffer* dst_framebuffer, + const MathUtil::Rectangle& dst_rect, + const AbstractTexture* src_texture, + const MathUtil::Rectangle& src_rect) +{ + ASSERT(dst_framebuffer->GetColorFormat() == AbstractTextureFormat::RGBA8); + + BeginUtilityDrawing(); + + // The shader needs to know the source rectangle. + const auto converted_src_rect = + ConvertFramebufferRectangle(src_rect, src_texture->GetWidth(), src_texture->GetHeight()); + const float rcp_src_width = 1.0f / src_texture->GetWidth(); + const float rcp_src_height = 1.0f / src_texture->GetHeight(); + const std::array uniforms = {{converted_src_rect.left * rcp_src_width, + converted_src_rect.top * rcp_src_height, + converted_src_rect.GetWidth() * rcp_src_width, + converted_src_rect.GetHeight() * rcp_src_height}}; + g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); + + // Discard if we're overwriting the whole thing. + if (static_cast(dst_rect.GetWidth()) == dst_framebuffer->GetWidth() && + static_cast(dst_rect.GetHeight()) == dst_framebuffer->GetHeight()) + { + SetAndDiscardFramebuffer(dst_framebuffer); + } + else + { + SetFramebuffer(dst_framebuffer); + } + + SetViewportAndScissor(ConvertFramebufferRectangle(dst_rect, dst_framebuffer)); + SetPipeline(dst_framebuffer->GetLayers() > 1 ? g_shader_cache->GetRGBA8StereoCopyPipeline() : + g_shader_cache->GetRGBA8CopyPipeline()); + SetTexture(0, src_texture); + SetSamplerState(0, RenderState::GetLinearSamplerState()); + Draw(0, 3); + EndUtilityDrawing(); + if (dst_framebuffer->GetColorAttachment()) + dst_framebuffer->GetColorAttachment()->FinishedRendering(); +} + +MathUtil::Rectangle +AbstractGfx::ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, + const AbstractFramebuffer* framebuffer) const +{ + return ConvertFramebufferRectangle(rect, framebuffer->GetWidth(), framebuffer->GetHeight()); +} + +MathUtil::Rectangle +AbstractGfx::ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, u32 fb_width, + u32 fb_height) const +{ + MathUtil::Rectangle ret = rect; + if (g_ActiveConfig.backend_info.bUsesLowerLeftOrigin) + { + ret.top = fb_height - rect.bottom; + ret.bottom = fb_height - rect.top; + } + return ret; +} + +std::unique_ptr AbstractGfx::CreateAsyncShaderCompiler() +{ + return std::make_unique(); +} + +bool AbstractGfx::UseGeometryShaderForUI() const +{ + // OpenGL doesn't render to a 2-layer backbuffer like D3D/Vulkan for quad-buffered stereo, + // instead drawing twice and the eye selected by glDrawBuffer() (see Presenter::RenderXFBToScreen) + return g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer && + g_ActiveConfig.backend_info.api_type != APIType::OpenGL; +} diff --git a/Source/Core/VideoCommon/AbstractGfx.h b/Source/Core/VideoCommon/AbstractGfx.h new file mode 100644 index 0000000000..2db077c98c --- /dev/null +++ b/Source/Core/VideoCommon/AbstractGfx.h @@ -0,0 +1,174 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "Common/MathUtil.h" + +#include "VideoCommon/RenderState.h" + +#include +#include + +class AbstractFramebuffer; +class AbstractPipeline; +class AbstractShader; +class AbstractTexture; +class AbstractStagingTexture; +class NativeVertexFormat; +struct ComputePipelineConfig; +struct AbstractPipelineConfig; +struct PortableVertexDeclaration; +struct TextureConfig; +enum class AbstractTextureFormat : u32; +enum class ShaderStage; +enum class StagingTextureType; + +struct SurfaceInfo +{ + u32 width = 0; + u32 height = 0; + float scale = 0.0f; + AbstractTextureFormat format = {}; +}; + +namespace VideoCommon +{ +class AsyncShaderCompiler; +} + +// Bitmask containing information about which configuration has changed for the backend. +enum ConfigChangeBits : u32 +{ + CONFIG_CHANGE_BIT_HOST_CONFIG = (1 << 0), + CONFIG_CHANGE_BIT_MULTISAMPLES = (1 << 1), + CONFIG_CHANGE_BIT_STEREO_MODE = (1 << 2), + CONFIG_CHANGE_BIT_TARGET_SIZE = (1 << 3), + CONFIG_CHANGE_BIT_ANISOTROPY = (1 << 4), + CONFIG_CHANGE_BIT_FORCE_TEXTURE_FILTERING = (1 << 5), + CONFIG_CHANGE_BIT_VSYNC = (1 << 6), + CONFIG_CHANGE_BIT_BBOX = (1 << 7) +}; + +using ClearColor = std::array; + +class AbstractGfx +{ +public: + virtual bool IsHeadless() const = 0; + + virtual void SetPipeline(const AbstractPipeline* pipeline) {} + virtual void SetScissorRect(const MathUtil::Rectangle& rc) {} + virtual void SetTexture(u32 index, const AbstractTexture* texture) {} + virtual void SetSamplerState(u32 index, const SamplerState& state) {} + virtual void SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) {} + virtual void UnbindTexture(const AbstractTexture* texture) {} + virtual void SetViewport(float x, float y, float width, float height, float near_depth, + float far_depth) + { + } + virtual void SetFullscreen(bool enable_fullscreen) {} + virtual bool IsFullscreen() const { return false; } + virtual void BeginUtilityDrawing(); + virtual void EndUtilityDrawing(); + virtual std::unique_ptr CreateTexture(const TextureConfig& config, + std::string_view name = "") = 0; + virtual std::unique_ptr + CreateStagingTexture(StagingTextureType type, const TextureConfig& config) = 0; + virtual std::unique_ptr + CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) = 0; + + // Framebuffer operations. + virtual void SetFramebuffer(AbstractFramebuffer* framebuffer); + virtual void SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer); + virtual void SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, + const ClearColor& color_value = {}, float depth_value = 0.0f); + + virtual void ClearRegion(const MathUtil::Rectangle& rc, + const MathUtil::Rectangle& target_rc, bool colorEnable, + bool alphaEnable, bool zEnable, u32 color, u32 z); + + // Drawing with currently-bound pipeline state. + virtual void Draw(u32 base_vertex, u32 num_vertices) {} + virtual void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) {} + + // Dispatching compute shaders with currently-bound state. + virtual void DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y, + u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z) + { + } + + // Binds the backbuffer for rendering. The buffer will be cleared immediately after binding. + // This is where any window size changes are detected, therefore m_backbuffer_width and/or + // m_backbuffer_height may change after this function returns. + virtual void BindBackbuffer(const ClearColor& clear_color = {}) {} + + // Presents the backbuffer to the window system, or "swaps buffers". + virtual void PresentBackbuffer() {} + + // Shader modules/objects. + virtual std::unique_ptr CreateShaderFromSource(ShaderStage stage, + std::string_view source, + std::string_view name = "") = 0; + virtual std::unique_ptr CreateShaderFromBinary(ShaderStage stage, + const void* data, size_t length, + std::string_view name = "") = 0; + virtual std::unique_ptr + CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) = 0; + virtual std::unique_ptr CreatePipeline(const AbstractPipelineConfig& config, + const void* cache_data = nullptr, + size_t cache_data_length = 0) = 0; + + AbstractFramebuffer* GetCurrentFramebuffer() const { return m_current_framebuffer; } + + // Sets viewport and scissor to the specified rectangle. rect is assumed to be in framebuffer + // coordinates, i.e. lower-left origin in OpenGL. + void SetViewportAndScissor(const MathUtil::Rectangle& rect, float min_depth = 0.0f, + float max_depth = 1.0f); + + // Scales a GPU texture using a copy shader. + virtual void ScaleTexture(AbstractFramebuffer* dst_framebuffer, + const MathUtil::Rectangle& dst_rect, + const AbstractTexture* src_texture, + const MathUtil::Rectangle& src_rect); + + // Converts an upper-left to lower-left if required by the backend, optionally + // clamping to the framebuffer size. + MathUtil::Rectangle ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, + u32 fb_width, u32 fb_height) const; + MathUtil::Rectangle + ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, + const AbstractFramebuffer* framebuffer) const; + + virtual void Flush() {} + virtual void WaitForGPUIdle() {} + + // For opengl's glDrawBuffer + virtual void SelectLeftBuffer() {} + virtual void SelectRightBuffer() {} + virtual void SelectMainBuffer() {} + + // A simple presentation fallback, only used by video software + virtual void ShowImage(const AbstractTexture* source_texture, + const MathUtil::Rectangle& source_rc) + { + } + + virtual std::unique_ptr CreateAsyncShaderCompiler(); + + // Called when the configuration changes, and backend structures need to be updated. + virtual void OnConfigChanged(u32 bits) {} + + // Returns true if a layer-expanding geometry shader should be used when rendering the user + // interface and final XFB. + bool UseGeometryShaderForUI() const; + + // Returns info about the main surface (aka backbuffer) + virtual SurfaceInfo GetSurfaceInfo() const { return {}; } + +protected: + AbstractFramebuffer* m_current_framebuffer = nullptr; + const AbstractPipeline* m_current_pipeline = nullptr; +}; + +extern std::unique_ptr g_gfx; diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp index fb34e2413e..03b83b21cc 100644 --- a/Source/Core/VideoCommon/AbstractTexture.cpp +++ b/Source/Core/VideoCommon/AbstractTexture.cpp @@ -8,8 +8,8 @@ #include "Common/Assert.h" #include "Common/Image.h" #include "Common/MsgHandler.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractStagingTexture.h" -#include "VideoCommon/RenderBase.h" AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c) { @@ -36,7 +36,7 @@ bool AbstractTexture::Save(const std::string& filename, unsigned int level) TextureConfig readback_texture_config(level_width, level_height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0); auto readback_texture = - g_renderer->CreateStagingTexture(StagingTextureType::Readback, readback_texture_config); + g_gfx->CreateStagingTexture(StagingTextureType::Readback, readback_texture_config); if (!readback_texture) return false; diff --git a/Source/Core/VideoCommon/BPFunctions.cpp b/Source/Core/VideoCommon/BPFunctions.cpp index c065f1cc5f..a37e3720ff 100644 --- a/Source/Core/VideoCommon/BPFunctions.cpp +++ b/Source/Core/VideoCommon/BPFunctions.cpp @@ -12,6 +12,7 @@ #include "Common/Logging/Log.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/FramebufferManager.h" #include "VideoCommon/RenderBase.h" @@ -198,9 +199,8 @@ void SetScissorAndViewport() auto native_rc = ComputeScissorRects().Best(); auto target_rc = g_renderer->ConvertEFBRectangle(native_rc.rect); - auto converted_rc = - g_renderer->ConvertFramebufferRectangle(target_rc, g_renderer->GetCurrentFramebuffer()); - g_renderer->SetScissorRect(converted_rc); + auto converted_rc = g_gfx->ConvertFramebufferRectangle(target_rc, g_gfx->GetCurrentFramebuffer()); + g_gfx->SetScissorRect(converted_rc); float raw_x = (xfmem.viewport.xOrig - native_rc.x_off) - xfmem.viewport.wd; float raw_y = (xfmem.viewport.yOrig - native_rc.y_off) + xfmem.viewport.ht; @@ -280,9 +280,9 @@ void SetScissorAndViewport() // Lower-left flip. if (g_ActiveConfig.backend_info.bUsesLowerLeftOrigin) - y = static_cast(g_renderer->GetCurrentFramebuffer()->GetHeight()) - y - height; + y = static_cast(g_gfx->GetCurrentFramebuffer()->GetHeight()) - y - height; - g_renderer->SetViewport(x, y, width, height, near_depth, far_depth); + g_gfx->SetViewport(x, y, width, height, near_depth, far_depth); } void SetDepthMode() diff --git a/Source/Core/VideoCommon/BoundingBox.h b/Source/Core/VideoCommon/BoundingBox.h index bf8ceeb818..d8d2508716 100644 --- a/Source/Core/VideoCommon/BoundingBox.h +++ b/Source/Core/VideoCommon/BoundingBox.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "Common/CommonTypes.h" @@ -49,3 +50,5 @@ private: std::array m_dirty = {}; bool m_is_valid = true; }; + +extern std::unique_ptr g_bounding_box; diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 20b3257082..4507904afd 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -1,6 +1,8 @@ add_library(videocommon AbstractFramebuffer.cpp AbstractFramebuffer.h + AbstractGfx.cpp + AbstractGfx.h AbstractShader.h AbstractStagingTexture.cpp AbstractStagingTexture.h diff --git a/Source/Core/VideoCommon/FrameDumper.cpp b/Source/Core/VideoCommon/FrameDumper.cpp index db0d099376..35431a4abf 100644 --- a/Source/Core/VideoCommon/FrameDumper.cpp +++ b/Source/Core/VideoCommon/FrameDumper.cpp @@ -11,6 +11,7 @@ #include "Core/Config/MainSettings.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/AbstractTexture.h" #include "VideoCommon/OnScreenDisplay.h" @@ -51,8 +52,8 @@ void FrameDumper::DumpCurrentFrame(const AbstractTexture* src_texture, if (!CheckFrameDumpRenderTexture(target_width, target_height)) return; - g_renderer->ScaleTexture(m_frame_dump_render_framebuffer.get(), - m_frame_dump_render_framebuffer->GetRect(), src_texture, src_rect); + g_gfx->ScaleTexture(m_frame_dump_render_framebuffer.get(), + m_frame_dump_render_framebuffer->GetRect(), src_texture, src_rect); src_texture = m_frame_dump_render_texture.get(); copy_rect = src_texture->GetRect(); } @@ -79,7 +80,7 @@ bool FrameDumper::CheckFrameDumpRenderTexture(u32 target_width, u32 target_heigh // Recreate texture, but release before creating so we don't temporarily use twice the RAM. m_frame_dump_render_framebuffer.reset(); m_frame_dump_render_texture.reset(); - m_frame_dump_render_texture = g_renderer->CreateTexture( + m_frame_dump_render_texture = g_gfx->CreateTexture( TextureConfig(target_width, target_height, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_RenderTarget), "Frame dump render texture"); @@ -89,7 +90,7 @@ bool FrameDumper::CheckFrameDumpRenderTexture(u32 target_width, u32 target_heigh return false; } m_frame_dump_render_framebuffer = - g_renderer->CreateFramebuffer(m_frame_dump_render_texture.get(), nullptr); + g_gfx->CreateFramebuffer(m_frame_dump_render_texture.get(), nullptr); ASSERT(m_frame_dump_render_framebuffer); return true; } @@ -101,7 +102,7 @@ bool FrameDumper::CheckFrameDumpReadbackTexture(u32 target_width, u32 target_hei return true; rbtex.reset(); - rbtex = g_renderer->CreateStagingTexture( + rbtex = g_gfx->CreateStagingTexture( StagingTextureType::Readback, TextureConfig(target_width, target_height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0)); if (!rbtex) diff --git a/Source/Core/VideoCommon/FramebufferManager.cpp b/Source/Core/VideoCommon/FramebufferManager.cpp index f025b2dfde..861536813e 100644 --- a/Source/Core/VideoCommon/FramebufferManager.cpp +++ b/Source/Core/VideoCommon/FramebufferManager.cpp @@ -11,6 +11,7 @@ #include "Common/MsgHandler.h" #include "Core/Config/GraphicsSettings.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractShader.h" #include "VideoCommon/AbstractStagingTexture.h" @@ -171,17 +172,17 @@ bool FramebufferManager::CreateEFBFramebuffer() const TextureConfig efb_depth_texture_config = GetEFBDepthTextureConfig(); // 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 +192,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 +202,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 +211,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 +220,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 +246,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& region) @@ -270,15 +271,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 +299,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 +323,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(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(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 +343,7 @@ bool FramebufferManager::CompileConversionPipelines() for (u32 i = 0; i < NUM_EFB_REINTERPRET_TYPES; i++) { EFBReinterpretType convtype = static_cast(i); - std::unique_ptr pixel_shader = g_renderer->CreateShaderFromSource( + std::unique_ptr pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateFormatConversionShader(convtype, GetEFBSamples()), fmt::format("Framebuffer conversion pixel shader {}", convtype)); @@ -358,7 +359,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 +494,7 @@ void FramebufferManager::RefreshPeekCache() if (flush_command_buffer) { - g_renderer->Flush(); + g_gfx->Flush(); } } @@ -562,33 +563,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 +597,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 +615,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; @@ -635,12 +636,12 @@ bool FramebufferManager::CreateReadbackFramebuffer() 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; } @@ -657,21 +658,21 @@ bool FramebufferManager::CreateReadbackFramebuffer() 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) @@ -737,7 +738,7 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index, bool async // 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 +749,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(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(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 +763,7 @@ void FramebufferManager::PopulateEFBCache(bool depth, u32 tile_index, bool async data.texture.get(), MathUtil::Rectangle(0, 0, rect.GetWidth(), rect.GetHeight()), 0, 0, rect); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); } else { @@ -790,7 +790,7 @@ void FramebufferManager::ClearEFB(const MathUtil::Rectangle& rc, bool clear { FlushEFBPokes(); FlagPeekCacheAsOutOfDate(); - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); // Set up uniforms. struct Uniforms @@ -809,17 +809,17 @@ void FramebufferManager::ClearEFB(const MathUtil::Rectangle& rc, bool clear 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(); + const auto target_rc = g_gfx->ConvertFramebufferRectangle(g_renderer->ConvertEFBRectangle(rc), + m_efb_framebuffer.get()); + g_gfx->SetPipeline(m_efb_clear_pipelines[clear_color][clear_alpha][clear_z].get()); + g_gfx->SetViewportAndScissor(target_rc); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); } 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) @@ -848,7 +848,7 @@ bool FramebufferManager::CompileClearPipelines() config.depth_state.updateenable = depth_enable != 0; m_efb_clear_pipelines[color_enable][alpha_enable][depth_enable] = - g_renderer->CreatePipeline(config); + g_gfx->CreatePipeline(config); if (!m_efb_clear_pipelines[color_enable][alpha_enable][depth_enable]) return false; } @@ -957,17 +957,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(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 +985,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 +1007,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; @@ -1077,9 +1077,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 +1089,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(); } diff --git a/Source/Core/VideoCommon/OnScreenUI.cpp b/Source/Core/VideoCommon/OnScreenUI.cpp index 72f0c8f08a..291f0c23e2 100644 --- a/Source/Core/VideoCommon/OnScreenUI.cpp +++ b/Source/Core/VideoCommon/OnScreenUI.cpp @@ -10,6 +10,7 @@ #include "Core/Config/NetplaySettings.h" #include "Core/Movie.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractShader.h" #include "VideoCommon/FramebufferShaderGen.h" @@ -18,7 +19,6 @@ #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/PerformanceMetrics.h" #include "VideoCommon/Present.h" -#include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VideoConfig.h" @@ -61,7 +61,7 @@ bool OnScreenUI::Initialize(u32 width, u32 height, float scale) vdecl.texcoords[0] = {ComponentFormat::Float, 2, offsetof(ImDrawVert, uv), true, false}; vdecl.colors[0] = {ComponentFormat::UByte, 4, offsetof(ImDrawVert, col), true, false}; vdecl.stride = sizeof(ImDrawVert); - m_imgui_vertex_format = g_renderer->CreateNativeVertexFormat(vdecl); + m_imgui_vertex_format = g_gfx->CreateNativeVertexFormat(vdecl); if (!m_imgui_vertex_format) { PanicAlertFmt("Failed to create ImGui vertex format"); @@ -78,7 +78,7 @@ bool OnScreenUI::Initialize(u32 width, u32 height, float scale) TextureConfig font_tex_config(font_tex_width, font_tex_height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0); std::unique_ptr font_tex = - g_renderer->CreateTexture(font_tex_config, "ImGui font texture"); + g_gfx->CreateTexture(font_tex_config, "ImGui font texture"); if (!font_tex) { PanicAlertFmt("Failed to create ImGui texture"); @@ -120,10 +120,10 @@ bool OnScreenUI::RecompileImGuiPipeline() return true; } - std::unique_ptr vertex_shader = g_renderer->CreateShaderFromSource( + std::unique_ptr vertex_shader = g_gfx->CreateShaderFromSource( ShaderStage::Vertex, FramebufferShaderGen::GenerateImGuiVertexShader(), "ImGui vertex shader"); - std::unique_ptr pixel_shader = g_renderer->CreateShaderFromSource( + std::unique_ptr pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateImGuiPixelShader(), "ImGui pixel shader"); if (!vertex_shader || !pixel_shader) { @@ -133,9 +133,9 @@ bool OnScreenUI::RecompileImGuiPipeline() // GS is used to render the UI to both eyes in stereo modes. std::unique_ptr geometry_shader; - if (g_renderer->UseGeometryShaderForUI()) + if (g_gfx->UseGeometryShaderForUI()) { - geometry_shader = g_renderer->CreateShaderFromSource( + geometry_shader = g_gfx->CreateShaderFromSource( ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 1), "ImGui passthrough geometry shader"); if (!geometry_shader) @@ -163,7 +163,7 @@ bool OnScreenUI::RecompileImGuiPipeline() pconfig.framebuffer_state.samples = 1; pconfig.framebuffer_state.per_sample_shading = false; pconfig.usage = AbstractPipelineUsage::Utility; - m_imgui_pipeline = g_renderer->CreatePipeline(pconfig); + m_imgui_pipeline = g_gfx->CreatePipeline(pconfig); if (!m_imgui_pipeline) { PanicAlertFmt("Failed to create imgui pipeline"); @@ -204,8 +204,8 @@ void OnScreenUI::DrawImGui() if (!draw_data) return; - g_renderer->SetViewport(0.0f, 0.0f, static_cast(m_backbuffer_width), - static_cast(m_backbuffer_height), 0.0f, 1.0f); + g_gfx->SetViewport(0.0f, 0.0f, static_cast(m_backbuffer_width), + static_cast(m_backbuffer_height), 0.0f, 1.0f); // Uniform buffer for draws. struct ImGuiUbo @@ -216,8 +216,8 @@ void OnScreenUI::DrawImGui() ImGuiUbo ubo = {{1.0f / m_backbuffer_width * 2.0f, 1.0f / m_backbuffer_height * 2.0f}}; // Set up common state for drawing. - g_renderer->SetPipeline(m_imgui_pipeline.get()); - g_renderer->SetSamplerState(0, RenderState::GetPointSamplerState()); + g_gfx->SetPipeline(m_imgui_pipeline.get()); + g_gfx->SetSamplerState(0, RenderState::GetPointSamplerState()); g_vertex_manager->UploadUtilityUniforms(&ubo, sizeof(ubo)); for (int i = 0; i < draw_data->CmdListsCount; i++) @@ -239,13 +239,13 @@ void OnScreenUI::DrawImGui() continue; } - g_renderer->SetScissorRect(g_renderer->ConvertFramebufferRectangle( + g_gfx->SetScissorRect(g_gfx->ConvertFramebufferRectangle( MathUtil::Rectangle( static_cast(cmd.ClipRect.x), static_cast(cmd.ClipRect.y), static_cast(cmd.ClipRect.z), static_cast(cmd.ClipRect.w)), - g_renderer->GetCurrentFramebuffer())); - g_renderer->SetTexture(0, reinterpret_cast(cmd.TextureId)); - g_renderer->DrawIndexed(base_index, cmd.ElemCount, base_vertex); + g_gfx->GetCurrentFramebuffer())); + g_gfx->SetTexture(0, reinterpret_cast(cmd.TextureId)); + g_gfx->DrawIndexed(base_index, cmd.ElemCount, base_vertex); base_index += cmd.ElemCount; } } @@ -255,9 +255,9 @@ void OnScreenUI::DrawImGui() // itself will be clipped to whatever bounds were last set by ImGui, resulting in a rather useless // capture whenever any ImGui windows are open. We'll reset the scissor rectangle to the entire // viewport here to avoid this problem. - g_renderer->SetScissorRect(g_renderer->ConvertFramebufferRectangle( + g_gfx->SetScissorRect(g_gfx->ConvertFramebufferRectangle( MathUtil::Rectangle(0, 0, m_backbuffer_width, m_backbuffer_height), - g_renderer->GetCurrentFramebuffer())); + g_gfx->GetCurrentFramebuffer())); } // Create On-Screen-Messages diff --git a/Source/Core/VideoCommon/PostProcessing.cpp b/Source/Core/VideoCommon/PostProcessing.cpp index f14b8f892b..7f4faed582 100644 --- a/Source/Core/VideoCommon/PostProcessing.cpp +++ b/Source/Core/VideoCommon/PostProcessing.cpp @@ -20,12 +20,12 @@ #include "Common/StringUtil.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractPipeline.h" #include "VideoCommon/AbstractShader.h" #include "VideoCommon/AbstractTexture.h" #include "VideoCommon/FramebufferManager.h" #include "VideoCommon/Present.h" -#include "VideoCommon/RenderBase.h" #include "VideoCommon/ShaderCache.h" #include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VideoCommon.h" @@ -417,9 +417,9 @@ void PostProcessing::BlitFromTexture(const MathUtil::Rectangle& dst, const MathUtil::Rectangle& src, const AbstractTexture* src_tex, int src_layer) { - if (g_renderer->GetCurrentFramebuffer()->GetColorFormat() != m_framebuffer_format) + if (g_gfx->GetCurrentFramebuffer()->GetColorFormat() != m_framebuffer_format) { - m_framebuffer_format = g_renderer->GetCurrentFramebuffer()->GetColorFormat(); + m_framebuffer_format = g_gfx->GetCurrentFramebuffer()->GetColorFormat(); RecompilePipeline(); } @@ -430,12 +430,12 @@ void PostProcessing::BlitFromTexture(const MathUtil::Rectangle& dst, g_vertex_manager->UploadUtilityUniforms(m_uniform_staging_buffer.data(), static_cast(m_uniform_staging_buffer.size())); - g_renderer->SetViewportAndScissor( - g_renderer->ConvertFramebufferRectangle(dst, g_renderer->GetCurrentFramebuffer())); - g_renderer->SetPipeline(m_pipeline.get()); - g_renderer->SetTexture(0, src_tex); - g_renderer->SetSamplerState(0, RenderState::GetLinearSamplerState()); - g_renderer->Draw(0, 3); + g_gfx->SetViewportAndScissor( + g_gfx->ConvertFramebufferRectangle(dst, g_gfx->GetCurrentFramebuffer())); + g_gfx->SetPipeline(m_pipeline.get()); + g_gfx->SetTexture(0, src_tex); + g_gfx->SetSamplerState(0, RenderState::GetLinearSamplerState()); + g_gfx->Draw(0, 3); } std::string PostProcessing::GetUniformBufferHeader() const @@ -598,8 +598,8 @@ bool PostProcessing::CompileVertexShader() ss << "}\n"; - m_vertex_shader = g_renderer->CreateShaderFromSource(ShaderStage::Vertex, ss.str(), - "Post-processing vertex shader"); + m_vertex_shader = + g_gfx->CreateShaderFromSource(ShaderStage::Vertex, ss.str(), "Post-processing vertex shader"); if (!m_vertex_shader) { PanicAlertFmt("Failed to compile post-processing vertex shader"); @@ -688,7 +688,7 @@ bool PostProcessing::CompilePixelShader() // Generate GLSL and compile the new shader. m_config.LoadShader(g_ActiveConfig.sPostProcessingShader); - m_pixel_shader = g_renderer->CreateShaderFromSource( + m_pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, GetHeader() + m_config.GetShaderCode() + GetFooter(), fmt::format("Post-processing pixel shader: {}", m_config.GetShader())); if (!m_pixel_shader) @@ -697,7 +697,7 @@ bool PostProcessing::CompilePixelShader() // Use default shader. m_config.LoadDefaultShader(); - m_pixel_shader = g_renderer->CreateShaderFromSource( + m_pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, GetHeader() + m_config.GetShaderCode() + GetFooter(), "Default post-processing pixel shader"); if (!m_pixel_shader) @@ -716,14 +716,14 @@ bool PostProcessing::CompilePipeline() AbstractPipelineConfig config = {}; config.vertex_shader = m_vertex_shader.get(); config.geometry_shader = - g_renderer->UseGeometryShaderForUI() ? g_shader_cache->GetTexcoordGeometryShader() : nullptr; + g_gfx->UseGeometryShaderForUI() ? g_shader_cache->GetTexcoordGeometryShader() : nullptr; config.pixel_shader = m_pixel_shader.get(); config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles); config.depth_state = RenderState::GetNoDepthTestingDepthState(); config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = RenderState::GetColorFramebufferState(m_framebuffer_format); config.usage = AbstractPipelineUsage::Utility; - m_pipeline = g_renderer->CreatePipeline(config); + m_pipeline = g_gfx->CreatePipeline(config); if (!m_pipeline) return false; diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp index 5cddf38aa3..8f10707d0d 100644 --- a/Source/Core/VideoCommon/Present.cpp +++ b/Source/Core/VideoCommon/Present.cpp @@ -8,6 +8,7 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/FrameDumper.h" #include "VideoCommon/OnScreenUI.h" #include "VideoCommon/PostProcessing.h" @@ -47,6 +48,9 @@ bool Presenter::Initialize() if (!m_onscreen_ui->Initialize(m_backbuffer_width, m_backbuffer_height, m_backbuffer_scale)) return false; + if (!g_gfx->IsHeadless()) + SetBackbuffer(g_gfx->GetSurfaceInfo()); + return true; } @@ -57,13 +61,12 @@ void Presenter::SetBackbuffer(int backbuffer_width, int backbuffer_height) UpdateDrawRectangle(); } -void Presenter::SetBackbuffer(int backbuffer_width, int backbuffer_height, float backbuffer_scale, - AbstractTextureFormat backbuffer_format) +void Presenter::SetBackbuffer(SurfaceInfo info) { - m_backbuffer_width = backbuffer_width; - m_backbuffer_height = backbuffer_height; - m_backbuffer_scale = backbuffer_scale; - m_backbuffer_format = backbuffer_format; + m_backbuffer_width = info.width; + m_backbuffer_height = info.height; + m_backbuffer_scale = info.scale; + m_backbuffer_format = info.format; UpdateDrawRectangle(); } @@ -74,14 +77,14 @@ void Presenter::CheckForConfigChanges(u32 changed_bits) if (m_post_processor->GetConfig()->GetShader() != g_ActiveConfig.sPostProcessingShader) { // The existing shader must not be in use when it's destroyed - g_renderer->WaitForGPUIdle(); + g_gfx->WaitForGPUIdle(); m_post_processor->RecompileShader(); } // Stereo mode change requires recompiling our post processing pipeline and imgui pipelines for // rendering the UI. - if (changed_bits & Renderer::ConfigChangeBits::CONFIG_CHANGE_BIT_STEREO_MODE) + if (changed_bits & ConfigChangeBits::CONFIG_CHANGE_BIT_STEREO_MODE) { m_onscreen_ui->RecompileImGuiPipeline(); m_post_processor->RecompilePipeline(); @@ -90,24 +93,24 @@ void Presenter::CheckForConfigChanges(u32 changed_bits) void Presenter::BeginUIFrame() { - if (g_renderer->IsHeadless()) + if (g_gfx->IsHeadless()) return; - g_renderer->BeginUtilityDrawing(); - g_renderer->BindBackbuffer({0.0f, 0.0f, 0.0f, 1.0f}); + g_gfx->BeginUtilityDrawing(); + g_gfx->BindBackbuffer({0.0f, 0.0f, 0.0f, 1.0f}); } void Presenter::EndUIFrame() { m_onscreen_ui->Finalize(); - if (g_renderer->IsHeadless()) + if (g_gfx->IsHeadless()) { m_onscreen_ui->DrawImGui(); std::lock_guard guard(m_swap_mutex); - g_renderer->PresentBackbuffer(); - g_renderer->EndUtilityDrawing(); + g_gfx->PresentBackbuffer(); + g_gfx->EndUtilityDrawing(); } m_onscreen_ui->BeginImGuiFrame(m_backbuffer_width, m_backbuffer_height); @@ -392,7 +395,7 @@ void Presenter::RenderXFBToScreen(const MathUtil::Rectangle& target_rc, { if (!g_ActiveConfig.backend_info.bSupportsPostProcessing) { - g_renderer->ShowImage(source_texture, source_rc); + g_gfx->ShowImage(source_texture, source_rc); return; } @@ -400,13 +403,13 @@ void Presenter::RenderXFBToScreen(const MathUtil::Rectangle& target_rc, g_ActiveConfig.backend_info.bUsesExplictQuadBuffering) { // Quad-buffered stereo is annoying on GL. - g_renderer->SelectLeftBuffer(); + g_gfx->SelectLeftBuffer(); m_post_processor->BlitFromTexture(target_rc, source_rc, source_texture, 0); - g_renderer->SelectRightBuffer(); + g_gfx->SelectRightBuffer(); m_post_processor->BlitFromTexture(target_rc, source_rc, source_texture, 1); - g_renderer->SelectMainBuffer(); + g_gfx->SelectMainBuffer(); } else if (g_ActiveConfig.stereo_mode == StereoMode::SBS || g_ActiveConfig.stereo_mode == StereoMode::TAB) @@ -436,7 +439,7 @@ bool Presenter::SubmitXFB(RcTcacheEntry xfb_entry, MathUtil::Rectangle& xfb if (g_frame_dumper->IsFrameDumping()) { MathUtil::Rectangle target_rect; - if (!g_ActiveConfig.bInternalResolutionFrameDumps && !g_renderer->IsHeadless()) + if (!g_ActiveConfig.bInternalResolutionFrameDumps && !g_gfx->IsHeadless()) { target_rect = GetTargetRectangle(); } @@ -469,10 +472,10 @@ void Presenter::Present() m_onscreen_ui->Finalize(); // Render the XFB to the screen. - g_renderer->BeginUtilityDrawing(); - if (!g_renderer->IsHeadless()) + g_gfx->BeginUtilityDrawing(); + if (!g_gfx->IsHeadless()) { - g_renderer->BindBackbuffer({{0.0f, 0.0f, 0.0f, 1.0f}}); + g_gfx->BindBackbuffer({{0.0f, 0.0f, 0.0f, 1.0f}}); UpdateDrawRectangle(); @@ -488,7 +491,7 @@ void Presenter::Present() // Present to the window system. { std::lock_guard guard(m_swap_mutex); - g_renderer->PresentBackbuffer(); + g_gfx->PresentBackbuffer(); } // Update the window size based on the frame that was just rendered. @@ -498,7 +501,7 @@ void Presenter::Present() m_onscreen_ui->BeginImGuiFrame(m_backbuffer_width, m_backbuffer_height); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); } void Presenter::SetKeyMap(std::span> key_map) diff --git a/Source/Core/VideoCommon/Present.h b/Source/Core/VideoCommon/Present.h index 5f535f7208..3b99c3207d 100644 --- a/Source/Core/VideoCommon/Present.h +++ b/Source/Core/VideoCommon/Present.h @@ -16,6 +16,7 @@ #include class AbstractTexture; +struct SurfaceInfo; namespace VideoCommon { @@ -51,8 +52,7 @@ public: AbstractTextureFormat GetBackbufferFormat() const { return m_backbuffer_format; } void SetWindowSize(int width, int height); void SetBackbuffer(int backbuffer_width, int backbuffer_height); - void SetBackbuffer(int backbuffer_width, int backbuffer_height, float backbuffer_scale, - AbstractTextureFormat backbuffer_format); + void SetBackbuffer(SurfaceInfo info); void UpdateDrawRectangle(); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 86725f534e..ec5f25267f 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -38,6 +38,7 @@ #include "Core/System.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractTexture.h" #include "VideoCommon/BoundingBox.h" #include "VideoCommon/CommandProcessor.h" @@ -59,17 +60,12 @@ std::unique_ptr g_renderer; -Renderer::Renderer(int backbuffer_width, int backbuffer_height, float backbuffer_scale, - AbstractTextureFormat backbuffer_format) - : m_last_xfb_width{MAX_XFB_WIDTH}, m_last_xfb_height{MAX_XFB_HEIGHT} +Renderer::Renderer() : m_last_xfb_width{MAX_XFB_WIDTH}, m_last_xfb_height{MAX_XFB_HEIGHT} { UpdateActiveConfig(); FreeLook::UpdateActiveConfig(); CalculateTargetSize(); - g_presenter->SetBackbuffer(backbuffer_width, backbuffer_height, backbuffer_scale, - backbuffer_format); - m_is_game_widescreen = SConfig::GetInstance().bWii && Config::Get(Config::SYSCONF_WIDESCREEN); g_freelook_camera.SetControlType(FreeLook::GetActiveConfig().camera_config.control_type); } @@ -78,13 +74,6 @@ Renderer::~Renderer() = default; bool Renderer::Initialize() { - m_bounding_box = CreateBoundingBox(); - if (g_ActiveConfig.backend_info.bSupportsBBox && !m_bounding_box->Initialize()) - { - PanicAlertFmt("Failed to initialize bounding box."); - return false; - } - if (g_ActiveConfig.bGraphicMods) { // If a config change occurred in a previous session, @@ -101,12 +90,12 @@ bool Renderer::Initialize() m_graphics_mod_manager.Load(*g_ActiveConfig.graphics_mod_config); } - return g_presenter->Initialize(); + return true; } void Renderer::Shutdown() { - m_bounding_box.reset(); + g_bounding_box.reset(); } void Renderer::BeginUtilityDrawing() @@ -121,31 +110,38 @@ void Renderer::EndUtilityDrawing() BPFunctions::SetScissorAndViewport(); } -void Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer) -{ - m_current_framebuffer = framebuffer; -} - -void Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) -{ - m_current_framebuffer = framebuffer; -} - -void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, - const ClearColor& color_value, float depth_value) -{ - m_current_framebuffer = framebuffer; -} - bool Renderer::EFBHasAlphaChannel() const { return m_prev_efb_format == PixelFormat::RGBA6_Z24; } -void Renderer::ClearScreen(const MathUtil::Rectangle& rc, bool colorEnable, bool alphaEnable, - bool zEnable, u32 color, u32 z) +void Renderer::ClearScreen(const MathUtil::Rectangle& rc, bool color_enable, bool alpha_enable, + bool z_enable, u32 color, u32 z) { - g_framebuffer_manager->ClearEFB(rc, colorEnable, alphaEnable, zEnable, color, z); + g_framebuffer_manager->FlushEFBPokes(); + g_framebuffer_manager->FlagPeekCacheAsOutOfDate(); + + // Native -> EFB coordinates + MathUtil::Rectangle target_rc = Renderer::ConvertEFBRectangle(rc); + target_rc.ClampUL(0, 0, m_target_width, m_target_height); + + // 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) + { + // Force alpha writes, and clear the alpha channel. + alpha_enable = true; + color &= 0x00FFFFFF; + } + + g_gfx->ClearRegion(rc, target_rc, color_enable, alpha_enable, z_enable, color, z); + + // Scissor rect must be restored. + BPFunctions::SetScissorAndViewport(); } void Renderer::ReinterpretPixelData(EFBReinterpretType convtype) @@ -155,17 +151,17 @@ void Renderer::ReinterpretPixelData(EFBReinterpretType convtype) bool Renderer::IsBBoxEnabled() const { - return m_bounding_box->IsEnabled(); + return g_bounding_box->IsEnabled(); } void Renderer::BBoxEnable(PixelShaderManager& pixel_shader_manager) { - m_bounding_box->Enable(pixel_shader_manager); + g_bounding_box->Enable(pixel_shader_manager); } void Renderer::BBoxDisable(PixelShaderManager& pixel_shader_manager) { - m_bounding_box->Disable(pixel_shader_manager); + g_bounding_box->Disable(pixel_shader_manager); } u16 Renderer::BBoxRead(u32 index) @@ -173,7 +169,7 @@ u16 Renderer::BBoxRead(u32 index) if (!g_ActiveConfig.bBBoxEnable || !g_ActiveConfig.backend_info.bSupportsBBox) return m_bounding_box_fallback[index]; - return m_bounding_box->Get(index); + return g_bounding_box->Get(index); } void Renderer::BBoxWrite(u32 index, u16 value) @@ -184,7 +180,7 @@ void Renderer::BBoxWrite(u32 index, u16 value) return; } - m_bounding_box->Set(index, value); + g_bounding_box->Set(index, value); } void Renderer::BBoxFlush() @@ -192,7 +188,7 @@ void Renderer::BBoxFlush() if (!g_ActiveConfig.bBBoxEnable || !g_ActiveConfig.backend_info.bSupportsBBox) return; - m_bounding_box->Flush(); + g_bounding_box->Flush(); } u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) @@ -436,13 +432,13 @@ void Renderer::CheckForConfigChanges() return; // Notify the backend of the changes, if any. - OnConfigChanged(changed_bits); + g_gfx->OnConfigChanged(changed_bits); // If there's any shader changes, wait for the GPU to finish before destroying anything. if (changed_bits & (CONFIG_CHANGE_BIT_HOST_CONFIG | CONFIG_CHANGE_BIT_MULTISAMPLES)) { - WaitForGPUIdle(); - SetPipeline(nullptr); + g_gfx->WaitForGPUIdle(); + g_gfx->SetPipeline(nullptr); } // Framebuffer changed? @@ -469,81 +465,6 @@ void Renderer::CheckForConfigChanges() } } -bool Renderer::IsHeadless() const -{ - return true; -} - -void Renderer::SetViewportAndScissor(const MathUtil::Rectangle& rect, float min_depth, - float max_depth) -{ - SetViewport(static_cast(rect.left), static_cast(rect.top), - static_cast(rect.GetWidth()), static_cast(rect.GetHeight()), min_depth, - max_depth); - SetScissorRect(rect); -} - -void Renderer::ScaleTexture(AbstractFramebuffer* dst_framebuffer, - const MathUtil::Rectangle& dst_rect, - const AbstractTexture* src_texture, - const MathUtil::Rectangle& src_rect) -{ - ASSERT(dst_framebuffer->GetColorFormat() == AbstractTextureFormat::RGBA8); - - BeginUtilityDrawing(); - - // The shader needs to know the source rectangle. - const auto converted_src_rect = - ConvertFramebufferRectangle(src_rect, src_texture->GetWidth(), src_texture->GetHeight()); - const float rcp_src_width = 1.0f / src_texture->GetWidth(); - const float rcp_src_height = 1.0f / src_texture->GetHeight(); - const std::array uniforms = {{converted_src_rect.left * rcp_src_width, - converted_src_rect.top * rcp_src_height, - converted_src_rect.GetWidth() * rcp_src_width, - converted_src_rect.GetHeight() * rcp_src_height}}; - g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - - // Discard if we're overwriting the whole thing. - if (static_cast(dst_rect.GetWidth()) == dst_framebuffer->GetWidth() && - static_cast(dst_rect.GetHeight()) == dst_framebuffer->GetHeight()) - { - SetAndDiscardFramebuffer(dst_framebuffer); - } - else - { - SetFramebuffer(dst_framebuffer); - } - - SetViewportAndScissor(ConvertFramebufferRectangle(dst_rect, dst_framebuffer)); - SetPipeline(dst_framebuffer->GetLayers() > 1 ? g_shader_cache->GetRGBA8StereoCopyPipeline() : - g_shader_cache->GetRGBA8CopyPipeline()); - SetTexture(0, src_texture); - SetSamplerState(0, RenderState::GetLinearSamplerState()); - Draw(0, 3); - EndUtilityDrawing(); - if (dst_framebuffer->GetColorAttachment()) - dst_framebuffer->GetColorAttachment()->FinishedRendering(); -} - -MathUtil::Rectangle -Renderer::ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, - const AbstractFramebuffer* framebuffer) const -{ - return ConvertFramebufferRectangle(rect, framebuffer->GetWidth(), framebuffer->GetHeight()); -} - -MathUtil::Rectangle Renderer::ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, - u32 fb_width, u32 fb_height) const -{ - MathUtil::Rectangle ret = rect; - if (g_ActiveConfig.backend_info.bUsesLowerLeftOrigin) - { - ret.top = fb_height - rect.bottom; - ret.bottom = fb_height - rect.top; - } - return ret; -} - MathUtil::Rectangle Renderer::ConvertEFBRectangle(const MathUtil::Rectangle& rc) const { MathUtil::Rectangle result; @@ -590,14 +511,6 @@ void Renderer::RecordVideoMemory() texMem); } -bool Renderer::UseGeometryShaderForUI() const -{ - // OpenGL doesn't render to a 2-layer backbuffer like D3D/Vulkan for quad-buffered stereo, - // instead drawing twice and the eye selected by glDrawBuffer() (see Presenter::RenderXFBToScreen) - return g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer && - g_ActiveConfig.backend_info.api_type != APIType::OpenGL; -} - void Renderer::ForceReloadTextures() { m_force_reload_textures.Set(); @@ -756,7 +669,7 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6 } else { - Flush(); + g_gfx->Flush(); } // Update our last xfb values @@ -768,7 +681,7 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6 } else { - Flush(); + g_gfx->Flush(); } } @@ -803,7 +716,7 @@ void Renderer::DoState(PointerWrap& p) p.Do(m_last_xfb_height); p.DoArray(m_bounding_box_fallback); - m_bounding_box->DoState(p); + g_bounding_box->DoState(p); if (p.IsReadMode()) { @@ -821,11 +734,6 @@ void Renderer::DoState(PointerWrap& p) #endif } -std::unique_ptr Renderer::CreateAsyncShaderCompiler() -{ - return std::make_unique(); -} - const GraphicsModManager& Renderer::GetGraphicsModManager() const { return m_graphics_mod_manager; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 17fe407618..fb88dfd1eb 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -64,100 +64,18 @@ struct EfbPokeData class Renderer { public: - Renderer(int backbuffer_width, int backbuffer_height, float backbuffer_scale, - AbstractTextureFormat backbuffer_format); + Renderer(); virtual ~Renderer(); - using ClearColor = std::array; - - virtual bool IsHeadless() const = 0; - virtual bool Initialize(); virtual void Shutdown(); - virtual void SetPipeline(const AbstractPipeline* pipeline) {} - virtual void SetScissorRect(const MathUtil::Rectangle& rc) {} - virtual void SetTexture(u32 index, const AbstractTexture* texture) {} - virtual void SetSamplerState(u32 index, const SamplerState& state) {} - virtual void SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) {} - virtual void UnbindTexture(const AbstractTexture* texture) {} - virtual void SetViewport(float x, float y, float width, float height, float near_depth, - float far_depth) - { - } - virtual void SetFullscreen(bool enable_fullscreen) {} - virtual bool IsFullscreen() const { return false; } - virtual void BeginUtilityDrawing(); - virtual void EndUtilityDrawing(); - virtual std::unique_ptr CreateTexture(const TextureConfig& config, - std::string_view name = "") = 0; - virtual std::unique_ptr - CreateStagingTexture(StagingTextureType type, const TextureConfig& config) = 0; - virtual std::unique_ptr - CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) = 0; - - // Framebuffer operations. - virtual void SetFramebuffer(AbstractFramebuffer* framebuffer); - virtual void SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer); - virtual void SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, - const ClearColor& color_value = {}, float depth_value = 0.0f); - - // Drawing with currently-bound pipeline state. - virtual void Draw(u32 base_vertex, u32 num_vertices) {} - virtual void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) {} - - // Dispatching compute shaders with currently-bound state. - virtual void DispatchComputeShader(const AbstractShader* shader, u32 groupsize_x, u32 groupsize_y, - u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z) - { - } - - // Binds the backbuffer for rendering. The buffer will be cleared immediately after binding. - // This is where any window size changes are detected, therefore m_backbuffer_width and/or - // m_backbuffer_height may change after this function returns. - virtual void BindBackbuffer(const ClearColor& clear_color = {}) {} - - // Presents the backbuffer to the window system, or "swaps buffers". - virtual void PresentBackbuffer() {} - - // Shader modules/objects. - virtual std::unique_ptr CreateShaderFromSource(ShaderStage stage, - std::string_view source, - std::string_view name = "") = 0; - virtual std::unique_ptr CreateShaderFromBinary(ShaderStage stage, - const void* data, size_t length, - std::string_view name = "") = 0; - virtual std::unique_ptr - CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) = 0; - virtual std::unique_ptr CreatePipeline(const AbstractPipelineConfig& config, - const void* cache_data = nullptr, - size_t cache_data_length = 0) = 0; - - AbstractFramebuffer* GetCurrentFramebuffer() const { return m_current_framebuffer; } - + void BeginUtilityDrawing(); + void EndUtilityDrawing(); // Ideal internal resolution - multiple of the native EFB resolution int GetTargetWidth() const { return m_target_width; } int GetTargetHeight() const { return m_target_height; } - // Sets viewport and scissor to the specified rectangle. rect is assumed to be in framebuffer - // coordinates, i.e. lower-left origin in OpenGL. - void SetViewportAndScissor(const MathUtil::Rectangle& rect, float min_depth = 0.0f, - float max_depth = 1.0f); - - // Scales a GPU texture using a copy shader. - virtual void ScaleTexture(AbstractFramebuffer* dst_framebuffer, - const MathUtil::Rectangle& dst_rect, - const AbstractTexture* src_texture, - const MathUtil::Rectangle& src_rect); - - // Converts an upper-left to lower-left if required by the backend, optionally - // clamping to the framebuffer size. - MathUtil::Rectangle ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, - u32 fb_width, u32 fb_height) const; - MathUtil::Rectangle - ConvertFramebufferRectangle(const MathUtil::Rectangle& rect, - const AbstractFramebuffer* framebuffer) const; - // EFB coordinate conversion functions // Use this to convert a whole native EFB rect to backbuffer coordinates MathUtil::Rectangle ConvertEFBRectangle(const MathUtil::Rectangle& rc) const; @@ -188,29 +106,12 @@ public: void BBoxWrite(u32 index, u16 value); void BBoxFlush(); - virtual void Flush() {} - virtual void WaitForGPUIdle() {} - // Finish up the current frame, print some stats void Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks); void UpdateWidescreenHeuristic(); bool IsGameWidescreen() const { return m_is_game_widescreen; } - // A simple presentation fallback, only used by video software - virtual void ShowImage(const AbstractTexture* source_texture, - const MathUtil::Rectangle& source_rc) - { - } - - // For opengl's glDrawBuffer - virtual void SelectLeftBuffer() {} - virtual void SelectRightBuffer() {} - virtual void SelectMainBuffer() {} - - // Called when the configuration changes, and backend structures need to be updated. - virtual void OnConfigChanged(u32 bits) {} - PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; } void StorePixelFormat(PixelFormat new_format) { m_prev_efb_format = new_format; } bool EFBHasAlphaChannel() const; @@ -218,30 +119,11 @@ public: bool UseVertexDepthRange() const; void DoState(PointerWrap& p); - virtual std::unique_ptr CreateAsyncShaderCompiler(); - - // Returns true if a layer-expanding geometry shader should be used when rendering the user - // interface and final XFB. - bool UseGeometryShaderForUI() const; - // Will forcibly reload all textures on the next swap void ForceReloadTextures(); const GraphicsModManager& GetGraphicsModManager() const; - // Bitmask containing information about which configuration has changed for the backend. - enum ConfigChangeBits : u32 - { - CONFIG_CHANGE_BIT_HOST_CONFIG = (1 << 0), - CONFIG_CHANGE_BIT_MULTISAMPLES = (1 << 1), - CONFIG_CHANGE_BIT_STEREO_MODE = (1 << 2), - CONFIG_CHANGE_BIT_TARGET_SIZE = (1 << 3), - CONFIG_CHANGE_BIT_ANISOTROPY = (1 << 4), - CONFIG_CHANGE_BIT_FORCE_TEXTURE_FILTERING = (1 << 5), - CONFIG_CHANGE_BIT_VSYNC = (1 << 6), - CONFIG_CHANGE_BIT_BBOX = (1 << 7) - }; - protected: std::tuple CalculateTargetScale(int x, int y) const; bool CalculateTargetSize(); @@ -251,11 +133,6 @@ protected: void CheckFifoRecording(); void RecordVideoMemory(); - virtual std::unique_ptr CreateBoundingBox() const = 0; - - AbstractFramebuffer* m_current_framebuffer = nullptr; - const AbstractPipeline* m_current_pipeline = nullptr; - bool m_is_game_widescreen = false; bool m_was_orthographically_anamorphic = false; diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 1be1ad1167..b9876dc533 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -10,12 +10,12 @@ #include "Common/MsgHandler.h" #include "Core/ConfigManager.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/ConstantManager.h" #include "VideoCommon/DriverDetails.h" #include "VideoCommon/FramebufferManager.h" #include "VideoCommon/FramebufferShaderGen.h" #include "VideoCommon/Present.h" -#include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexLoaderManager.h" #include "VideoCommon/VertexManagerBase.h" @@ -45,7 +45,7 @@ bool ShaderCache::Initialize() if (!CompileSharedPipelines()) return false; - m_async_shader_compiler = g_renderer->CreateAsyncShaderCompiler(); + m_async_shader_compiler = g_gfx->CreateAsyncShaderCompiler(); return true; } @@ -122,7 +122,7 @@ const AbstractPipeline* ShaderCache::GetPipelineForUid(const GXPipelineUid& uid) std::unique_ptr pipeline; std::optional pipeline_config = GetGXPipelineConfig(uid); if (pipeline_config) - pipeline = g_renderer->CreatePipeline(*pipeline_config); + pipeline = g_gfx->CreatePipeline(*pipeline_config); if (g_ActiveConfig.bShaderCache && !exists_in_cache) AppendGXPipelineUID(uid); return InsertGXPipeline(uid, std::move(pipeline)); @@ -154,7 +154,7 @@ const AbstractPipeline* ShaderCache::GetUberPipelineForUid(const GXUberPipelineU std::unique_ptr pipeline; std::optional pipeline_config = GetGXPipelineConfig(uid); if (pipeline_config) - pipeline = g_renderer->CreatePipeline(*pipeline_config); + pipeline = g_gfx->CreatePipeline(*pipeline_config); return InsertGXUberPipeline(uid, std::move(pipeline)); } @@ -235,7 +235,7 @@ void ShaderCache::LoadShaderCache(T& cache, APIType api_type, const char* type, CacheReader(T& cache_) : cache(cache_) {} void Read(const K& key, const u8* value, u32 value_size) { - auto shader = g_renderer->CreateShaderFromBinary(stage, value, value_size); + auto shader = g_gfx->CreateShaderFromBinary(stage, value, value_size); if (shader) { auto& entry = cache.shader_map[key]; @@ -298,7 +298,7 @@ void ShaderCache::LoadPipelineCache(T& cache, LinearDiskCache& if (!config) return; - auto pipeline = g_renderer->CreatePipeline(*config, value, value_size); + auto pipeline = g_gfx->CreatePipeline(*config, value, value_size); if (!pipeline) { // If any of the pipelines fail to create, consider the cache stale. @@ -435,7 +435,7 @@ std::unique_ptr ShaderCache::CompileVertexShader(const VertexSha { const ShaderCode source_code = GenerateVertexShaderCode(m_api_type, m_host_config, uid.GetUidData()); - return g_renderer->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer()); + return g_gfx->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer()); } std::unique_ptr @@ -443,15 +443,15 @@ ShaderCache::CompileVertexUberShader(const UberShader::VertexShaderUid& uid) con { const ShaderCode source_code = UberShader::GenVertexShader(m_api_type, m_host_config, uid.GetUidData()); - return g_renderer->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer(), - fmt::to_string(*uid.GetUidData())); + return g_gfx->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer(), + fmt::to_string(*uid.GetUidData())); } std::unique_ptr ShaderCache::CompilePixelShader(const PixelShaderUid& uid) const { const ShaderCode source_code = GeneratePixelShaderCode(m_api_type, m_host_config, uid.GetUidData()); - return g_renderer->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer()); + return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer()); } std::unique_ptr @@ -459,8 +459,8 @@ ShaderCache::CompilePixelUberShader(const UberShader::PixelShaderUid& uid) const { const ShaderCode source_code = UberShader::GenPixelShader(m_api_type, m_host_config, uid.GetUidData()); - return g_renderer->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(), - fmt::to_string(*uid.GetUidData())); + return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(), + fmt::to_string(*uid.GetUidData())); } const AbstractShader* ShaderCache::InsertVertexShader(const VertexShaderUid& uid, @@ -556,8 +556,8 @@ const AbstractShader* ShaderCache::CreateGeometryShader(const GeometryShaderUid& const ShaderCode source_code = GenerateGeometryShaderCode(m_api_type, m_host_config, uid.GetUidData()); std::unique_ptr shader = - g_renderer->CreateShaderFromSource(ShaderStage::Geometry, source_code.GetBuffer(), - fmt::format("Geometry shader: {}", *uid.GetUidData())); + g_gfx->CreateShaderFromSource(ShaderStage::Geometry, source_code.GetBuffer(), + fmt::format("Geometry shader: {}", *uid.GetUidData())); auto& entry = m_gs_cache.shader_map[uid]; entry.pending = false; @@ -1159,7 +1159,7 @@ void ShaderCache::QueuePipelineCompile(const GXPipelineUid& uid, u32 priority) bool Compile() override { if (config) - pipeline = g_renderer->CreatePipeline(*config); + pipeline = g_gfx->CreatePipeline(*config); return true; } @@ -1234,7 +1234,7 @@ void ShaderCache::QueueUberPipelineCompile(const GXUberPipelineUid& uid, u32 pri bool Compile() override { if (config) - UberPipeline = g_renderer->CreatePipeline(*config); + UberPipeline = g_gfx->CreatePipeline(*config); return true; } @@ -1372,7 +1372,7 @@ ShaderCache::GetEFBCopyToVRAMPipeline(const TextureConversionShaderGen::TCShader return iter->second.get(); auto shader_code = TextureConversionShaderGen::GeneratePixelShader(m_api_type, uid.GetUidData()); - auto shader = g_renderer->CreateShaderFromSource( + auto shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, shader_code.GetBuffer(), fmt::format("EFB copy to VRAM pixel shader: {}", *uid.GetUidData())); if (!shader) @@ -1392,7 +1392,7 @@ ShaderCache::GetEFBCopyToVRAMPipeline(const TextureConversionShaderGen::TCShader config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = RenderState::GetRGBA8FramebufferState(); config.usage = AbstractPipelineUsage::Utility; - auto iiter = m_efb_copy_to_vram_pipelines.emplace(uid, g_renderer->CreatePipeline(config)); + auto iiter = m_efb_copy_to_vram_pipelines.emplace(uid, g_gfx->CreatePipeline(config)); return iiter.first->second.get(); } @@ -1404,7 +1404,7 @@ const AbstractPipeline* ShaderCache::GetEFBCopyToRAMPipeline(const EFBCopyParams const std::string shader_code = TextureConversionShaderTiled::GenerateEncodingShader(uid, m_api_type); - const auto shader = g_renderer->CreateShaderFromSource( + const auto shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, shader_code, fmt::format("EFB copy to RAM pixel shader: {}", uid)); if (!shader) { @@ -1420,19 +1420,19 @@ const AbstractPipeline* ShaderCache::GetEFBCopyToRAMPipeline(const EFBCopyParams config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = RenderState::GetColorFramebufferState(AbstractTextureFormat::BGRA8); config.usage = AbstractPipelineUsage::Utility; - auto iiter = m_efb_copy_to_ram_pipelines.emplace(uid, g_renderer->CreatePipeline(config)); + auto iiter = m_efb_copy_to_ram_pipelines.emplace(uid, g_gfx->CreatePipeline(config)); return iiter.first->second.get(); } bool ShaderCache::CompileSharedPipelines() { - m_screen_quad_vertex_shader = g_renderer->CreateShaderFromSource( + m_screen_quad_vertex_shader = g_gfx->CreateShaderFromSource( ShaderStage::Vertex, FramebufferShaderGen::GenerateScreenQuadVertexShader(), "Screen quad vertex shader"); - m_texture_copy_vertex_shader = g_renderer->CreateShaderFromSource( + m_texture_copy_vertex_shader = g_gfx->CreateShaderFromSource( ShaderStage::Vertex, FramebufferShaderGen::GenerateTextureCopyVertexShader(), "Texture copy vertex shader"); - m_efb_copy_vertex_shader = g_renderer->CreateShaderFromSource( + m_efb_copy_vertex_shader = g_gfx->CreateShaderFromSource( ShaderStage::Vertex, TextureConversionShaderGen::GenerateVertexShader(m_api_type).GetBuffer(), "EFB copy vertex shader"); if (!m_screen_quad_vertex_shader || !m_texture_copy_vertex_shader || !m_efb_copy_vertex_shader) @@ -1440,20 +1440,20 @@ bool ShaderCache::CompileSharedPipelines() if (UseGeometryShaderForEFBCopies()) { - m_texcoord_geometry_shader = g_renderer->CreateShaderFromSource( + m_texcoord_geometry_shader = g_gfx->CreateShaderFromSource( ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 0), "Texcoord passthrough geometry shader"); - m_color_geometry_shader = g_renderer->CreateShaderFromSource( + m_color_geometry_shader = g_gfx->CreateShaderFromSource( ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(0, 1), "Color passthrough geometry shader"); if (!m_texcoord_geometry_shader || !m_color_geometry_shader) return false; } - m_texture_copy_pixel_shader = g_renderer->CreateShaderFromSource( + m_texture_copy_pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateTextureCopyPixelShader(), "Texture copy pixel shader"); - m_color_pixel_shader = g_renderer->CreateShaderFromSource( + m_color_pixel_shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, FramebufferShaderGen::GenerateColorPixelShader(), "Color pixel shader"); if (!m_texture_copy_pixel_shader || !m_color_pixel_shader) return false; @@ -1468,14 +1468,14 @@ bool ShaderCache::CompileSharedPipelines() config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = RenderState::GetRGBA8FramebufferState(); config.usage = AbstractPipelineUsage::Utility; - m_copy_rgba8_pipeline = g_renderer->CreatePipeline(config); + m_copy_rgba8_pipeline = g_gfx->CreatePipeline(config); if (!m_copy_rgba8_pipeline) return false; if (UseGeometryShaderForEFBCopies()) { config.geometry_shader = m_texcoord_geometry_shader.get(); - m_rgba8_stereo_copy_pipeline = g_renderer->CreatePipeline(config); + m_rgba8_stereo_copy_pipeline = g_gfx->CreatePipeline(config); if (!m_rgba8_stereo_copy_pipeline) return false; } @@ -1488,7 +1488,7 @@ bool ShaderCache::CompileSharedPipelines() for (size_t i = 0; i < NUM_PALETTE_CONVERSION_SHADERS; i++) { TLUTFormat format = static_cast(i); - auto shader = g_renderer->CreateShaderFromSource( + auto shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, TextureConversionShaderTiled::GeneratePaletteConversionShader(format, m_api_type), fmt::format("Palette conversion pixel shader: {}", format)); @@ -1496,7 +1496,7 @@ bool ShaderCache::CompileSharedPipelines() return false; config.pixel_shader = shader.get(); - m_palette_conversion_pipelines[i] = g_renderer->CreatePipeline(config); + m_palette_conversion_pipelines[i] = g_gfx->CreatePipeline(config); if (!m_palette_conversion_pipelines[i]) return false; } @@ -1527,7 +1527,7 @@ const AbstractPipeline* ShaderCache::GetTextureReinterpretPipeline(TextureFormat return nullptr; } - std::unique_ptr shader = g_renderer->CreateShaderFromSource( + std::unique_ptr shader = g_gfx->CreateShaderFromSource( ShaderStage::Pixel, shader_source, fmt::format("Texture reinterpret pixel shader: {} to {}", from_format, to_format)); if (!shader) @@ -1546,7 +1546,7 @@ const AbstractPipeline* ShaderCache::GetTextureReinterpretPipeline(TextureFormat config.blending_state = RenderState::GetNoBlendingBlendState(); config.framebuffer_state = RenderState::GetRGBA8FramebufferState(); config.usage = AbstractPipelineUsage::Utility; - auto iiter = m_texture_reinterpret_pipelines.emplace(key, g_renderer->CreatePipeline(config)); + auto iiter = m_texture_reinterpret_pipelines.emplace(key, g_gfx->CreatePipeline(config)); return iiter.first->second.get(); } @@ -1574,7 +1574,7 @@ ShaderCache::GetTextureDecodingShader(TextureFormat format, fmt::format("Texture decoding compute shader: {}", format); std::unique_ptr shader = - g_renderer->CreateShaderFromSource(ShaderStage::Compute, shader_source, name); + g_gfx->CreateShaderFromSource(ShaderStage::Compute, shader_source, name); if (!shader) { m_texture_decoding_shaders.emplace(key, nullptr); diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 6102767e70..e991669950 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -34,6 +34,7 @@ #include "Core/System.h" #include "VideoCommon/AbstractFramebuffer.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/FramebufferManager.h" @@ -298,7 +299,7 @@ RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const decoded_entry->SetNotCopy(); decoded_entry->may_have_overlapping_textures = entry->may_have_overlapping_textures; - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); const u32 palette_size = entry->format == TextureFormat::I4 ? 32 : 512; u32 texel_buffer_offset; @@ -318,19 +319,19 @@ RcTcacheEntry TextureCacheBase::ApplyPaletteToEntry(RcTcacheEntry& entry, const uniforms.texel_buffer_offset = texel_buffer_offset; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - g_renderer->SetAndDiscardFramebuffer(decoded_entry->framebuffer.get()); - g_renderer->SetViewportAndScissor(decoded_entry->texture->GetRect()); - g_renderer->SetPipeline(pipeline); - g_renderer->SetTexture(1, entry->texture.get()); - g_renderer->SetSamplerState(1, RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(decoded_entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(decoded_entry->texture->GetRect()); + g_gfx->SetPipeline(pipeline); + g_gfx->SetTexture(1, entry->texture.get()); + g_gfx->SetSamplerState(1, RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); decoded_entry->texture->FinishedRendering(); } else { ERROR_LOG_FMT(VIDEO, "Texel buffer upload of {} bytes failed", palette_size); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); } textures_by_address.emplace(decoded_entry->addr, decoded_entry); @@ -369,14 +370,14 @@ RcTcacheEntry TextureCacheBase::ReinterpretEntry(const RcTcacheEntry& existing_e reinterpreted_entry->may_have_overlapping_textures = existing_entry->may_have_overlapping_textures; - g_renderer->BeginUtilityDrawing(); - g_renderer->SetAndDiscardFramebuffer(reinterpreted_entry->framebuffer.get()); - g_renderer->SetViewportAndScissor(reinterpreted_entry->texture->GetRect()); - g_renderer->SetPipeline(pipeline); - g_renderer->SetTexture(0, existing_entry->texture.get()); - g_renderer->SetSamplerState(1, RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(reinterpreted_entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(reinterpreted_entry->texture->GetRect()); + g_gfx->SetPipeline(pipeline); + g_gfx->SetTexture(0, existing_entry->texture.get()); + g_gfx->SetSamplerState(1, RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); reinterpreted_entry->texture->FinishedRendering(); textures_by_address.emplace(reinterpreted_entry->addr, reinterpreted_entry); @@ -408,9 +409,8 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(RcTcacheEntry& entry, u32 new_wi } // No need to convert the coordinates here since they'll be the same. - g_renderer->ScaleTexture(new_texture->framebuffer.get(), - new_texture->texture->GetConfig().GetRect(), entry->texture.get(), - entry->texture->GetConfig().GetRect()); + g_gfx->ScaleTexture(new_texture->framebuffer.get(), new_texture->texture->GetConfig().GetRect(), + entry->texture.get(), entry->texture->GetConfig().GetRect()); entry->texture.swap(new_texture->texture); entry->framebuffer.swap(new_texture->framebuffer); @@ -432,8 +432,7 @@ bool TextureCacheBase::CheckReadbackTexture(u32 width, u32 height, AbstractTextu TextureConfig staging_config(std::max(width, 128u), std::max(height, 128u), 1, 1, 1, format, 0); m_readback_texture.reset(); - m_readback_texture = - g_renderer->CreateStagingTexture(StagingTextureType::Readback, staging_config); + m_readback_texture = g_gfx->CreateStagingTexture(StagingTextureType::Readback, staging_config); return m_readback_texture != nullptr; } @@ -1081,7 +1080,7 @@ static void SetSamplerState(u32 index, float custom_tex_scale, bool custom_tex, state.tm0.anisotropic_filtering = false; } - g_renderer->SetSamplerState(index, state); + g_gfx->SetSamplerState(index, state); auto& system = Core::System::GetInstance(); auto& pixel_shader_manager = system.GetPixelShaderManager(); pixel_shader_manager.SetSamplerState(index, state.tm0.hex, state.tm1.hex); @@ -1096,7 +1095,7 @@ void TextureCacheBase::BindTextures(BitSet32 used_textures) const RcTcacheEntry& tentry = bound_textures[i]; if (used_textures[i] && tentry) { - g_renderer->SetTexture(i, tentry->texture.get()); + g_gfx->SetTexture(i, tentry->texture.get()); pixel_shader_manager.SetTexDims(i, tentry->native_width, tentry->native_height); const float custom_tex_scale = tentry->GetWidth() / float(tentry->native_width); @@ -2013,8 +2012,8 @@ void TextureCacheBase::StitchXFBCopy(RcTcacheEntry& stitched_entry) // We may have to scale if one of the copies is not internal resolution. if (srcrect.GetWidth() != dstrect.GetWidth() || srcrect.GetHeight() != dstrect.GetHeight()) { - g_renderer->ScaleTexture(stitched_entry->framebuffer.get(), dstrect, entry->texture.get(), - srcrect); + g_gfx->ScaleTexture(stitched_entry->framebuffer.get(), dstrect, entry->texture.get(), + srcrect); } else { @@ -2521,7 +2520,7 @@ std::unique_ptr TextureCacheBase::GetEFBCopyStagingTextu return ptr; } - std::unique_ptr tex = g_renderer->CreateStagingTexture( + std::unique_ptr tex = g_gfx->CreateStagingTexture( StagingTextureType::Readback, m_efb_encoding_texture->GetConfig()); if (!tex) WARN_LOG_FMT(VIDEO, "Failed to create EFB copy staging texture"); @@ -2614,7 +2613,7 @@ TextureCacheBase::AllocateTexture(const TextureConfig& config) return std::move(entry); } - std::unique_ptr texture = g_renderer->CreateTexture(config); + std::unique_ptr texture = g_gfx->CreateTexture(config); if (!texture) { WARN_LOG_FMT(VIDEO, "Failed to allocate a {}x{}x{} texture", config.width, config.height, @@ -2625,7 +2624,7 @@ TextureCacheBase::AllocateTexture(const TextureConfig& config) std::unique_ptr framebuffer; if (config.IsRenderTarget()) { - framebuffer = g_renderer->CreateFramebuffer(texture.get(), nullptr); + framebuffer = g_gfx->CreateFramebuffer(texture.get(), nullptr); if (!framebuffer) { WARN_LOG_FMT(VIDEO, "Failed to allocate a {}x{}x{} framebuffer", config.width, config.height, @@ -2745,12 +2744,11 @@ bool TextureCacheBase::CreateUtilityTextures() { constexpr TextureConfig encoding_texture_config( EFB_WIDTH * 4, 1024, 1, 1, 1, AbstractTextureFormat::BGRA8, AbstractTextureFlag_RenderTarget); - m_efb_encoding_texture = - g_renderer->CreateTexture(encoding_texture_config, "EFB encoding texture"); + m_efb_encoding_texture = g_gfx->CreateTexture(encoding_texture_config, "EFB encoding texture"); if (!m_efb_encoding_texture) return false; - m_efb_encoding_framebuffer = g_renderer->CreateFramebuffer(m_efb_encoding_texture.get(), nullptr); + m_efb_encoding_framebuffer = g_gfx->CreateFramebuffer(m_efb_encoding_texture.get(), nullptr); if (!m_efb_encoding_framebuffer) return false; @@ -2759,7 +2757,7 @@ bool TextureCacheBase::CreateUtilityTextures() constexpr TextureConfig decoding_texture_config( 1024, 1024, 1, 1, 1, AbstractTextureFormat::RGBA8, AbstractTextureFlag_ComputeImage); m_decoding_texture = - g_renderer->CreateTexture(decoding_texture_config, "GPU texture decoding texture"); + g_gfx->CreateTexture(decoding_texture_config, "GPU texture decoding texture"); if (!m_decoding_texture) return false; } @@ -2788,14 +2786,14 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c } const auto scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); - const auto framebuffer_rect = g_renderer->ConvertFramebufferRectangle( + const auto framebuffer_rect = g_gfx->ConvertFramebufferRectangle( scaled_src_rect, g_framebuffer_manager->GetEFBFramebuffer()); AbstractTexture* src_texture = is_depth_copy ? g_framebuffer_manager->ResolveEFBDepthTexture(framebuffer_rect) : g_framebuffer_manager->ResolveEFBColorTexture(framebuffer_rect); src_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); // Fill uniform buffer. struct Uniforms @@ -2832,14 +2830,14 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); // Use the copy pipeline to render the VRAM copy. - g_renderer->SetAndDiscardFramebuffer(entry->framebuffer.get()); - g_renderer->SetViewportAndScissor(entry->framebuffer->GetRect()); - g_renderer->SetPipeline(copy_pipeline); - g_renderer->SetTexture(0, src_texture); - g_renderer->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : - RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); - g_renderer->EndUtilityDrawing(); + g_gfx->SetAndDiscardFramebuffer(entry->framebuffer.get()); + g_gfx->SetViewportAndScissor(entry->framebuffer->GetRect()); + g_gfx->SetPipeline(copy_pipeline); + g_gfx->SetTexture(0, src_texture); + g_gfx->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : + RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); + g_gfx->EndUtilityDrawing(); entry->texture->FinishedRendering(); } @@ -2862,14 +2860,14 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& } const auto scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); - const auto framebuffer_rect = g_renderer->ConvertFramebufferRectangle( + const auto framebuffer_rect = g_gfx->ConvertFramebufferRectangle( scaled_src_rect, g_framebuffer_manager->GetEFBFramebuffer()); AbstractTexture* src_texture = params.depth ? g_framebuffer_manager->ResolveEFBDepthTexture(framebuffer_rect) : g_framebuffer_manager->ResolveEFBColorTexture(framebuffer_rect); src_texture->FinishedRendering(); - g_renderer->BeginUtilityDrawing(); + g_gfx->BeginUtilityDrawing(); // Fill uniform buffer. struct Uniforms @@ -2909,15 +2907,15 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& const auto encode_rect = MathUtil::Rectangle(0, 0, render_width, render_height); // Render to GPU texture, and then copy to CPU-accessible texture. - g_renderer->SetAndDiscardFramebuffer(m_efb_encoding_framebuffer.get()); - g_renderer->SetViewportAndScissor(encode_rect); - g_renderer->SetPipeline(copy_pipeline); - g_renderer->SetTexture(0, src_texture); - g_renderer->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : - RenderState::GetPointSamplerState()); - g_renderer->Draw(0, 3); + g_gfx->SetAndDiscardFramebuffer(m_efb_encoding_framebuffer.get()); + g_gfx->SetViewportAndScissor(encode_rect); + g_gfx->SetPipeline(copy_pipeline); + g_gfx->SetTexture(0, src_texture); + g_gfx->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() : + RenderState::GetPointSamplerState()); + g_gfx->Draw(0, 3); dst->CopyFromTexture(m_efb_encoding_texture.get(), encode_rect, 0, 0, encode_rect); - g_renderer->EndUtilityDrawing(); + g_gfx->EndUtilityDrawing(); // Flush if there's sufficient draws between this copy and the last. g_vertex_manager->OnEFBCopyToRAM(); @@ -2970,12 +2968,12 @@ bool TextureCacheBase::DecodeTextureOnGPU(RcTcacheEntry& entry, u32 dst_level, c aligned_height, src_offset, row_stride / bytes_per_buffer_elem, palette_offset}; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); - g_renderer->SetComputeImageTexture(m_decoding_texture.get(), false, true); + g_gfx->SetComputeImageTexture(m_decoding_texture.get(), false, true); auto dispatch_groups = TextureConversionShaderTiled::GetDispatchCount(info, aligned_width, aligned_height); - g_renderer->DispatchComputeShader(shader, info->group_size_x, info->group_size_y, 1, - dispatch_groups.first, dispatch_groups.second, 1); + g_gfx->DispatchComputeShader(shader, info->group_size_x, info->group_size_y, 1, + dispatch_groups.first, dispatch_groups.second, 1); // Copy from decoding texture -> final texture // This is because we don't want to have to create compute view for every layer diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index 9bee673db4..f3d580b801 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -20,12 +20,12 @@ #include "Core/HW/Memmap.h" #include "Core/System.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/CPMemory.h" #include "VideoCommon/DataReader.h" #include "VideoCommon/IndexGenerator.h" #include "VideoCommon/NativeVertexFormat.h" -#include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexLoaderBase.h" #include "VideoCommon/VertexManagerBase.h" @@ -140,7 +140,7 @@ NativeVertexFormat* GetOrCreateMatchingFormat(const PortableVertexDeclaration& d auto iter = s_native_vertex_map.find(decl); if (iter == s_native_vertex_map.end()) { - std::unique_ptr fmt = g_renderer->CreateNativeVertexFormat(decl); + std::unique_ptr fmt = g_gfx->CreateNativeVertexFormat(decl); auto ipair = s_native_vertex_map.emplace(decl, std::move(fmt)); iter = ipair.first; } diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 1ccfebad0c..5f6b8a310e 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -17,6 +17,7 @@ #include "Core/DolphinAnalytics.h" #include "Core/System.h" +#include "VideoCommon/AbstractGfx.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/BoundingBox.h" #include "VideoCommon/DataReader.h" @@ -329,7 +330,7 @@ void VertexManagerBase::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 ba g_renderer->BBoxFlush(); } - g_renderer->DrawIndexed(base_index, num_indices, base_vertex); + g_gfx->DrawIndexed(base_index, num_indices, base_vertex); } void VertexManagerBase::UploadUniforms() @@ -599,7 +600,7 @@ void VertexManagerBase::Flush() UpdatePipelineObject(); if (m_current_pipeline_object) { - g_renderer->SetPipeline(m_current_pipeline_object); + g_gfx->SetPipeline(m_current_pipeline_object); if (PerfQueryBase::ShouldEmulate()) g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); @@ -877,7 +878,7 @@ void VertexManagerBase::OnDraw() u32 diff = m_draw_counter - m_last_efb_copy_draw_counter; if (m_unflushed_efb_copy && diff > MINIMUM_DRAW_CALLS_PER_COMMAND_BUFFER_FOR_READBACK) { - g_renderer->Flush(); + g_gfx->Flush(); m_unflushed_efb_copy = false; m_last_efb_copy_draw_counter = m_draw_counter; } @@ -892,7 +893,7 @@ void VertexManagerBase::OnDraw() m_scheduled_command_buffer_kicks.end(), m_draw_counter)) { // Kick a command buffer on the background thread. - g_renderer->Flush(); + g_gfx->Flush(); m_unflushed_efb_copy = false; m_last_efb_copy_draw_counter = m_draw_counter; } @@ -927,7 +928,7 @@ void VertexManagerBase::OnEFBCopyToRAM() } m_unflushed_efb_copy = false; - g_renderer->Flush(); + g_gfx->Flush(); } void VertexManagerBase::OnEndFrame() diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp index 167848b425..40fcd8b0f4 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.cpp +++ b/Source/Core/VideoCommon/VideoBackendBase.cpp @@ -324,7 +324,9 @@ void VideoBackendBase::InitializeShared() // do not initialize again for the config window m_initialized = true; + g_renderer = std::make_unique(); g_presenter = std::make_unique(); + g_frame_dumper = std::make_unique(); auto& system = Core::System::GetInstance(); auto& command_processor = system.GetCommandProcessor(); @@ -337,7 +339,13 @@ void VideoBackendBase::InitializeShared() system.GetGeometryShaderManager().Init(); system.GetPixelShaderManager().Init(); TMEM::Init(); - g_frame_dumper = std::make_unique(); + + if (!g_renderer->Initialize() || !g_presenter->Initialize()) + { + PanicAlertFmtT("Failed to initialize renderer classes"); + Shutdown(); + return; + } g_Config.VerifyValidity(); UpdateActiveConfig();