From fee8bdd90c3c8fd61385a84152cf22c107013747 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 21 Aug 2018 22:04:54 -0400 Subject: [PATCH] gl_rasterizer_cache: Reserve surfaces that have already been created for later use. --- .../renderer_opengl/gl_rasterizer_cache.cpp | 31 +++++++++++++++-- .../renderer_opengl/gl_rasterizer_cache.h | 33 +++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index a13c1d97d7..10b2d8f3c4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -787,10 +787,20 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres } } + // Try to get a previously reserved surface + surface = TryGetReservedSurface(params); + // No surface found - create a new one - surface = std::make_shared(params); - RegisterSurface(surface); - LoadSurface(surface); + if (!surface) { + surface = std::make_shared(params); + ReserveSurface(surface); + RegisterSurface(surface); + } + + // Only load surface from memory if we care about the contents + if (preserve_contents) { + LoadSurface(surface); + } return surface; } @@ -940,6 +950,21 @@ void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { surface_cache.erase(search); } +void RasterizerCacheOpenGL::ReserveSurface(const Surface& surface) { + const auto& surface_reserve_key{SurfaceReserveKey::Create(surface->GetSurfaceParams())}; + surface_reserve[surface_reserve_key] = surface; +} + +Surface RasterizerCacheOpenGL::TryGetReservedSurface(const SurfaceParams& params) { + const auto& surface_reserve_key{SurfaceReserveKey::Create(params)}; + auto search{surface_reserve.find(surface_reserve_key)}; + if (search != surface_reserve.end()) { + RegisterSurface(search->second); + return search->second; + } + return {}; +} + template constexpr auto RangeFromInterval(Map& map, const Interval& interval) { return boost::make_iterator_range(map.equal_range(interval)); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index f273152a20..c8c615df22 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -11,6 +11,7 @@ #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" @@ -682,6 +683,27 @@ struct SurfaceParams { u32 cache_height; }; +}; // namespace OpenGL + +/// Hashable variation of SurfaceParams, used for a key in the surface cache +struct SurfaceReserveKey : Common::HashableStruct { + static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) { + SurfaceReserveKey res; + res.state = params; + return res; + } +}; +namespace std { +template <> +struct hash { + size_t operator()(const SurfaceReserveKey& k) const { + return k.Hash(); + } +}; +} // namespace std + +namespace OpenGL { + class CachedSurface final { public: CachedSurface(const SurfaceParams& params); @@ -752,12 +774,23 @@ private: /// Remove surface from the cache void UnregisterSurface(const Surface& surface); + /// Reserves a unique surface that can be reused later + void ReserveSurface(const Surface& surface); + + /// Tries to get a reserved surface for the specified parameters + Surface TryGetReservedSurface(const SurfaceParams& params); + /// 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; PageMap cached_pages; + /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have + /// previously been used. This is to prevent surfaces from being constantly created and + /// destroyed when used with different surface parameters. + std::unordered_map surface_reserve; + OGLFramebuffer read_framebuffer; OGLFramebuffer draw_framebuffer; };