From a5e528e2d0bc784ebf24850e5913cece912c685e Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Wed, 28 Oct 2026 00:24:14 -0400 Subject: nx2: get title 4 past the difficulty confirm - MME: implement MME_DMA_READ / MME_DMA_READ_FIFOED (Turing macros read query results into their load FIFO; the conditional-render macro at 0x142 needs it). - vi2 present waits up to 4 s for the frame fence (was 250 ms) so shader compile stalls don't let the game lap its equal-value gate semaphores. - Native QMD: fire the third release slot at word 52, which NVN2 patches for queue-to-queue syncs (compute queue releasing a gate the 3D queue waits on). - Compute class SET_REPORT_SEMAPHORE (0x6c0-0x6c3) releases. - Ampere lowering: AOFFI, any LOP3 truth table, STG RZ, LDG 0x981, IABS, I2FP rounding, IMAD negated addend, SHFL 0x989 (all 77 title-4 shaders lower). - Debug: EDEN_NX2_SEM_WATCH= traces acquires, releases, method arguments and compute macro emits for one semaphore block; EDEN_NX2_KEY_SCRIPT scripted key presses; per-submit logs moved to TRACE. --- src/video_core/dma_pusher.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/video_core/dma_pusher.cpp') diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 2c95b6de03..040bf18362 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -13,6 +13,7 @@ #include "core/core.h" #include "core/memory.h" #include "video_core/dma_pusher.h" +#include "video_core/control/channel_state.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/gpu.h" #include "video_core/guest_memory.h" @@ -134,6 +135,16 @@ bool DmaPusher::Step() { if (++dma_pushbuffer_subindex >= command_list_size) { // A split method resumes within the submission that split it; ring addresses repeat // every frame, so a stale one could otherwise swallow the headers of a later entry. + for (const auto& parked : parked_methods) { + static std::atomic reported{}; + if (reported.fetch_add(1) < 16) { + LOG_WARNING(HW_GPU, + "Submission ended with parked method {:#x} (sub {}, {} words left, " + "resume {:#x})", + parked.method, parked.subchannel, parked.method_count, + parked.resume_address); + } + } parked_methods.clear(); dma_pushbuffer.pop(); dma_pushbuffer_subindex = 0; @@ -264,7 +275,21 @@ void DmaPusher::SetState(const CommandHeader& command_header) { dma_state.method_count = command_header.method_count; } +// EDEN_NX2_SEM_WATCH=: log every method whose argument is the low word of an +// address in the 16 bytes there (finds the engine and method that release a semaphore). +void DmaPusher::WatchArgument(u32 method, u32 argument) const { + static const u32 watch = [] { + const char* value = std::getenv("EDEN_NX2_SEM_WATCH"); + return value ? static_cast(std::strtoull(value, nullptr, 16)) : 0U; + }(); + if (watch != 0 && (argument & ~0xfU) == watch) { + LOG_INFO(HW_GPU, "Semaphore watch: channel {} subchannel {} method {:#x} argument {:#x}", + channel_state.bind_id, dma_state.subchannel, method, argument); + } +} + void DmaPusher::CallMethod(u32 argument) { + WatchArgument(dma_state.method, argument); if (dma_state.method < non_puller_methods) { puller.CallPullerMethod(*this, Engines::Puller::MethodCall{ dma_state.method, @@ -289,6 +314,9 @@ void DmaPusher::CallMethod(u32 argument) { } void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) { + for (u32 i = 0; i < num_methods; ++i) { + WatchArgument(dma_state.method + (dma_state.non_incrementing ? 0 : i), base_start[i]); + } if (dma_state.method < non_puller_methods) { puller.CallMultiMethod(*this, dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count); } else { -- cgit v1.2.3