mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-11 15:07:40 +00:00
[TEST] Hunting down recursive mutex 8
This commit is contained in:
@@ -121,6 +121,15 @@ void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
|
|||||||
memory_tracker.MarkRegionAsCpuModified(device_addr, size);
|
memory_tracker.MarkRegionAsCpuModified(device_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class P>
|
||||||
|
void BufferCache<P>::CpuWriteInvalidate(DAddr device_addr, u64 size) {
|
||||||
|
if (!memory_tracker.CpuMarkIfNotGpuModified(device_addr, size)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
WriteMemory(device_addr, size);
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::CachedWriteMemory(DAddr device_addr, u64 size) {
|
void BufferCache<P>::CachedWriteMemory(DAddr device_addr, u64 size) {
|
||||||
const bool is_dirty = IsRegionRegistered(device_addr, size);
|
const bool is_dirty = IsRegionRegistered(device_addr, size);
|
||||||
|
|||||||
@@ -217,6 +217,8 @@ public:
|
|||||||
|
|
||||||
void WriteMemory(DAddr device_addr, u64 size);
|
void WriteMemory(DAddr device_addr, u64 size);
|
||||||
|
|
||||||
|
void CpuWriteInvalidate(DAddr device_addr, u64 size);
|
||||||
|
|
||||||
void CachedWriteMemory(DAddr device_addr, u64 size);
|
void CachedWriteMemory(DAddr device_addr, u64 size);
|
||||||
|
|
||||||
bool OnCPUWrite(DAddr device_addr, u64 size);
|
bool OnCPUWrite(DAddr device_addr, u64 size);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <bit>
|
#include <bit>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <mutex>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <ankerl/unordered_dense.h>
|
#include <ankerl/unordered_dense.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -130,12 +131,28 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlushCachedWrites() noexcept {
|
void FlushCachedWrites() noexcept {
|
||||||
|
std::scoped_lock lk{tracker_mutex};
|
||||||
for (auto id : cached_pages) {
|
for (auto id : cached_pages) {
|
||||||
top_tier[id]->FlushCachedWrites();
|
top_tier[id]->FlushCachedWrites();
|
||||||
}
|
}
|
||||||
cached_pages.clear();
|
cached_pages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool CpuMarkIfNotGpuModified(VAddr addr, u64 size) {
|
||||||
|
std::scoped_lock lk{tracker_mutex};
|
||||||
|
const bool gpu = IteratePagesNoLock<false>(
|
||||||
|
addr, size, [](Manager* manager, u64 offset, size_t sz) {
|
||||||
|
return manager->IsRegionModified(Type::GPU, offset, sz);
|
||||||
|
});
|
||||||
|
if (gpu) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IteratePagesNoLock<true>(addr, size, [](Manager* manager, u64 offset, size_t sz) {
|
||||||
|
manager->ChangeRegionState(Type::CPU, true, manager->cpu_addr + offset, sz);
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Call 'func' for each CPU modified range and unmark those pages as CPU modified
|
/// Call 'func' for each CPU modified range and unmark those pages as CPU modified
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
|
void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
|
||||||
@@ -162,6 +179,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
template <bool create_region_on_fail, typename Func>
|
template <bool create_region_on_fail, typename Func>
|
||||||
bool IteratePages(VAddr cpu_address, size_t size, Func&& func) {
|
bool IteratePages(VAddr cpu_address, size_t size, Func&& func) {
|
||||||
|
std::scoped_lock lk{tracker_mutex};
|
||||||
|
return IteratePagesNoLock<create_region_on_fail>(cpu_address, size, std::forward<Func>(func));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool create_region_on_fail, typename Func>
|
||||||
|
bool IteratePagesNoLock(VAddr cpu_address, size_t size, Func&& func) {
|
||||||
using FuncReturn = typename std::invoke_result<Func, Manager*, u64, size_t>::type;
|
using FuncReturn = typename std::invoke_result<Func, Manager*, u64, size_t>::type;
|
||||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||||
std::size_t remaining_size{size};
|
std::size_t remaining_size{size};
|
||||||
@@ -199,6 +222,7 @@ private:
|
|||||||
|
|
||||||
template <bool create_region_on_fail, typename Func>
|
template <bool create_region_on_fail, typename Func>
|
||||||
std::pair<u64, u64> IteratePairs(VAddr cpu_address, size_t size, Func&& func) {
|
std::pair<u64, u64> IteratePairs(VAddr cpu_address, size_t size, Func&& func) {
|
||||||
|
std::scoped_lock lk{tracker_mutex};
|
||||||
std::size_t remaining_size{size};
|
std::size_t remaining_size{size};
|
||||||
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
|
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
|
||||||
u64 page_offset{cpu_address & HIGHER_PAGE_MASK};
|
u64 page_offset{cpu_address & HIGHER_PAGE_MASK};
|
||||||
@@ -259,6 +283,7 @@ private:
|
|||||||
std::deque<Manager*> free_managers;
|
std::deque<Manager*> free_managers;
|
||||||
ankerl::unordered_dense::set<u32> cached_pages;
|
ankerl::unordered_dense::set<u32> cached_pages;
|
||||||
DeviceTracker* device_tracker = nullptr;
|
DeviceTracker* device_tracker = nullptr;
|
||||||
|
std::mutex tracker_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
|||||||
@@ -773,6 +773,7 @@ bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool ENABLE_TEXTURE_CACHE_INVALIDATION_SKIP = true;
|
static constexpr bool ENABLE_TEXTURE_CACHE_INVALIDATION_SKIP = true;
|
||||||
|
static constexpr bool ENABLE_FINE_GRAINED_TRACKER_LOCK = true;
|
||||||
|
|
||||||
void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) {
|
void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) {
|
||||||
if (addr == 0 || size == 0) {
|
if (addr == 0 || size == 0) {
|
||||||
@@ -784,7 +785,9 @@ void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) {
|
|||||||
std::scoped_lock lock{texture_cache.mutex};
|
std::scoped_lock lock{texture_cache.mutex};
|
||||||
texture_cache.WriteMemory(addr, size);
|
texture_cache.WriteMemory(addr, size);
|
||||||
}
|
}
|
||||||
{
|
if (ENABLE_FINE_GRAINED_TRACKER_LOCK) {
|
||||||
|
buffer_cache.CpuWriteInvalidate(addr, size);
|
||||||
|
} else {
|
||||||
std::scoped_lock lock{buffer_cache.mutex};
|
std::scoped_lock lock{buffer_cache.mutex};
|
||||||
buffer_cache.WriteMemory(addr, size);
|
buffer_cache.WriteMemory(addr, size);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user