Memory: replace PhysicalToVirtualAddress with a more dedicated function
There is no external use of PhysicalToVirtualAddress any more, so it there is no need to have a generic function that handles all physical regions. Also, the previous APT change makes it possible that linear heap has some regions mapped to old and new VAddr regions at the same time, so we need to check both region and mark cached for the mapped one. RasterizerMarkRegionCached would skip the unmapped one in its loop
This commit is contained in:
parent
8c65433ab5
commit
2654a679b3
|
@ -318,6 +318,22 @@ u8* GetPhysicalPointer(PAddr address) {
|
||||||
return target_pointer;
|
return target_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
|
||||||
|
static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) {
|
||||||
|
if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
|
||||||
|
return {addr - VRAM_PADDR + VRAM_VADDR};
|
||||||
|
} else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
|
||||||
|
return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR};
|
||||||
|
} else {
|
||||||
|
// While the physical <-> virtual mapping is 1:1 for the regions supported by the cache,
|
||||||
|
// some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond
|
||||||
|
// the end address of VRAM, causing the Virtual->Physical translation to fail when flushing
|
||||||
|
// parts of the texture.
|
||||||
|
LOG_ERROR(HW_Memory, "Trying to use invalid physical address for rasterizer: {:08X}", addr);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) {
|
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) {
|
||||||
if (start == 0) {
|
if (start == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -327,19 +343,7 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) {
|
||||||
PAddr paddr = start;
|
PAddr paddr = start;
|
||||||
|
|
||||||
for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
|
for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
|
||||||
std::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr);
|
for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) {
|
||||||
// While the physical <-> virtual mapping is 1:1 for the regions supported by the cache,
|
|
||||||
// some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond
|
|
||||||
// the end address of VRAM, causing the Virtual->Physical translation to fail when flushing
|
|
||||||
// parts of the texture.
|
|
||||||
if (!maybe_vaddr) {
|
|
||||||
LOG_ERROR(HW_Memory,
|
|
||||||
"Trying to flush a cached region to an invalid physical address {:08X}",
|
|
||||||
paddr);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
VAddr vaddr = *maybe_vaddr;
|
|
||||||
|
|
||||||
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||||
|
|
||||||
if (cached) {
|
if (cached) {
|
||||||
|
@ -366,9 +370,9 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) {
|
||||||
case PageType::RasterizerCachedMemory: {
|
case PageType::RasterizerCachedMemory: {
|
||||||
u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
|
u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
|
||||||
if (pointer == nullptr) {
|
if (pointer == nullptr) {
|
||||||
// It's possible that this function has been called while updating the pagetable
|
// It's possible that this function has been called while updating the
|
||||||
// after unmapping a VMA. In that case the underlying VMA will no longer exist,
|
// pagetable after unmapping a VMA. In that case the underlying VMA will no
|
||||||
// and we should just leave the pagetable entry blank.
|
// longer exist, and we should just leave the pagetable entry blank.
|
||||||
page_type = PageType::Unmapped;
|
page_type = PageType::Unmapped;
|
||||||
} else {
|
} else {
|
||||||
page_type = PageType::Memory;
|
page_type = PageType::Memory;
|
||||||
|
@ -382,6 +386,7 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerFlushRegion(PAddr start, u32 size) {
|
void RasterizerFlushRegion(PAddr start, u32 size) {
|
||||||
if (VideoCore::g_renderer == nullptr) {
|
if (VideoCore::g_renderer == nullptr) {
|
||||||
|
@ -820,25 +825,6 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) {
|
||||||
return *paddr;
|
return *paddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
|
|
||||||
if (addr == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
|
|
||||||
return addr - VRAM_PADDR + VRAM_VADDR;
|
|
||||||
} else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
|
|
||||||
return addr - FCRAM_PADDR +
|
|
||||||
Core::System::GetInstance().Kernel().GetCurrentProcess()->GetLinearHeapAreaAddress();
|
|
||||||
} else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
|
|
||||||
return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
|
|
||||||
} else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
|
|
||||||
return addr - IO_AREA_PADDR + IO_AREA_VADDR;
|
|
||||||
} else if (addr >= N3DS_EXTRA_RAM_PADDR && addr < N3DS_EXTRA_RAM_PADDR_END) {
|
|
||||||
return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetFCRAMOffset(u8* pointer) {
|
u32 GetFCRAMOffset(u8* pointer) {
|
||||||
ASSERT(pointer >= fcram.data() && pointer < fcram.data() + fcram.size());
|
ASSERT(pointer >= fcram.data() && pointer < fcram.data() + fcram.size());
|
||||||
return pointer - fcram.data();
|
return pointer - fcram.data();
|
||||||
|
|
|
@ -228,11 +228,6 @@ std::optional<PAddr> TryVirtualToPhysicalAddress(VAddr addr);
|
||||||
*/
|
*/
|
||||||
PAddr VirtualToPhysicalAddress(VAddr addr);
|
PAddr VirtualToPhysicalAddress(VAddr addr);
|
||||||
|
|
||||||
/**
|
|
||||||
* Undoes a mapping performed by VirtualToPhysicalAddress().
|
|
||||||
*/
|
|
||||||
std::optional<VAddr> PhysicalToVirtualAddress(PAddr paddr);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a pointer to the memory region beginning at the specified physical address.
|
* Gets a pointer to the memory region beginning at the specified physical address.
|
||||||
*/
|
*/
|
||||||
|
|
Reference in New Issue