summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-08-28 20:23:44 -0400
committerGravatar bunnei2018-08-31 13:07:28 -0400
commit9bc71fcc5f8a71c8cc3a520babeb757711a6a309 (patch)
tree8a62a2a4ed6553bef1edc1cc0b15b6c6ad2eb744
parentgl_renderer: Cache textures, framebuffers, and shaders based on CPU address. (diff)
downloadyuzu-9bc71fcc5f8a71c8cc3a520babeb757711a6a309.tar.gz
yuzu-9bc71fcc5f8a71c8cc3a520babeb757711a6a309.tar.xz
yuzu-9bc71fcc5f8a71c8cc3a520babeb757711a6a309.zip
rasterizer_cache: Use boost::interval_map for a more accurate cache.
-rw-r--r--src/video_core/rasterizer_cache.h78
1 files changed, 45 insertions, 33 deletions
diff --git a/src/video_core/rasterizer_cache.h b/src/video_core/rasterizer_cache.h
index 599d39f62..de1eab86b 100644
--- a/src/video_core/rasterizer_cache.h
+++ b/src/video_core/rasterizer_cache.h
@@ -4,7 +4,9 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <unordered_map> 7#include <set>
8
9#include <boost/icl/interval_map.hpp>
8 10
9#include "common/common_types.h" 11#include "common/common_types.h"
10#include "core/core.h" 12#include "core/core.h"
@@ -17,62 +19,72 @@ template <class T>
17class RasterizerCache : NonCopyable { 19class RasterizerCache : NonCopyable {
18public: 20public:
19 /// Mark the specified region as being invalidated 21 /// Mark the specified region as being invalidated
20 void InvalidateRegion(VAddr region_addr, size_t region_size) { 22 void InvalidateRegion(VAddr addr, u64 size) {
21 for (auto iter = cached_objects.cbegin(); iter != cached_objects.cend();) { 23 if (size == 0)
22 const auto& object{iter->second}; 24 return;
23 25
24 ++iter; 26 const ObjectInterval interval{addr, addr + size};
27 for (auto& pair : boost::make_iterator_range(object_cache.equal_range(interval))) {
28 for (auto& cached_object : pair.second) {
29 if (!cached_object)
30 continue;
25 31
26 if (object->GetAddr() <= (region_addr + region_size) && 32 remove_objects.emplace(cached_object);
27 region_addr <= (object->GetAddr() + object->GetSizeInBytes())) {
28 // Regions overlap, so invalidate
29 Unregister(object);
30 } 33 }
31 } 34 }
35
36 for (auto& remove_object : remove_objects) {
37 Unregister(remove_object);
38 }
39
40 remove_objects.clear();
41 }
42
43 /// Invalidates everything in the cache
44 void InvalidateAll() {
45 while (object_cache.begin() != object_cache.end()) {
46 Unregister(*object_cache.begin()->second.begin());
47 }
32 } 48 }
33 49
34protected: 50protected:
35 /// Tries to get an object from the cache with the specified address 51 /// Tries to get an object from the cache with the specified address
36 T TryGet(VAddr addr) const { 52 T TryGet(VAddr addr) const {
37 const auto& search{cached_objects.find(addr)}; 53 const ObjectInterval interval{addr};
38 if (search != cached_objects.end()) { 54 for (auto& pair : boost::make_iterator_range(object_cache.equal_range(interval))) {
39 return search->second; 55 for (auto& cached_object : pair.second) {
56 if (cached_object->GetAddr() == addr) {
57 return cached_object;
58 }
59 }
40 } 60 }
41
42 return nullptr; 61 return nullptr;
43 } 62 }
44 63
45 /// Gets a reference to the cache
46 const std::unordered_map<VAddr, T>& GetCache() const {
47 return cached_objects;
48 }
49
50 /// Register an object into the cache 64 /// Register an object into the cache
51 void Register(const T& object) { 65 void Register(const T& object) {
52 const auto& search{cached_objects.find(object->GetAddr())}; 66 object_cache.add({GetInterval(object), ObjectSet{object}});
53 if (search != cached_objects.end()) {
54 // Registered already
55 return;
56 }
57
58 auto& rasterizer = Core::System::GetInstance().Renderer().Rasterizer(); 67 auto& rasterizer = Core::System::GetInstance().Renderer().Rasterizer();
59 rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), 1); 68 rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), 1);
60 cached_objects[object->GetAddr()] = std::move(object);
61 } 69 }
62 70
63 /// Unregisters an object from the cache 71 /// Unregisters an object from the cache
64 void Unregister(const T& object) { 72 void Unregister(const T& object) {
65 const auto& search{cached_objects.find(object->GetAddr())};
66 if (search == cached_objects.end()) {
67 // Unregistered already
68 return;
69 }
70
71 auto& rasterizer = Core::System::GetInstance().Renderer().Rasterizer(); 73 auto& rasterizer = Core::System::GetInstance().Renderer().Rasterizer();
72 rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), -1); 74 rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), -1);
73 cached_objects.erase(search); 75 object_cache.subtract({GetInterval(object), ObjectSet{object}});
74 } 76 }
75 77
76private: 78private:
77 std::unordered_map<VAddr, T> cached_objects; 79 using ObjectSet = std::set<T>;
80 using ObjectCache = boost::icl::interval_map<VAddr, ObjectSet>;
81 using ObjectInterval = typename ObjectCache::interval_type;
82
83 static auto GetInterval(const T& object) {
84 return ObjectInterval::right_open(object->GetAddr(),
85 object->GetAddr() + object->GetSizeInBytes());
86 }
87
88 ObjectCache object_cache;
89 ObjectSet remove_objects;
78}; 90};