From dacf83ac0257727a48c971ca1cfcd220976c461f Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 28 Dec 2019 21:45:56 -0300 Subject: [PATCH] renderer_opengl: Reintroduce dirty flags for render targets --- .../renderer_opengl/gl_rasterizer.cpp | 20 +++-- .../renderer_opengl/gl_rasterizer.h | 6 +- .../renderer_opengl/gl_state_tracker.cpp | 85 +++++++++++++++++++ .../renderer_opengl/gl_state_tracker.h | 56 ++++++++++++ .../renderer_opengl/gl_texture_cache.cpp | 7 +- .../renderer_opengl/gl_texture_cache.h | 5 +- .../renderer_opengl/renderer_opengl.cpp | 6 +- .../renderer_opengl/renderer_opengl.h | 3 + src/video_core/texture_cache/texture_cache.h | 20 ++++- 9 files changed, 195 insertions(+), 13 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 2fb8ec33b2..a1675355e1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -99,11 +99,12 @@ void oglEnablei(GLenum cap, bool state, GLuint index) { } // Anonymous namespace RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, - ScreenInfo& info, GLShader::ProgramManager& program_manager) - : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device}, + ScreenInfo& info, GLShader::ProgramManager& program_manager, + StateTracker& state_tracker) + : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device, state_tracker}, shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, - screen_info{info}, program_manager{program_manager}, buffer_cache{*this, system, device, - STREAM_BUFFER_SIZE} { + screen_info{info}, program_manager{program_manager}, state_tracker{state_tracker}, + buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} { CheckExtensions(); } @@ -320,9 +321,17 @@ void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, shader_cache.LoadDiskCache(stop_loading, callback); } +void RasterizerOpenGL::SetupDirtyFlags() { + state_tracker.Initialize(); +} + void RasterizerOpenGL::ConfigureFramebuffers() { MICROPROFILE_SCOPE(OpenGL_Framebuffer); auto& gpu = system.GPU().Maxwell3D(); + if (!gpu.dirty.flags[VideoCommon::Dirty::RenderTargets]) { + return; + } + gpu.dirty.flags[VideoCommon::Dirty::RenderTargets] = false; texture_cache.GuardRenderTargets(true); @@ -361,8 +370,6 @@ void RasterizerOpenGL::ConfigureFramebuffers() { void RasterizerOpenGL::ConfigureClearFramebuffer(bool using_color_fb, bool using_depth_fb, bool using_stencil_fb) { - using VideoCore::Surface::SurfaceType; - auto& gpu = system.GPU().Maxwell3D(); const auto& regs = gpu.regs; @@ -381,6 +388,7 @@ void RasterizerOpenGL::ConfigureClearFramebuffer(bool using_color_fb, bool using key.colors[0] = color_surface; key.zeta = depth_surface; + state_tracker.NotifyFramebuffer(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_cache.GetFramebuffer(key)); } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 48443bdff6..22a3a33525 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -30,6 +30,7 @@ #include "video_core/renderer_opengl/gl_shader_cache.h" #include "video_core/renderer_opengl/gl_shader_decompiler.h" #include "video_core/renderer_opengl/gl_shader_manager.h" +#include "video_core/renderer_opengl/gl_state_tracker.h" #include "video_core/renderer_opengl/gl_texture_cache.h" #include "video_core/renderer_opengl/utils.h" #include "video_core/textures/texture.h" @@ -54,7 +55,8 @@ struct DrawParameters; class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { public: explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, - ScreenInfo& info, GLShader::ProgramManager& program_manager); + ScreenInfo& info, GLShader::ProgramManager& program_manager, + StateTracker& state_tracker); ~RasterizerOpenGL() override; void Draw(bool is_indexed, bool is_instanced) override; @@ -75,6 +77,7 @@ public: u32 pixel_stride) override; void LoadDiskResources(const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback) override; + void SetupDirtyFlags() override; /// Returns true when there are commands queued to the OpenGL server. bool AnyCommandQueued() const { @@ -216,6 +219,7 @@ private: Core::System& system; ScreenInfo& screen_info; GLShader::ProgramManager& program_manager; + StateTracker& state_tracker; static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; OGLBufferCache buffer_cache; diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp index e69de29bb2..268b9351e8 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.cpp +++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp @@ -0,0 +1,85 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include + +#include "common/common_types.h" +#include "core/core.h" +#include "video_core/engines/maxwell_3d.h" +#include "video_core/gpu.h" +#include "video_core/renderer_opengl/gl_state_tracker.h" + +#define OFF(field_name) MAXWELL3D_REG_INDEX(field_name) +#define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / sizeof(u32)) + +namespace OpenGL { + +namespace { + +using namespace Dirty; +using namespace VideoCommon::Dirty; +using Tegra::Engines::Maxwell3D; +using Regs = Maxwell3D::Regs; +using Dirty = std::remove_reference_t; +using Tables = std::remove_reference_t; +using Table = std::remove_reference_t; + +template +void FillBlock(Table& table, std::size_t begin, std::size_t num, Integer dirty_index) { + const auto it = std::begin(table) + begin; + std::fill(it, it + num, static_cast(dirty_index)); +} + +template +void FillBlock(Tables& tables, std::size_t begin, std::size_t num, Integer1 index_a, + Integer2 index_b) { + FillBlock(tables[0], begin, num, index_a); + FillBlock(tables[1], begin, num, index_b); +} + +void SetupDirtyRenderTargets(Tables& tables) { + static constexpr std::size_t num_per_rt = NUM(rt[0]); + static constexpr std::size_t begin = OFF(rt); + static constexpr std::size_t num = num_per_rt * Regs::NumRenderTargets; + for (std::size_t rt = 0; rt < Regs::NumRenderTargets; ++rt) { + FillBlock(tables[0], begin + rt * num_per_rt, num_per_rt, ColorBuffer0 + rt); + } + FillBlock(tables[1], begin, num, RenderTargets); + + static constexpr std::array zeta_flags{ZetaBuffer, RenderTargets}; + for (std::size_t i = 0; i < std::size(zeta_flags); ++i) { + const u8 flag = zeta_flags[i]; + auto& table = tables[i]; + table[OFF(zeta_enable)] = flag; + table[OFF(zeta_width)] = flag; + table[OFF(zeta_height)] = flag; + FillBlock(table, OFF(zeta), NUM(zeta), flag); + } +} + +} // Anonymous namespace + +StateTracker::StateTracker(Core::System& system) : system{system} {} + +void StateTracker::Initialize() { + auto& dirty = system.GPU().Maxwell3D().dirty; + std::size_t entry_index = 0; + const auto AddEntry = [&dirty, &entry_index](std::size_t dirty_register) { + dirty.on_write_stores[entry_index++] = static_cast(dirty_register); + }; + + AddEntry(RenderTargets); + for (std::size_t i = 0; i < Regs::NumRenderTargets; ++i) { + AddEntry(ColorBuffer0 + i); + } + AddEntry(ZetaBuffer); + + auto& tables = dirty.tables; + SetupDirtyRenderTargets(tables); +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_state_tracker.h b/src/video_core/renderer_opengl/gl_state_tracker.h index e69de29bb2..91d4bb8d3a 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.h +++ b/src/video_core/renderer_opengl/gl_state_tracker.h @@ -0,0 +1,56 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" +#include "video_core/dirty_flags.h" +#include "video_core/engines/maxwell_3d.h" + +namespace Core { +class System; +} + +namespace OpenGL { + +namespace Dirty { +enum : u8 { + First = VideoCommon::Dirty::LastCommonEntry, + + VertexFormats, + VertexBuffers, + VertexInstances, + Shaders, + Viewports, + CullTestEnable, + FrontFace, + CullFace, + PrimitiveRestart, + DepthTest, + StencilTest, + ColorMask, + BlendState, + PolygonOffset, + + VertexBuffer0 = PolygonOffset + 8, + VertexInstance0 = VertexBuffer0 + 32, +}; +} + +class StateTracker { +public: + explicit StateTracker(Core::System& system); + + void Initialize(); + + void NotifyFramebuffer() { + auto& flags = system.GPU().Maxwell3D().dirty.flags; + flags[VideoCommon::Dirty::RenderTargets] = true; + } + +private: + Core::System& system; +}; + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index e2a58f0adc..1cadcf2871 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -10,6 +10,7 @@ #include "core/core.h" #include "video_core/morton.h" #include "video_core/renderer_opengl/gl_resource_manager.h" +#include "video_core/renderer_opengl/gl_state_tracker.h" #include "video_core/renderer_opengl/gl_texture_cache.h" #include "video_core/renderer_opengl/utils.h" #include "video_core/texture_cache/surface_base.h" @@ -479,8 +480,8 @@ OGLTextureView CachedSurfaceView::CreateTextureView() const { TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, - const Device& device) - : TextureCacheBase{system, rasterizer} { + const Device& device, StateTracker& state_tracker) + : TextureCacheBase{system, rasterizer}, state_tracker{state_tracker} { src_framebuffer.Create(); dst_framebuffer.Create(); } @@ -518,6 +519,8 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view, UNIMPLEMENTED_IF(dst_params.target == SurfaceTarget::Texture3D); // TODO: Signal state tracker about these changes + state_tracker.NotifyFramebuffer(); + if (dst_params.srgb_conversion) { glEnable(GL_FRAMEBUFFER_SRGB); } else { diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 303534ca6d..6658c6ffd8 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -27,6 +27,7 @@ using VideoCommon::ViewParams; class CachedSurfaceView; class CachedSurface; class TextureCacheOpenGL; +class StateTracker; using Surface = std::shared_ptr; using View = std::shared_ptr; @@ -127,7 +128,7 @@ private: class TextureCacheOpenGL final : public TextureCacheBase { public: explicit TextureCacheOpenGL(Core::System& system, VideoCore::RasterizerInterface& rasterizer, - const Device& device); + const Device& device, StateTracker& state_tracker); ~TextureCacheOpenGL(); protected: @@ -144,6 +145,8 @@ protected: private: GLuint FetchPBO(std::size_t buffer_size); + StateTracker& state_tracker; + OGLFramebuffer src_framebuffer; OGLFramebuffer dst_framebuffer; std::unordered_map copy_pbo_cache; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 5e16bb99bd..36c634e0d3 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -482,8 +482,8 @@ void RendererOpenGL::CreateRasterizer() { if (rasterizer) { return; } - rasterizer = - std::make_unique(system, emu_window, screen_info, program_manager); + rasterizer = std::make_unique(system, emu_window, screen_info, + program_manager, state_tracker); } void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, @@ -576,6 +576,8 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); // TODO: Signal state tracker about these changes + state_tracker.NotifyFramebuffer(); + program_manager.UseVertexShader(vertex_program.handle); program_manager.UseGeometryShader(0); program_manager.UseFragmentShader(fragment_program.handle); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index ca670e7c81..33073ce5b0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -11,6 +11,7 @@ #include "video_core/renderer_base.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_shader_manager.h" +#include "video_core/renderer_opengl/gl_state_tracker.h" namespace Core { class System; @@ -91,6 +92,8 @@ private: Core::Frontend::EmuWindow& emu_window; Core::System& system; + StateTracker state_tracker{system}; + // OpenGL object IDs OGLBuffer vertex_buffer; OGLProgram vertex_program; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index ec6dfa49eb..51373b6871 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -22,6 +22,7 @@ #include "core/core.h" #include "core/memory.h" #include "core/settings.h" +#include "video_core/dirty_flags.h" #include "video_core/engines/fermi_2d.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/gpu.h" @@ -142,6 +143,10 @@ public: TView GetDepthBufferSurface(bool preserve_contents) { std::lock_guard lock{mutex}; auto& maxwell3d = system.GPU().Maxwell3D(); + if (!maxwell3d.dirty.flags[VideoCommon::Dirty::ZetaBuffer]) { + return depth_buffer.view; + } + maxwell3d.dirty.flags[VideoCommon::Dirty::ZetaBuffer] = false; const auto& regs{maxwell3d.regs}; const auto gpu_addr{regs.zeta.Address()}; @@ -170,6 +175,10 @@ public: std::lock_guard lock{mutex}; ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); auto& maxwell3d = system.GPU().Maxwell3D(); + if (!maxwell3d.dirty.flags[VideoCommon::Dirty::ColorBuffer0 + index]) { + return render_targets[index].view; + } + maxwell3d.dirty.flags[VideoCommon::Dirty::ColorBuffer0 + index] = false; const auto& regs{maxwell3d.regs}; if (index >= regs.rt_control.count || regs.rt[index].Address() == 0 || @@ -310,7 +319,16 @@ protected: // and reading it from a separate buffer. virtual void BufferCopy(TSurface& src_surface, TSurface& dst_surface) = 0; - void ManageRenderTargetUnregister([[maybe_unused]] TSurface& surface) {} + void ManageRenderTargetUnregister(TSurface& surface) { + auto& dirty = system.GPU().Maxwell3D().dirty; + const u32 index = surface->GetRenderTarget(); + if (index == DEPTH_RT) { + dirty.flags[VideoCommon::Dirty::ZetaBuffer] = true; + } else { + dirty.flags[VideoCommon::Dirty::ColorBuffer0 + index] = true; + } + dirty.flags[VideoCommon::Dirty::RenderTargets] = true; + } void Register(TSurface surface) { const GPUVAddr gpu_addr = surface->GetGpuAddr();