aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/engines/maxwell_3d.cpp
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 07:47:45 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 07:47:45 -0400
commit1d7758b714da7eede15664676007668bdee19946 (patch)
tree263c43c3bb9fbad91dd9561ced9dd44260b210b4 /src/video_core/engines/maxwell_3d.cpp
parent11a775e2aa084db58fadf6dc171d5f25bf592dfc (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.cpp21
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) {