Merge pull request #1637 from FernandoS27/cache

Improved GPU Caches lookup Speed
This commit is contained in:
bunnei 2018-11-14 19:07:52 -08:00 committed by GitHub
commit 8a537a2021
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 17 additions and 18 deletions

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <set> #include <set>
#include <unordered_map>
#include <boost/icl/interval_map.hpp> #include <boost/icl/interval_map.hpp>
#include <boost/range/iterator_range_core.hpp> #include <boost/range/iterator_range_core.hpp>
@ -88,29 +89,25 @@ public:
/// Invalidates everything in the cache /// Invalidates everything in the cache
void InvalidateAll() { void InvalidateAll() {
while (object_cache.begin() != object_cache.end()) { while (interval_cache.begin() != interval_cache.end()) {
Unregister(*object_cache.begin()->second.begin()); Unregister(*interval_cache.begin()->second.begin());
} }
} }
protected: protected:
/// Tries to get an object from the cache with the specified address /// Tries to get an object from the cache with the specified address
T TryGet(VAddr addr) const { T TryGet(VAddr addr) const {
const ObjectInterval interval{addr}; const auto iter = map_cache.find(addr);
for (auto& pair : boost::make_iterator_range(object_cache.equal_range(interval))) { if (iter != map_cache.end())
for (auto& cached_object : pair.second) { return iter->second;
if (cached_object->GetAddr() == addr) {
return cached_object;
}
}
}
return nullptr; return nullptr;
} }
/// Register an object into the cache /// Register an object into the cache
void Register(const T& object) { void Register(const T& object) {
object->SetIsRegistered(true); object->SetIsRegistered(true);
object_cache.add({GetInterval(object), ObjectSet{object}}); interval_cache.add({GetInterval(object), ObjectSet{object}});
map_cache.insert({object->GetAddr(), object});
rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), 1); rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), 1);
} }
@ -118,13 +115,13 @@ protected:
void Unregister(const T& object) { void Unregister(const T& object) {
object->SetIsRegistered(false); object->SetIsRegistered(false);
rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), -1); rasterizer.UpdatePagesCachedCount(object->GetAddr(), object->GetSizeInBytes(), -1);
// Only flush if use_accurate_gpu_emulation is enabled, as it incurs a performance hit // Only flush if use_accurate_gpu_emulation is enabled, as it incurs a performance hit
if (Settings::values.use_accurate_gpu_emulation) { if (Settings::values.use_accurate_gpu_emulation) {
FlushObject(object); FlushObject(object);
} }
object_cache.subtract({GetInterval(object), ObjectSet{object}}); interval_cache.subtract({GetInterval(object), ObjectSet{object}});
map_cache.erase(object->GetAddr());
} }
/// Returns a ticks counter used for tracking when cached objects were last modified /// Returns a ticks counter used for tracking when cached objects were last modified
@ -141,7 +138,7 @@ private:
std::vector<T> objects; std::vector<T> objects;
const ObjectInterval interval{addr, addr + size}; const ObjectInterval interval{addr, addr + size};
for (auto& pair : boost::make_iterator_range(object_cache.equal_range(interval))) { for (auto& pair : boost::make_iterator_range(interval_cache.equal_range(interval))) {
for (auto& cached_object : pair.second) { for (auto& cached_object : pair.second) {
if (!cached_object) { if (!cached_object) {
continue; continue;
@ -167,15 +164,17 @@ private:
} }
using ObjectSet = std::set<T>; using ObjectSet = std::set<T>;
using ObjectCache = boost::icl::interval_map<VAddr, ObjectSet>; using ObjectCache = std::unordered_map<VAddr, T>;
using ObjectInterval = typename ObjectCache::interval_type; using IntervalCache = boost::icl::interval_map<VAddr, ObjectSet>;
using ObjectInterval = typename IntervalCache::interval_type;
static auto GetInterval(const T& object) { static auto GetInterval(const T& object) {
return ObjectInterval::right_open(object->GetAddr(), return ObjectInterval::right_open(object->GetAddr(),
object->GetAddr() + object->GetSizeInBytes()); object->GetAddr() + object->GetSizeInBytes());
} }
ObjectCache object_cache; ///< Cache of objects ObjectCache map_cache;
IntervalCache interval_cache; ///< Cache of objects
u64 modified_ticks{}; ///< Counter of cache state ticks, used for in-order flushing u64 modified_ticks{}; ///< Counter of cache state ticks, used for in-order flushing
VideoCore::RasterizerInterface& rasterizer; VideoCore::RasterizerInterface& rasterizer;
}; };