mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-26 00:56:45 +00:00
[buffer_cache, memory, pipeline] Added translation entry structure and update buffer cache handling
This commit is contained in:
@@ -127,6 +127,11 @@ public:
|
||||
void UpdatePagesCachedBatch(std::span<const std::pair<DAddr, size_t>> ranges, s32 delta);
|
||||
|
||||
private:
|
||||
struct TranslationEntry {
|
||||
DAddr guest_page{};
|
||||
u8* host_ptr{};
|
||||
};
|
||||
|
||||
// Internal helper that performs the update assuming the caller already holds the necessary lock.
|
||||
void UpdatePagesCachedCountNoLock(DAddr addr, size_t size, s32 delta);
|
||||
|
||||
@@ -195,6 +200,11 @@ private:
|
||||
}
|
||||
|
||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||
inline static thread_local TranslationEntry t_slot0{};
|
||||
inline static thread_local TranslationEntry t_slot1{};
|
||||
inline static thread_local TranslationEntry t_slot2{};
|
||||
inline static thread_local TranslationEntry t_slot3{};
|
||||
inline static thread_local u32 cache_cursor = 0;
|
||||
using CounterType = u8;
|
||||
using CounterAtomicType = std::atomic_uint8_t;
|
||||
static constexpr size_t subentries = 8 / sizeof(CounterType);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
@@ -247,6 +247,10 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
|
||||
}
|
||||
impl->multi_dev_address.Register(new_dev, start_id);
|
||||
}
|
||||
t_slot0 = {};
|
||||
t_slot1 = {};
|
||||
t_slot2 = {};
|
||||
t_slot3 = {};
|
||||
if (track) {
|
||||
TrackContinuityImpl(address, virtual_address, size, asid);
|
||||
}
|
||||
@@ -278,6 +282,10 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
|
||||
compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG;
|
||||
}
|
||||
}
|
||||
t_slot0 = {};
|
||||
t_slot1 = {};
|
||||
t_slot2 = {};
|
||||
t_slot3 = {};
|
||||
}
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
|
||||
@@ -417,6 +425,50 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) {
|
||||
device_inter->FlushRegion(address, size);
|
||||
const std::size_t page_offset = address & Memory::YUZU_PAGEMASK;
|
||||
if (size <= Memory::YUZU_PAGESIZE - page_offset) {
|
||||
const DAddr guest_page = address & ~static_cast<DAddr>(Memory::YUZU_PAGEMASK);
|
||||
if (t_slot0.guest_page == guest_page && t_slot0.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot0.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
if (t_slot1.guest_page == guest_page && t_slot1.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot1.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
if (t_slot2.guest_page == guest_page && t_slot2.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot2.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
if (t_slot3.guest_page == guest_page && t_slot3.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot3.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
|
||||
const auto phys_addr = compressed_physical_ptr[page_index];
|
||||
if (phys_addr != 0) {
|
||||
auto* const mem_ptr = GetPointerFromRaw<u8>(
|
||||
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS));
|
||||
switch (cache_cursor & 3U) {
|
||||
case 0:
|
||||
t_slot0 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
case 1:
|
||||
t_slot1 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
case 2:
|
||||
t_slot2 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
default:
|
||||
t_slot3 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
}
|
||||
cache_cursor = (cache_cursor + 1) & 3U;
|
||||
std::memcpy(dest_pointer, mem_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
WalkBlock(
|
||||
address, size,
|
||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||
@@ -455,6 +507,50 @@ void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_poin
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) {
|
||||
const std::size_t page_offset = address & Memory::YUZU_PAGEMASK;
|
||||
if (size <= Memory::YUZU_PAGESIZE - page_offset) {
|
||||
const DAddr guest_page = address & ~static_cast<DAddr>(Memory::YUZU_PAGEMASK);
|
||||
if (t_slot0.guest_page == guest_page && t_slot0.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot0.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
if (t_slot1.guest_page == guest_page && t_slot1.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot1.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
if (t_slot2.guest_page == guest_page && t_slot2.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot2.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
if (t_slot3.guest_page == guest_page && t_slot3.host_ptr != nullptr) {
|
||||
std::memcpy(dest_pointer, t_slot3.host_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::size_t page_index = address >> Memory::YUZU_PAGEBITS;
|
||||
const auto phys_addr = compressed_physical_ptr[page_index];
|
||||
if (phys_addr != 0) {
|
||||
auto* const mem_ptr = GetPointerFromRaw<u8>(
|
||||
(static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS));
|
||||
switch (cache_cursor & 3U) {
|
||||
case 0:
|
||||
t_slot0 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
case 1:
|
||||
t_slot1 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
case 2:
|
||||
t_slot2 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
default:
|
||||
t_slot3 = TranslationEntry{.guest_page = guest_page, .host_ptr = mem_ptr};
|
||||
break;
|
||||
}
|
||||
cache_cursor = (cache_cursor + 1) & 3U;
|
||||
std::memcpy(dest_pointer, mem_ptr + page_offset, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
WalkBlock(
|
||||
address, size,
|
||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||
|
||||
Reference in New Issue
Block a user