aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/gpu_split.cpp
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 11:55:07 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 20:49:48 -0400
commit15e953cafd5cb348833cb373d7ddd996b81307f7 (patch)
tree3fd08c6943dd5b620fe1c899c283c1c78a6a5545 /src/video_core/gpu_split.cpp
parent17c10c3690eab1ab461318f7e3e8850d490fb753 (diff)
video_core: GPU thread split on by default for Switch 2 titles; cheaper front paths
Clean A/B in title 1 (3 rounds each): 1.46x the draws a second of one thread, frames 17% shorter, no crashes, front register copies equal to the back's in 57,089 checks. EDEN_NX2_SPLIT=0 runs everything on one thread, =1 keeps macros on the back. The front's per-write paths no longer check guarded statics (GpuSplit::Get, Nx2Profile::Enabled, the skip-same switches) and the ring's method writes are inline. Notes row 145.
Diffstat (limited to 'src/video_core/gpu_split.cpp')
-rw-r--r--src/video_core/gpu_split.cpp36
1 files changed, 4 insertions, 32 deletions
diff --git a/src/video_core/gpu_split.cpp b/src/video_core/gpu_split.cpp
index 970fc0b559..07fda589ff 100644
--- a/src/video_core/gpu_split.cpp
+++ b/src/video_core/gpu_split.cpp
@@ -80,15 +80,12 @@ void GpuSplit::CheckOwner(const char* where) {
#endif
}
-GpuSplit& GpuSplit::Get() {
- static GpuSplit split;
- return split;
-}
+GpuSplit GpuSplit::instance;
void GpuSplit::MaybeStart(Core::System& system_) {
static const char mode = [] {
const char* value = std::getenv("EDEN_NX2_SPLIT");
- return value != nullptr ? value[0] : '0';
+ return value != nullptr ? value[0] : '2';
}();
const bool wanted = mode == '1' || mode == '2';
if (active || !wanted || !Tegra::g_nx2_ampere.load(std::memory_order_relaxed)) {
@@ -127,7 +124,7 @@ void GpuSplit::Stop() {
active = false;
}
-u64* GpuSplit::Reserve(size_t words) {
+u64* GpuSplit::ReserveSlow(size_t words) {
size_t index = write_position & RingMask;
if (index + words > RingWords) {
// Entries never wrap: skip to the start of the ring.
@@ -194,10 +191,7 @@ void GpuSplit::Drain() {
}
}
-void GpuSplit::SelectEngine(Tegra::Engines::EngineInterface* engine) {
- if (engine == front_engine) {
- return;
- }
+void GpuSplit::SwitchEngine(Tegra::Engines::EngineInterface* engine) {
front_engine = engine;
u64* const entry = Reserve(2);
entry[0] = static_cast<u64>(Kind::Engine);
@@ -205,28 +199,6 @@ void GpuSplit::SelectEngine(Tegra::Engines::EngineInterface* engine) {
Commit(2);
}
-void GpuSplit::Method(Tegra::Engines::EngineInterface* engine, u32 method, u32 argument,
- bool is_last, const GPUVAddr* segment) {
- SelectEngine(engine);
- const size_t words = segment != nullptr ? 2 : 1;
- u64* const entry = Reserve(words);
- entry[0] = static_cast<u64>(Kind::Method) | (is_last ? IsLast : 0) |
- (segment != nullptr ? HasSegment : 0) | (u64{method & 0xffff} << 8) |
- (u64{argument} << 32);
- if (segment != nullptr) {
- entry[1] = *segment;
- }
- Commit(words);
-}
-
-void GpuSplit::MacroWrite(Tegra::Engines::EngineInterface* engine, u32 method, u32 argument) {
- SelectEngine(engine);
- u64* const entry = Reserve(1);
- entry[0] = static_cast<u64>(Kind::Method) | IsLast | Direct | (u64{method & 0xffff} << 8) |
- (u64{argument} << 32);
- Commit(1);
-}
-
void GpuSplit::MultiMethod(Tegra::Engines::EngineInterface* engine, u32 method, const u32* words,
u32 amount, u32 methods_pending, const GPUVAddr* segment) {
SelectEngine(engine);