core: Improve MemorySystem::GetPhysicalPointer (#1587)

This commit is contained in:
PabloMK7 2026-01-09 10:23:44 +01:00 committed by GitHub
parent 19641fc29c
commit 47cd41cc58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 27 deletions

View File

@ -638,13 +638,10 @@ std::string MemorySystem::ReadCString(VAddr vaddr, std::size_t max_length) {
return string;
}
u8* MemorySystem::GetPhysicalPointer(PAddr address) {
return GetPhysicalRef(address);
}
MemoryRef MemorySystem::GetPhysicalRef(PAddr address) {
if (address == physical_ptr_cache.first) {
return physical_ptr_cache.second;
MemorySystem::PhysMemRegionInfo MemorySystem::GetPhysMemRegionInfo(PAddr address) {
if (address >= phys_mem_region_info_cache.region_start &&
address < phys_mem_region_info_cache.region_end) {
return phys_mem_region_info_cache;
}
constexpr std::array memory_areas = {
@ -661,38 +658,52 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) {
});
if (area == memory_areas.end()) [[unlikely]] {
LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address,
LOG_ERROR(HW_Memory, "Unknown GetPhysMemRegionInfo @ {:#08X} at PC {:#08X}", address,
impl->GetPC());
physical_ptr_cache = {address, {nullptr}};
return physical_ptr_cache.second;
phys_mem_region_info_cache = PhysMemRegionInfo();
return phys_mem_region_info_cache;
}
u32 offset_into_region = address - area->first;
std::shared_ptr<BackingMem> target_mem = nullptr;
switch (area->first) {
case VRAM_PADDR:
target_mem = impl->vram_mem;
phys_mem_region_info_cache = {&impl->vram_mem, area->first, area->second};
break;
case DSP_RAM_PADDR:
target_mem = impl->dsp_mem;
phys_mem_region_info_cache = {&impl->dsp_mem, area->first, area->second};
break;
case FCRAM_PADDR:
target_mem = impl->fcram_mem;
phys_mem_region_info_cache = {&impl->fcram_mem, area->first, area->second};
break;
case N3DS_EXTRA_RAM_PADDR:
target_mem = impl->n3ds_extra_ram_mem;
phys_mem_region_info_cache = {&impl->n3ds_extra_ram_mem, area->first, area->second};
break;
default:
UNREACHABLE();
}
if (offset_into_region > target_mem->GetSize()) [[unlikely]] {
physical_ptr_cache = {address, {nullptr}};
return physical_ptr_cache.second;
return phys_mem_region_info_cache;
}
u8* MemorySystem::GetPhysicalPointer(PAddr address) {
auto target_mem = GetPhysMemRegionInfo(address);
if (!target_mem.valid()) [[unlikely]] {
return {nullptr};
}
physical_ptr_cache = {address, {target_mem, offset_into_region}};
return physical_ptr_cache.second;
u32 offset_into_region = address - target_mem.region_start;
return target_mem.backing_mem->get()->GetPtr() + offset_into_region;
}
MemoryRef MemorySystem::GetPhysicalRef(PAddr address) {
const auto& target_mem = GetPhysMemRegionInfo(address);
if (!target_mem.valid()) [[unlikely]] {
return {nullptr};
}
u32 offset_into_region = address - target_mem.region_start;
return {*target_mem.backing_mem, offset_into_region};
}
std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) {

View File

@ -664,14 +664,35 @@ private:
*/
MemoryRef GetPointerForRasterizerCache(VAddr addr) const;
void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type);
class PhysMemRegionInfo {
public:
// Use a pointer to the shared pointer instead of the shared pointer directly to prevent
// overhead in hot code.
const std::shared_ptr<BackingMem>* backing_mem{};
std::pair<PAddr, MemoryRef> physical_ptr_cache;
PAddr region_start{};
PAddr region_end{};
PhysMemRegionInfo() = default;
PhysMemRegionInfo(const std::shared_ptr<BackingMem>* mem, PAddr reg_start, size_t reg_size)
: backing_mem(mem), region_start{reg_start},
region_end{reg_start + static_cast<PAddr>(reg_size)} {}
bool valid() const {
return backing_mem != nullptr;
}
};
PhysMemRegionInfo GetPhysMemRegionInfo(PAddr address);
void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type);
private:
class Impl;
std::unique_ptr<Impl> impl;
PhysMemRegionInfo phys_mem_region_info_cache{};
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version);

View File

@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstdint>
@ -272,7 +272,7 @@ void StartPicaTracing() {
}
void OnPicaRegWrite(u16 cmd_id, u16 mask, u32 value) {
if (!g_is_pica_tracing)
if (!g_is_pica_tracing) [[likely]]
return;
std::lock_guard lock(pica_trace_mutex);