diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 07:47:45 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 07:47:45 -0400 |
| commit | 1d7758b714da7eede15664676007668bdee19946 (patch) | |
| tree | 263c43c3bb9fbad91dd9561ced9dd44260b210b4 /src/video_core/engines/maxwell_3d.cpp | |
| parent | 11a775e2aa084db58fadf6dc171d5f25bf592dfc (diff) | |
nx2: method data continues across GPFIFO entries
Title 4 calls a 3D macro with a 6-word IncreaseOnce header, ends the main
GPFIFO entry after the first word and supplies the other five in a 5-word
subroutine entry. The split-method parking (an entry elsewhere was treated
as a call with a clean method state) fed those parameters to the parser as
headers: the macro ran with garbage, later draws read megabytes of unmapped
memory and the host driver timed out at the loading screen after the dock
scene. As on the hardware, the method state now simply continues; the old
guess stays behind EDEN_NX2_PARK_SPLIT_METHODS.
Debug aids: splits are logged at debug level with the words around them,
and a 3D write that interrupts a macro's parameters dumps the last 48 writes.
Diffstat (limited to 'src/video_core/engines/maxwell_3d.cpp')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 4ef2bbc11b..7884d8009c 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -405,9 +405,13 @@ void Maxwell3D::TraceFirstMethodWrite(u32 method, u32 argument) { void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { // It is an error to write to a register other than the current macro's ARG register before // it has finished execution. + if (executing_macro != 0 && method != executing_macro + 1) { + DumpRecentWrites(method); + } if (executing_macro != 0) { ASSERT(method == executing_macro + 1); } + RecordWrite(method, method_argument, 1, is_last_call ? 1 : 2); // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. @@ -423,7 +427,24 @@ void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument ProcessMethodCall(method, argument, method_argument, is_last_call); } +void Maxwell3D::DumpRecentWrites(u32 method) { + static u32 dumps{}; + if (dumps++ >= 4) { + return; + } + LOG_ERROR(HW_GPU, "Write to {:#x} while macro {:#x} collects parameters ({} so far); last writes:", + method, executing_macro, macro_params.size()); + for (size_t i = 0; i < recent_writes.size(); ++i) { + const auto& w = recent_writes[(recent_write_index + i) % recent_writes.size()]; + if (w.amount != 0) { + LOG_ERROR(HW_GPU, " method {:#x} arg {:#x} amount {} pending {}", w.method, w.argument, + w.amount, w.pending); + } + } +} + void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { + RecordWrite(method, amount ? base_start[0] : 0, amount, methods_pending); // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. if (method >= MacroRegistersStart) { |
