aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/dma_pusher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
-rw-r--r--src/video_core/dma_pusher.cpp28
1 files changed, 28 insertions, 0 deletions
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<u32> 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=<gpu address>: 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<u32>(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 {