mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-01-31 00:55:19 +01:00
Core: More memory hotfixes (#3954)
* Update memory.cpp * Fix CoalesceFreeRegions to account for address space gaps Fixes a regression in Saint's Row games.
This commit is contained in:
@@ -399,10 +399,11 @@ struct AddressSpace::Impl {
|
||||
auto it = std::prev(regions.upper_bound(virtual_addr));
|
||||
ASSERT_MSG(!it->second.is_mapped, "Cannot coalesce mapped regions");
|
||||
|
||||
// Check if there are free placeholders before this area.
|
||||
// Check if there are adjacent free placeholders before this area.
|
||||
bool can_coalesce = false;
|
||||
auto it_prev = it != regions.begin() ? std::prev(it) : regions.end();
|
||||
while (it_prev != regions.end() && !it_prev->second.is_mapped) {
|
||||
while (it_prev != regions.end() && !it_prev->second.is_mapped &&
|
||||
it_prev->first + it_prev->second.size == it->first) {
|
||||
// If there is an earlier region, move our iterator to that and increase size.
|
||||
it_prev->second.size = it_prev->second.size + it->second.size;
|
||||
regions.erase(it);
|
||||
@@ -415,9 +416,10 @@ struct AddressSpace::Impl {
|
||||
it_prev = it != regions.begin() ? std::prev(it) : regions.end();
|
||||
}
|
||||
|
||||
// Check if there are free placeholders after this area.
|
||||
// Check if there are adjacent free placeholders after this area.
|
||||
auto it_next = std::next(it);
|
||||
while (it_next != regions.end() && !it_next->second.is_mapped) {
|
||||
while (it_next != regions.end() && !it_next->second.is_mapped &&
|
||||
it->first + it->second.size == it_next->first) {
|
||||
// If there is a later region, increase our current region's size
|
||||
it->second.size = it->second.size + it_next->second.size;
|
||||
regions.erase(it_next);
|
||||
|
||||
@@ -117,7 +117,6 @@ void MemoryManager::SetPrtArea(u32 id, VAddr address, u64 size) {
|
||||
}
|
||||
|
||||
void MemoryManager::CopySparseMemory(VAddr virtual_addr, u8* dest, u64 size) {
|
||||
std::shared_lock lk{mutex};
|
||||
ASSERT_MSG(IsValidMapping(virtual_addr), "Attempted to access invalid address {:#x}",
|
||||
virtual_addr);
|
||||
|
||||
@@ -138,7 +137,6 @@ void MemoryManager::CopySparseMemory(VAddr virtual_addr, u8* dest, u64 size) {
|
||||
|
||||
bool MemoryManager::TryWriteBacking(void* address, const void* data, u64 size) {
|
||||
const VAddr virtual_addr = std::bit_cast<VAddr>(address);
|
||||
std::shared_lock lk{mutex};
|
||||
ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}",
|
||||
virtual_addr);
|
||||
|
||||
@@ -701,7 +699,7 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory
|
||||
}
|
||||
|
||||
s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) {
|
||||
mutex.lock();
|
||||
std::scoped_lock lk{mutex};
|
||||
ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}",
|
||||
virtual_addr);
|
||||
|
||||
@@ -710,7 +708,6 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) {
|
||||
while (it != vma_map.end() && it->second.base + it->second.size <= virtual_addr + size) {
|
||||
if (it->second.type != VMAType::PoolReserved && it->second.type != VMAType::Pooled) {
|
||||
LOG_ERROR(Kernel_Vmm, "Attempting to decommit non-pooled memory!");
|
||||
mutex.unlock();
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
it++;
|
||||
@@ -728,9 +725,7 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) {
|
||||
if (vma_base.type == VMAType::Pooled) {
|
||||
// We always map PoolCommitted memory to GPU, so unmap when decomitting.
|
||||
if (IsValidGpuMapping(current_addr, size_in_vma)) {
|
||||
mutex.unlock();
|
||||
rasterizer->UnmapMemory(current_addr, size_in_vma);
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
// Track how much pooled memory is decommitted
|
||||
@@ -781,7 +776,6 @@ s32 MemoryManager::PoolDecommit(VAddr virtual_addr, u64 size) {
|
||||
// Tracy memory tracking breaks from merging memory areas. Disabled for now.
|
||||
// TRACK_FREE(virtual_addr, "VMEM");
|
||||
|
||||
mutex.unlock();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@@ -789,13 +783,12 @@ s32 MemoryManager::UnmapMemory(VAddr virtual_addr, u64 size) {
|
||||
if (size == 0) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
mutex.lock();
|
||||
std::scoped_lock lk{mutex};
|
||||
virtual_addr = Common::AlignDown(virtual_addr, 16_KB);
|
||||
size = Common::AlignUp(size, 16_KB);
|
||||
ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}",
|
||||
virtual_addr);
|
||||
u64 bytes_unmapped = UnmapMemoryImpl(virtual_addr, size);
|
||||
mutex.unlock();
|
||||
return bytes_unmapped;
|
||||
}
|
||||
|
||||
@@ -873,9 +866,7 @@ u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma
|
||||
|
||||
// If this mapping has GPU access, unmap from GPU.
|
||||
if (IsValidGpuMapping(virtual_addr, size)) {
|
||||
mutex.unlock();
|
||||
rasterizer->UnmapMemory(virtual_addr, size);
|
||||
mutex.lock();
|
||||
}
|
||||
}
|
||||
return size_in_vma;
|
||||
|
||||
Reference in New Issue
Block a user