aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/memory_manager.cpp
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 03:39:52 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 03:39:52 -0400
commite17fd9cef116a088f080ca502951e500864a58b6 (patch)
treee7ff65f614622515d6a2e4263521909eea89a5d8 /src/video_core/memory_manager.cpp
parentea6c1193fbfa95e586bb6d129dc684163a12cb3e (diff)
parent80c79333fe6fd28a31b65b997f1cbf2987711c91 (diff)
Merge Switch 2 work from local Eden (nx2 at b0dd3fe)
Diffstat (limited to 'src/video_core/memory_manager.cpp')
-rw-r--r--src/video_core/memory_manager.cpp32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 8ffdcb6276..0eae8fac24 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -22,6 +22,10 @@
#include "video_core/texture_cache/util.h"
namespace Tegra {
+bool MemoryManager::IsShuttingDown() const {
+ return system.IsShuttingDown();
+}
+
using Tegra::Memory::GuestMemoryFlags;
std::atomic<size_t> MemoryManager::unique_identifier_generator{};
@@ -56,6 +60,10 @@ MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, GPU
: MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, split_address_, big_page_bits_, page_bits_)
{}
+void MemoryManager::SetNativeSyncpointShim(GPUVAddr address) {
+ native_syncpoint_shim.store(address, std::memory_order_release);
+}
+
MemoryManager::~MemoryManager() = default;
MemoryManager::EntryType MemoryManager::GetEntry(size_t position, bool is_big_page) const {
@@ -231,6 +239,15 @@ std::optional<DAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr, std::size_t s
template <typename T>
T MemoryManager::Read(GPUVAddr addr) const {
+ if constexpr (sizeof(T) == sizeof(u32)) {
+ const auto shim = native_syncpoint_shim.load(std::memory_order_acquire);
+ if (shim && addr >= shim && addr - shim < NumShimSyncpoints * sizeof(u32) &&
+ Common::IsAligned(addr - shim, sizeof(u32))) {
+ return static_cast<T>(system.Host1x().GetSyncpointManager().GetGuestSyncpointValue(
+ static_cast<u32>((addr - shim) / sizeof(u32))));
+ }
+ }
+
if (auto page_pointer{GetPointer(addr)}; page_pointer) {
// NOTE: Avoid adding any extra logic to this fast-path block
T value;
@@ -238,7 +255,10 @@ T MemoryManager::Read(GPUVAddr addr) const {
return value;
}
- ASSERT(false);
+ static std::atomic<u32> reported{};
+ if (reported.fetch_add(1) < 16) {
+ LOG_ERROR(HW_GPU, "Read{} of unmapped GPU address {:#x}", sizeof(T) * 8, addr);
+ }
return {};
}
@@ -390,6 +410,16 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
}
void MemoryManager::ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer, const std::size_t size) const {
+ // Small reads within one 4 KiB page (texture and sampler descriptors, several per draw): one
+ // translation and a copy, as Read<T> does, instead of the page walk (~3% of the GPU thread
+ // in title 1). Anything else, unmapped or sparse pages included, takes the full path.
+ constexpr std::size_t SmallPage = 0x1000;
+ if (size <= SmallPage && (gpu_src_addr & (SmallPage - 1)) + size <= SmallPage) {
+ if (const u8* const pointer = GetPointer(gpu_src_addr)) {
+ std::memcpy(dest_buffer, pointer, size);
+ return;
+ }
+ }
ReadBlockImpl(gpu_src_addr, dest_buffer, size, VideoCommon::CacheType::None, true);
}