summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp31
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h33
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 a13c1d97d..10b2d8f3c 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<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));
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index f273152a2..c8c615df2 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 <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;
};