3
0
Fork 0
forked from suyu/suyu

Memory: Fix invalidation handling from the CPU/Services

This commit is contained in:
Fernando Sahmkow 2023-11-10 16:43:56 +01:00
parent 1d03a0fa75
commit f1806d237f
3 changed files with 22 additions and 7 deletions

View file

@ -1,8 +1,10 @@
// SPDX-FileCopyrightText: 2015 Citra Emulator Project // SPDX-FileCopyrightText: 2015 Citra Emulator Project
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <mutex>
#include <span> #include <span>
#include "common/assert.h" #include "common/assert.h"
@ -10,6 +12,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/page_table.h" #include "common/page_table.h"
#include "common/scope_exit.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/core.h" #include "core/core.h"
@ -318,7 +321,7 @@ struct Memory::Impl {
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) { u8* const host_ptr) {
if constexpr (!UNSAFE) { if constexpr (!UNSAFE) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount); HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
} }
std::memcpy(host_ptr, src_buffer, copy_amount); std::memcpy(host_ptr, src_buffer, copy_amount);
}, },
@ -351,7 +354,7 @@ struct Memory::Impl {
}, },
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) { u8* const host_ptr) {
system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount); HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount);
std::memset(host_ptr, 0, copy_amount); std::memset(host_ptr, 0, copy_amount);
}, },
[](const std::size_t copy_amount) {}); [](const std::size_t copy_amount) {});
@ -420,7 +423,7 @@ struct Memory::Impl {
const std::size_t block_size) { const std::size_t block_size) {
// dc cvac: Store to point of coherency // dc cvac: Store to point of coherency
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
@ -430,7 +433,7 @@ struct Memory::Impl {
const std::size_t block_size) { const std::size_t block_size) {
// dc civac: Store to point of coherency, and invalidate from cache // dc civac: Store to point of coherency, and invalidate from cache
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); HandleRasterizerWrite(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
@ -767,7 +770,18 @@ struct Memory::Impl {
} }
void HandleRasterizerWrite(VAddr address, size_t size) { void HandleRasterizerWrite(VAddr address, size_t size) {
const size_t core = system.GetCurrentHostThreadID(); constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
const size_t core = std::min(system.GetCurrentHostThreadID(),
sys_core); // any other calls threads go to syscore.
// Guard on sys_core;
if (core == sys_core) [[unlikely]] {
sys_core_guard.lock();
}
SCOPE_EXIT({
if (core == sys_core) [[unlikely]] {
sys_core_guard.unlock();
}
});
auto& current_area = rasterizer_write_areas[core]; auto& current_area = rasterizer_write_areas[core];
VAddr subaddress = address >> YUZU_PAGEBITS; VAddr subaddress = address >> YUZU_PAGEBITS;
bool do_collection = current_area.last_address == subaddress; bool do_collection = current_area.last_address == subaddress;
@ -799,6 +813,7 @@ struct Memory::Impl {
rasterizer_read_areas{}; rasterizer_read_areas{};
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
std::mutex sys_core_guard;
}; };
Memory::Memory(Core::System& system_) : system{system_} { Memory::Memory(Core::System& system_) : system{system_} {

View file

@ -555,7 +555,7 @@ void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) {
} }
{ {
std::scoped_lock lock{buffer_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex};
buffer_cache.CachedWriteMemory(addr, size); buffer_cache.WriteMemory(addr, size);
} }
shader_cache.InvalidateRegion(addr, size); shader_cache.InvalidateRegion(addr, size);
} }

View file

@ -621,7 +621,7 @@ void RasterizerVulkan::OnCacheInvalidation(VAddr addr, u64 size) {
} }
{ {
std::scoped_lock lock{buffer_cache.mutex}; std::scoped_lock lock{buffer_cache.mutex};
buffer_cache.CachedWriteMemory(addr, size); buffer_cache.WriteMemory(addr, size);
} }
pipeline_cache.InvalidateRegion(addr, size); pipeline_cache.InvalidateRegion(addr, size);
} }