forked from suyu/suyu
Merge pull request #1637 from FernandoS27/cache
Improved GPU Caches lookup Speed
This commit is contained in:
commit
8a537a2021
1 changed files with 17 additions and 18 deletions
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue