summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/gsp_gpu.cpp11
-rw-r--r--src/core/hle/service/y2r_u.cpp4
-rw-r--r--src/core/memory.cpp91
-rw-r--r--src/core/memory.h13
4 files changed, 72 insertions, 47 deletions
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index bc964ec60..88684b82d 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -475,12 +475,11 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
// TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
// possible/likely
- Memory::RasterizerFlushRegion(
- Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
- command.dma_request.size);
- Memory::RasterizerFlushAndInvalidateRegion(
- Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
- command.dma_request.size);
+ Memory::RasterizerFlushVirtualRegion(command.dma_request.source_address,
+ command.dma_request.size, Memory::FlushMode::Flush);
+ Memory::RasterizerFlushVirtualRegion(command.dma_request.dest_address,
+ command.dma_request.size,
+ Memory::FlushMode::FlushAndInvalidate);
// TODO(Subv): These memory accesses should not go through the application's memory mapping.
// They should go through the GSP module's memory mapping.
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index e73971d5f..57172ddd6 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -587,8 +587,8 @@ static void StartConversion(Interface* self) {
// dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
u32 total_output_size =
conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
- Memory::RasterizerFlushAndInvalidateRegion(
- Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
+ Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size,
+ Memory::FlushMode::FlushAndInvalidate);
HW::Y2R::PerformConversion(conversion);
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 42ca69e00..38fe9e231 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -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());
diff --git a/src/core/memory.h b/src/core/memory.h
index 96ce9e52e..c8c56babd 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -190,6 +190,19 @@ void RasterizerFlushRegion(PAddr start, u32 size);
*/
void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size);
+enum class FlushMode {
+ /// Write back modified surfaces to RAM
+ Flush,
+ /// Write back modified surfaces to RAM, and also remove them from the cache
+ FlushAndInvalidate,
+};
+
+/**
+ * Flushes and invalidates any externally cached rasterizer resources touching the given virtual
+ * address region.
+ */
+void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
+
/**
* Dynarmic has an optimization to memory accesses when the pointer to the page exists that
* can be used by setting up the current page table as a callback. This function is used to