Memory: Add function to flush a virtual range from the rasterizer cache
This is slightly more ergonomic to use, correctly handles virtual regions which are disjoint in physical addressing space, and checks only regions which can be cached by the rasterizer.
This commit is contained in:
parent
75be7907c1
commit
1423b3b10e
4 changed files with 72 additions and 47 deletions
|
@ -83,19 +83,13 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
|
|||
LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
|
||||
(base + size) * PAGE_SIZE);
|
||||
|
||||
u32 end = base + size;
|
||||
RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
|
||||
FlushMode::FlushAndInvalidate);
|
||||
|
||||
u32 end = base + size;
|
||||
while (base != end) {
|
||||
ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base);
|
||||
|
||||
// Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
|
||||
// null here
|
||||
if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
|
||||
current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
|
||||
PAGE_SIZE);
|
||||
}
|
||||
|
||||
current_page_table->attributes[base] = type;
|
||||
current_page_table->pointers[base] = memory;
|
||||
current_page_table->cached_res_count[base] = 0;
|
||||
|
@ -189,7 +183,7 @@ T Read(const VAddr vaddr) {
|
|||
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
|
||||
break;
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
|
||||
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
|
||||
|
||||
T value;
|
||||
std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T));
|
||||
|
@ -198,8 +192,7 @@ T Read(const VAddr vaddr) {
|
|||
case PageType::Special:
|
||||
return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
|
||||
case PageType::RasterizerCachedSpecial: {
|
||||
RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
|
||||
|
||||
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
|
||||
return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
|
||||
}
|
||||
default:
|
||||
|
@ -229,8 +222,7 @@ void Write(const VAddr vaddr, const T data) {
|
|||
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
|
||||
break;
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
|
||||
|
||||
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
|
||||
std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
|
||||
break;
|
||||
}
|
||||
|
@ -238,8 +230,7 @@ void Write(const VAddr vaddr, const T data) {
|
|||
WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
|
||||
break;
|
||||
case PageType::RasterizerCachedSpecial: {
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
|
||||
|
||||
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
|
||||
WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
|
||||
break;
|
||||
}
|
||||
|
@ -369,11 +360,48 @@ void RasterizerFlushRegion(PAddr start, u32 size) {
|
|||
}
|
||||
|
||||
void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) {
|
||||
// Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
|
||||
// null here
|
||||
if (VideoCore::g_renderer != nullptr) {
|
||||
VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size);
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
|
||||
// Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
|
||||
// null here
|
||||
if (VideoCore::g_renderer != nullptr) {
|
||||
VAddr end = start + size;
|
||||
|
||||
auto CheckRegion = [&](VAddr region_start, VAddr region_end) {
|
||||
if (start >= region_end || end <= region_start) {
|
||||
// No overlap with region
|
||||
return;
|
||||
}
|
||||
|
||||
VAddr overlap_start = std::max(start, region_start);
|
||||
VAddr overlap_end = std::min(end, region_end);
|
||||
|
||||
PAddr physical_start = TryVirtualToPhysicalAddress(overlap_start).value();
|
||||
u32 overlap_size = overlap_end - overlap_start;
|
||||
|
||||
auto* rasterizer = VideoCore::g_renderer->Rasterizer();
|
||||
switch (mode) {
|
||||
case FlushMode::Flush:
|
||||
rasterizer->FlushRegion(physical_start, overlap_size);
|
||||
break;
|
||||
case FlushMode::FlushAndInvalidate:
|
||||
rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END);
|
||||
CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END);
|
||||
CheckRegion(VRAM_VADDR, VRAM_VADDR_END);
|
||||
}
|
||||
}
|
||||
|
||||
u8 Read8(const VAddr addr) {
|
||||
return Read<u8>(addr);
|
||||
}
|
||||
|
@ -420,16 +448,13 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
|
|||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
|
||||
std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedSpecial: {
|
||||
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
|
||||
|
||||
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
|
||||
GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
|
@ -490,18 +515,13 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
|
|||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
|
||||
copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
|
||||
std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedSpecial: {
|
||||
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
|
||||
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
|
||||
copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
|
||||
GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
|
@ -547,18 +567,13 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
|
|||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
|
||||
copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
|
||||
std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedSpecial: {
|
||||
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
|
||||
|
||||
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
|
||||
copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
|
||||
GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
|
||||
break;
|
||||
}
|
||||
|
@ -603,15 +618,13 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
|
|||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
|
||||
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
|
||||
WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedSpecial: {
|
||||
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
|
||||
|
||||
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
|
||||
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
|
||||
|
||||
std::vector<u8> buffer(copy_amount);
|
||||
GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue