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
3 changed files with 59 additions and 27 deletions
+33 -22
View File
@@ -638,13 +638,10 @@ std::string MemorySystem::ReadCString(VAddr vaddr, std::size_t max_length) {
return string; return string;
} }
u8* MemorySystem::GetPhysicalPointer(PAddr address) { MemorySystem::PhysMemRegionInfo MemorySystem::GetPhysMemRegionInfo(PAddr address) {
return GetPhysicalRef(address); if (address >= phys_mem_region_info_cache.region_start &&
} address < phys_mem_region_info_cache.region_end) {
return phys_mem_region_info_cache;
MemoryRef MemorySystem::GetPhysicalRef(PAddr address) {
if (address == physical_ptr_cache.first) {
return physical_ptr_cache.second;
} }
constexpr std::array memory_areas = { constexpr std::array memory_areas = {
@@ -661,38 +658,52 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) {
}); });
if (area == memory_areas.end()) [[unlikely]] { 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()); impl->GetPC());
physical_ptr_cache = {address, {nullptr}}; phys_mem_region_info_cache = PhysMemRegionInfo();
return physical_ptr_cache.second; return phys_mem_region_info_cache;
} }
u32 offset_into_region = address - area->first;
std::shared_ptr<BackingMem> target_mem = nullptr;
switch (area->first) { switch (area->first) {
case VRAM_PADDR: case VRAM_PADDR:
target_mem = impl->vram_mem; phys_mem_region_info_cache = {&impl->vram_mem, area->first, area->second};
break; break;
case DSP_RAM_PADDR: case DSP_RAM_PADDR:
target_mem = impl->dsp_mem; phys_mem_region_info_cache = {&impl->dsp_mem, area->first, area->second};
break; break;
case FCRAM_PADDR: case FCRAM_PADDR:
target_mem = impl->fcram_mem; phys_mem_region_info_cache = {&impl->fcram_mem, area->first, area->second};
break; break;
case N3DS_EXTRA_RAM_PADDR: 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; break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
if (offset_into_region > target_mem->GetSize()) [[unlikely]] {
physical_ptr_cache = {address, {nullptr}}; return phys_mem_region_info_cache;
return physical_ptr_cache.second; }
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}}; u32 offset_into_region = address - target_mem.region_start;
return physical_ptr_cache.second; 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) { std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) {
+23 -2
View File
@@ -664,14 +664,35 @@ private:
*/ */
MemoryRef GetPointerForRasterizerCache(VAddr addr) const; 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: private:
class Impl; class Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;
PhysMemRegionInfo phys_mem_region_info_cache{};
friend class boost::serialization::access; friend class boost::serialization::access;
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int file_version); void serialize(Archive& ar, const unsigned int file_version);
+3 -3
View File
@@ -1,5 +1,5 @@
// Copyright 2014 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cstdint> #include <cstdint>
@@ -272,7 +272,7 @@ void StartPicaTracing() {
} }
void OnPicaRegWrite(u16 cmd_id, u16 mask, u32 value) { void OnPicaRegWrite(u16 cmd_id, u16 mask, u32 value) {
if (!g_is_pica_tracing) if (!g_is_pica_tracing) [[likely]]
return; return;
std::lock_guard lock(pica_trace_mutex); std::lock_guard lock(pica_trace_mutex);