6 changed files with 213 additions and 101 deletions
-
141src/common/lru_cache.h
-
13src/video_core/buffer_cache/buffer_base.h
-
61src/video_core/buffer_cache/buffer_cache.h
-
2src/video_core/texture_cache/image_base.h
-
89src/video_core/texture_cache/texture_cache.h
-
8src/video_core/texture_cache/texture_cache_base.h
@ -0,0 +1,141 @@ |
|||
// Copyright 2021 yuzu Emulator Project |
|||
// Licensed under GPLv2+ or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <deque> |
|||
#include <memory> |
|||
#include <type_traits> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
namespace Common { |
|||
|
|||
template <class Traits> |
|||
class LeastRecentlyUsedCache { |
|||
using ObjectType = typename Traits::ObjectType; |
|||
using TickType = typename Traits::TickType; |
|||
|
|||
struct Item { |
|||
ObjectType obj; |
|||
TickType tick; |
|||
Item* next{}; |
|||
Item* prev{}; |
|||
}; |
|||
|
|||
public: |
|||
LeastRecentlyUsedCache() : first_item{}, last_item{} {} |
|||
~LeastRecentlyUsedCache() = default; |
|||
|
|||
size_t Insert(ObjectType obj, TickType tick) { |
|||
const auto new_id = build(); |
|||
auto& item = item_pool[new_id]; |
|||
item.obj = obj; |
|||
item.tick = tick; |
|||
attach(item); |
|||
return new_id; |
|||
} |
|||
|
|||
void Touch(size_t id, TickType tick) { |
|||
auto& item = item_pool[id]; |
|||
if (item.tick >= tick) { |
|||
return; |
|||
} |
|||
item.tick = tick; |
|||
if (&item == last_item) { |
|||
return; |
|||
} |
|||
detach(item); |
|||
attach(item); |
|||
} |
|||
|
|||
void Free(size_t id) { |
|||
auto& item = item_pool[id]; |
|||
detach(item); |
|||
item.prev = nullptr; |
|||
item.next = nullptr; |
|||
free_items.push_back(id); |
|||
} |
|||
|
|||
template <typename Func> |
|||
void ForEachItemBelow(TickType tick, Func&& func) { |
|||
static constexpr bool RETURNS_BOOL = |
|||
std::is_same_v<std::invoke_result<Func, ObjectType>, bool>; |
|||
Item* iterator = first_item; |
|||
while (iterator) { |
|||
if (static_cast<s64>(tick) - static_cast<s64>(iterator->tick) < 0) { |
|||
return; |
|||
} |
|||
Item* next = iterator->next; |
|||
if constexpr (RETURNS_BOOL) { |
|||
if (func(iterator->obj)) { |
|||
return; |
|||
} |
|||
} else { |
|||
func(iterator->obj); |
|||
} |
|||
iterator = next; |
|||
} |
|||
} |
|||
|
|||
private: |
|||
size_t build() { |
|||
if (free_items.empty()) { |
|||
const size_t item_id = item_pool.size(); |
|||
item_pool.emplace_back(); |
|||
auto& item = item_pool[item_id]; |
|||
item.next = nullptr; |
|||
item.prev = nullptr; |
|||
return item_id; |
|||
} |
|||
const size_t item_id = free_items.front(); |
|||
free_items.pop_front(); |
|||
auto& item = item_pool[item_id]; |
|||
item.next = nullptr; |
|||
item.prev = nullptr; |
|||
return item_id; |
|||
} |
|||
|
|||
void attach(Item& item) { |
|||
if (!first_item) { |
|||
first_item = &item; |
|||
} |
|||
if (!last_item) { |
|||
last_item = &item; |
|||
} else { |
|||
item.prev = last_item; |
|||
last_item->next = &item; |
|||
item.next = nullptr; |
|||
last_item = &item; |
|||
} |
|||
} |
|||
|
|||
void detach(Item& item) { |
|||
if (item.prev) { |
|||
item.prev->next = item.next; |
|||
} |
|||
if (item.next) { |
|||
item.next->prev = item.prev; |
|||
} |
|||
if (&item == first_item) { |
|||
first_item = item.next; |
|||
if (first_item) { |
|||
first_item->prev = nullptr; |
|||
} |
|||
} |
|||
if (&item == last_item) { |
|||
last_item = item.prev; |
|||
if (last_item) { |
|||
last_item->next = nullptr; |
|||
} |
|||
} |
|||
} |
|||
|
|||
std::deque<Item> item_pool; |
|||
std::deque<size_t> free_items; |
|||
Item* first_item; |
|||
Item* last_item; |
|||
}; |
|||
|
|||
} // namespace Common |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue