diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c4ce57f1c..56d9c575b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -413,11 +413,13 @@ void RasterizerOpenGL::Clear() { glClear(clear_mask); // Mark framebuffer surfaces as dirty - if (dirty_color_surface != nullptr) { - res_cache.MarkSurfaceAsDirty(dirty_color_surface); - } - if (dirty_depth_surface != nullptr) { - res_cache.MarkSurfaceAsDirty(dirty_depth_surface); + if (Settings::values.use_accurate_framebuffers) { + if (dirty_color_surface != nullptr) { + res_cache.FlushSurface(dirty_color_surface); + } + if (dirty_depth_surface != nullptr) { + res_cache.FlushSurface(dirty_depth_surface); + } } } @@ -520,11 +522,13 @@ void RasterizerOpenGL::DrawArrays() { state.Apply(); // Mark framebuffer surfaces as dirty - if (dirty_color_surface != nullptr) { - res_cache.MarkSurfaceAsDirty(dirty_color_surface); - } - if (dirty_depth_surface != nullptr) { - res_cache.MarkSurfaceAsDirty(dirty_depth_surface); + if (Settings::values.use_accurate_framebuffers) { + if (dirty_color_surface != nullptr) { + res_cache.FlushSurface(dirty_color_surface); + } + if (dirty_depth_surface != nullptr) { + res_cache.FlushSurface(dirty_depth_surface); + } } } diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 672eb2990..bb53a2821 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -565,17 +565,9 @@ void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); } -void RasterizerCacheOpenGL::MarkSurfaceAsDirty(const Surface& surface) { - if (Settings::values.use_accurate_framebuffers) { - // If enabled, always flush dirty surfaces - surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); - surface->FlushGLBuffer(); - } else { - // Otherwise, don't mark surfaces that we write to as cached, because the resulting loads - // and flushes are very slow and do not seem to improve accuracy - const auto& params{surface->GetSurfaceParams()}; - Memory::RasterizerMarkRegionCached(params.addr, params.size_in_bytes, false); - } +void RasterizerCacheOpenGL::FlushSurface(const Surface& surface) { + surface->DownloadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); + surface->FlushGLBuffer(); } Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { @@ -589,21 +581,22 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { return {}; // Check for an exact match in existing surfaces - const auto& surface_key{SurfaceKey::Create(params)}; - const auto& search{surface_cache.find(surface_key)}; + const auto& search{surface_cache.find(params.addr)}; Surface surface; if (search != surface_cache.end()) { surface = search->second; - if (Settings::values.use_accurate_framebuffers) { - // Reload the surface from Switch memory - LoadSurface(surface); + if (surface->GetSurfaceParams() != params || Settings::values.use_accurate_framebuffers) { + FlushSurface(surface); + UnregisterSurface(surface); + } else { + return surface; } - } else { - surface = std::make_shared(params); - RegisterSurface(surface); - LoadSurface(surface); } + surface = std::make_shared(params); + RegisterSurface(surface); + LoadSurface(surface); + return surface; } @@ -652,22 +645,20 @@ void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, size_t size) void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { const auto& params{surface->GetSurfaceParams()}; - const auto& surface_key{SurfaceKey::Create(params)}; - const auto& search{surface_cache.find(surface_key)}; + const auto& search{surface_cache.find(params.addr)}; if (search != surface_cache.end()) { // Registered already return; } - surface_cache[surface_key] = surface; + surface_cache[params.addr] = surface; UpdatePagesCachedCount(params.addr, params.size_in_bytes, 1); } void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { const auto& params{surface->GetSurfaceParams()}; - const auto& surface_key{SurfaceKey::Create(params)}; - const auto& search{surface_cache.find(surface_key)}; + const auto& search{surface_cache.find(params.addr)}; if (search == surface_cache.end()) { // Unregistered already diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index d00746e8c..5124199b2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -10,7 +10,6 @@ #include #include #include "common/common_types.h" -#include "common/hash.h" #include "common/math_util.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_opengl/gl_resource_manager.h" @@ -137,6 +136,7 @@ struct SurfaceParams { ASSERT(static_cast(format) < bpp_table.size()); return bpp_table[static_cast(format)]; } + u32 GetFormatBpp() const { return GetFormatBpp(pixel_format); } @@ -369,6 +369,18 @@ struct SurfaceParams { Tegra::GPUVAddr zeta_address, Tegra::DepthFormat format); + bool operator==(const SurfaceParams& other) const { + return std::tie(addr, is_tiled, block_height, pixel_format, component_type, type, width, + height, unaligned_height, size_in_bytes) == + std::tie(other.addr, other.is_tiled, other.block_height, other.pixel_format, + other.component_type, other.type, other.width, other.height, + other.unaligned_height, other.size_in_bytes); + } + + bool operator!=(const SurfaceParams& other) const { + return !operator==(other); + } + Tegra::GPUVAddr addr; bool is_tiled; u32 block_height; @@ -381,24 +393,6 @@ struct SurfaceParams { size_t size_in_bytes; }; -/// Hashable variation of SurfaceParams, used for a key in the surface cache -struct SurfaceKey : Common::HashableStruct { - static SurfaceKey Create(const SurfaceParams& params) { - SurfaceKey res; - res.state = params; - return res; - } -}; - -namespace std { -template <> -struct hash { - size_t operator()(const SurfaceKey& k) const { - return k.Hash(); - } -}; -} // namespace std - class CachedSurface final { public: CachedSurface(const SurfaceParams& params); @@ -444,8 +438,8 @@ public: SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle& viewport); - /// Marks the specified surface as "dirty", in that it is out of sync with Switch memory - void MarkSurfaceAsDirty(const Surface& surface); + /// Flushes the surface to Switch memory + void FlushSurface(const Surface& surface); /// Tries to find a framebuffer GPU address based on the provided CPU address Surface TryFindFramebufferSurface(VAddr cpu_addr) const; @@ -469,7 +463,7 @@ private: /// Increase/decrease the number of surface in pages touching the specified region void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta); - std::unordered_map surface_cache; + std::unordered_map surface_cache; PageMap cached_pages; OGLFramebuffer read_framebuffer;