aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 00:54:10 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 00:54:10 -0400
commitc90ce4034dd125bb28ba7ea59b8d8e9f42147faf (patch)
tree9eb301ff14bde507010db93b570b1852d32d9b55 /src
parent74cbdf00565e17b793d4b4927538f4bfe9b9ac8d (diff)
nvdrv: reset the Switch 2 GPU globals when the module is created
The Switch 2 GPU memory registry, the queue semaphore regions and the nx2 driver/Ampere flags are globals, so a game started after another one in the same window inherited the previous game's GPU mappings and semaphore regions (the region table could fill up, and the new game's GPU waits never completed). Reset them when nvdrv's module is created.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nvdrv/devices/nx2_stub_device.h11
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp9
-rw-r--r--src/video_core/nx2.h7
3 files changed, 27 insertions, 0 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nx2_stub_device.h b/src/core/hle/service/nvdrv/devices/nx2_stub_device.h
index b91a929f68..08c21f09e3 100644
--- a/src/core/hle/service/nvdrv/devices/nx2_stub_device.h
+++ b/src/core/hle/service/nvdrv/devices/nx2_stub_device.h
@@ -98,6 +98,17 @@ public:
listeners.erase(owner);
}
+ // A new emulation session starts: forget the previous game's mappings and device ranges (its
+ // address spaces removed their listeners when they closed).
+ void Reset() {
+ {
+ std::scoped_lock lk{device_mutex};
+ device_ranges.clear();
+ }
+ std::scoped_lock lk{mutex};
+ mappings.clear();
+ }
+
// Device (SMMU) address of a CPU range an address space mapped; used to present images.
void RecordDeviceRange(u64 cpu_address, u64 size, u64 device_address) {
std::scoped_lock lk{device_mutex};
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 5cac2693c5..2be24e3f57 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -31,6 +31,7 @@
#include "core/hle/service/server_manager.h"
#include "frontend_common/firmware_manager.h"
#include "video_core/gpu.h"
+#include "video_core/nx2.h"
namespace Service::Nvidia {
@@ -126,6 +127,14 @@ void LoopProcess(Core::System& system) {
Module::Module(Core::System& system)
: container{system.Host1x()}, service_context{system, "nvdrv"}, events_interface{*this} {
+ // Switch 2 state kept in globals belongs to one emulation session. A game started after another
+ // in the same window inherited the previous game's GPU mappings and queue semaphore regions
+ // (their table filled up, so the new game's GPU waits never completed) and the Switch 2 flags.
+ Devices::Nx2GpuMemoryRegistry::Get().Reset();
+ Tegra::Nx2ClearSemaphoreRegions();
+ Devices::g_nx2_driver = false;
+ Tegra::g_nx2_ampere = false;
+ Core::g_nx2_present_count = 0;
nx2_stub_builder = [this, &system](DeviceFD fd, const std::string& name) {
auto device = std::make_shared<Devices::nx2_stub_device>(system, name);
open_files.emplace(fd, device);
diff --git a/src/video_core/nx2.h b/src/video_core/nx2.h
index 5b6d89abdd..04a01e5314 100644
--- a/src/video_core/nx2.h
+++ b/src/video_core/nx2.h
@@ -46,6 +46,13 @@ inline void Nx2RemoveSemaphoreRegion(u64 start) {
}
}
+/// A new emulation session starts: no queue has a region yet.
+inline void Nx2ClearSemaphoreRegions() {
+ for (auto& region : g_nx2_semaphore_regions) {
+ region.store(0);
+ }
+}
+
/// GPU VA in the first page that mirrors a release at `address`, or 0.
inline u64 Nx2SemaphoreMirror(u64 address) {
for (const auto& region : g_nx2_semaphore_regions) {