diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 9ee5136c5..86e737d5f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -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 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 MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) { diff --git a/src/core/memory.h b/src/core/memory.h index ada5182b2..802dd8d6c 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -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* backing_mem{}; - std::pair physical_ptr_cache; + PAddr region_start{}; + PAddr region_end{}; + + PhysMemRegionInfo() = default; + + PhysMemRegionInfo(const std::shared_ptr* mem, PAddr reg_start, size_t reg_size) + : backing_mem(mem), region_start{reg_start}, + region_end{reg_start + static_cast(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; + PhysMemRegionInfo phys_mem_region_info_cache{}; + friend class boost::serialization::access; template void serialize(Archive& ar, const unsigned int file_version); diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index 88ee841c1..0331a6fea 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -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 @@ -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);