Просмотр исходного кода

gl_rasterizer_cache: Reserve surfaces that have already been created for later use.

bunnei 8 лет назад
Родитель
Сommit
fee8bdd90c

+ 28 - 3
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<CachedSurface>(params);
-    RegisterSurface(surface);
-    LoadSurface(surface);
+    if (!surface) {
+        surface = std::make_shared<CachedSurface>(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 <typename Map, typename Interval>
 constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
     return boost::make_iterator_range(map.equal_range(interval));

+ 33 - 0
src/video_core/renderer_opengl/gl_rasterizer_cache.h

@@ -11,6 +11,7 @@
 #include <boost/icl/interval_map.hpp>
 
 #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<OpenGL::SurfaceParams> {
+    static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) {
+        SurfaceReserveKey res;
+        res.state = params;
+        return res;
+    }
+};
+namespace std {
+template <>
+struct hash<SurfaceReserveKey> {
+    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<Tegra::GPUVAddr, Surface> 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<SurfaceReserveKey, Surface> surface_reserve;
+
     OGLFramebuffer read_framebuffer;
     OGLFramebuffer draw_framebuffer;
 };