aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/memory_manager.cpp
diff options
context:
space:
mode:
authornéo Luigi <85024393+neoluigi4123@users.noreply.github.com>2026-11-03 00:49:36 +0100
committernéo Luigi <85024393+neoluigi4123@users.noreply.github.com>2026-11-03 00:49:36 +0100
commitc84e5caf82a786f748c233e27b7f4ed9aaad9f44 (patch)
tree3ec9cab90d74292445d0a076370933bac946fc4d /src/video_core/memory_manager.cpp
parent2b413a46a2820f0a646baaa8dbd683009f096f32 (diff)
parentefa7c19e59839f0d464c2e9bd41f9ca8f867fef0 (diff)
Merge remote-tracking branch 'origin/nx2' into neo.ai/vibration-fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # src/core/hle/service/hid/hid_server.cpp # src/core/hle/service/hid/hid_server.h
Diffstat (limited to 'src/video_core/memory_manager.cpp')
-rw-r--r--src/video_core/memory_manager.cpp24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 9111ba10d2..ddfd2529fd 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -302,7 +302,7 @@ void MemoryManager::Write(GPUVAddr addr, T data) {
return;
}
// A Switch 2 sparse block nobody wrote yet gets its memory now.
- Tegra::Nx2BackSparseWrite(addr, sizeof(T));
+ Tegra::Nx2BackSparseWrite(addr, sizeof(T), &data);
if (auto page_pointer{GetPointer(addr)}; page_pointer) {
std::memcpy(page_pointer, &data, sizeof(T));
return;
@@ -431,11 +431,14 @@ void MemoryManager::ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std:
if (!unsafe) {
rasterizer->FlushRegion(dev_addr_base, copy_amount, which);
}
- if (!IsBigPageContinuous(page_index)) [[unlikely]] {
- memory.ReadBlockUnsafe(dev_addr_base, dest_buffer, copy_amount);
- } else {
- u8* physical = memory.GetPointer<u8>(dev_addr_base);
+ // A continuous big page may still have no host memory (a Switch 2 region backed as it is
+ // written, while its backing is pending): the per-page copy handles that.
+ u8* const physical = IsBigPageContinuous(page_index) ? memory.GetPointer<u8>(dev_addr_base)
+ : nullptr;
+ if (physical != nullptr) [[likely]] {
std::memcpy(dest_buffer, physical, copy_amount);
+ } else {
+ memory.ReadBlockUnsafe(dev_addr_base, dest_buffer, copy_amount);
}
dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
};
@@ -466,7 +469,7 @@ void MemoryManager::ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer, co
void MemoryManager::WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size, [[maybe_unused]] VideoCommon::CacheType which, bool unsafe) {
// Give Switch 2 sparse pages the write lands on their memory first (otherwise it is dropped).
- Tegra::Nx2BackSparseWrite(gpu_dest_addr, size);
+ Tegra::Nx2BackSparseWrite(gpu_dest_addr, size, src_buffer);
auto just_advance = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, std::size_t copy_amount) {
src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
};
@@ -485,11 +488,12 @@ void MemoryManager::WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffe
if (!unsafe) {
rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which);
}
- if (!IsBigPageContinuous(page_index)) [[unlikely]] {
- memory.WriteBlockUnsafe(dev_addr_base, src_buffer, copy_amount);
- } else {
- u8* physical = memory.GetPointer<u8>(dev_addr_base);
+ u8* const physical = IsBigPageContinuous(page_index) ? memory.GetPointer<u8>(dev_addr_base)
+ : nullptr;
+ if (physical != nullptr) [[likely]] {
std::memcpy(physical, src_buffer, copy_amount);
+ } else {
+ memory.WriteBlockUnsafe(dev_addr_base, src_buffer, copy_amount);
}
src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
};