Skip to content

Commit

Permalink
Add "Create frame dump" to the in-game developer menu (that can be en…
Browse files Browse the repository at this point in the history
…abled in dev settings)

Makes it possible to create one without connecting the websocket
debugger, even on non-Windows platforms.
  • Loading branch information
hrydgard committed Aug 24, 2023
1 parent 58dc13e commit d2d8688
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 22 deletions.
17 changes: 10 additions & 7 deletions Core/Debugger/WebSocket/GPURecordSubscriber.cpp
Expand Up @@ -44,7 +44,7 @@ DebuggerSubscriber *WebSocketGPURecordInit(DebuggerEventHandlerMap &map) {
WebSocketGPURecordState::~WebSocketGPURecordState() {
// Clear the callback to hopefully avoid a crash.
if (pending_)
GPURecord::SetCallback(nullptr);
GPURecord::ClearCallback();
}

// Begin recording (gpu.record.dump)
Expand All @@ -56,18 +56,21 @@ WebSocketGPURecordState::~WebSocketGPURecordState() {
//
// Note: recording may take a moment.
void WebSocketGPURecordState::Dump(DebuggerRequest &req) {
if (!PSP_IsInited())
if (!PSP_IsInited()) {
return req.Fail("CPU not started");
}

if (!GPURecord::Activate())
return req.Fail("Recording already in progress");

pending_ = true;
GPURecord::SetCallback([=](const Path &filename) {
bool result = GPURecord::RecordNextFrame([=](const Path &filename) {
lastFilename_ = filename;
pending_ = false;
});

if (!result) {
return req.Fail("Recording already in progress");
}

pending_ = true;

const JsonNode *value = req.data.get("ticket");
lastTicket_ = value ? json_stringify(value) : "";
}
Expand Down
12 changes: 7 additions & 5 deletions GPU/Debugger/Record.cpp
Expand Up @@ -49,7 +49,7 @@
namespace GPURecord {

static bool active = false;
static bool nextFrame = false;
static std::atomic<bool> nextFrame = false;
static int flipLastAction = -1;
static int flipFinishAt = -1;
static uint32_t lastEdramTrans = 0x400;
Expand Down Expand Up @@ -601,18 +601,20 @@ bool IsActivePending() {
return nextFrame || active;
}

bool Activate() {
bool RecordNextFrame(const std::function<void(const Path &)> callback) {
if (!nextFrame) {
nextFrame = true;
flipLastAction = gpuStats.numFlips;
flipFinishAt = -1;
writeCallback = callback;
nextFrame = true;
return true;
}
return false;
}

void SetCallback(const std::function<void(const Path &)> callback) {
writeCallback = callback;
void ClearCallback() {
// Not super thread safe..
writeCallback = nullptr;
}

static void FinishRecording() {
Expand Down
5 changes: 2 additions & 3 deletions GPU/Debugger/Record.h
Expand Up @@ -27,9 +27,8 @@ namespace GPURecord {

bool IsActive();
bool IsActivePending();
bool Activate();
// Call only if Activate() returns true.
void SetCallback(const std::function<void(const Path &)> callback);
bool RecordNextFrame(const std::function<void(const Path &)> callback);
void ClearCallback();

void NotifyCommand(u32 pc);
void NotifyMemcpy(u32 dest, u32 src, u32 sz);
Expand Down
25 changes: 21 additions & 4 deletions UI/DevScreens.cpp
Expand Up @@ -63,6 +63,7 @@
#include "Core/MIPS/JitCommon/JitBlockCache.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/MIPS/JitCommon/JitState.h"
#include "GPU/Debugger/Record.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
#include "UI/MiscScreens.h"
Expand Down Expand Up @@ -139,11 +140,27 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) {
return UI::EVENT_DONE;
});

items->Add(new Choice(dev->T("Dump next frame to log")))->OnClick.Add([](UI::EventParams &e) {
gpu->DumpNextFrame();
items->Add(new Choice(dev->T("Reset limited logging")))->OnClick.Handle(this, &DevMenuScreen::OnResetLimitedLogging);

items->Add(new Choice(dev->T("Create frame dump")))->OnClick.Add([](UI::EventParams &e) {
GPURecord::RecordNextFrame([](const Path &dumpPath) {
NOTICE_LOG(SYSTEM, "Frame dump created at '%s'", dumpPath.c_str());
if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) {
System_ShowFileInFolder(dumpPath);
} else {
g_OSD.Show(OSDType::MESSAGE_SUCCESS, dumpPath.ToVisualString(), 7.0f);
}
});
return UI::EVENT_DONE;
});
items->Add(new Choice(dev->T("Reset limited logging")))->OnClick.Handle(this, &DevMenuScreen::OnResetLimitedLogging);

// This one is not very useful these days, and only really on desktop. Hide it on other platforms.
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_DESKTOP) {
items->Add(new Choice(dev->T("Dump next frame to log")))->OnClick.Add([](UI::EventParams &e) {
gpu->DumpNextFrame();
return UI::EVENT_DONE;
});
}

scroll->Add(items);
parent->Add(scroll);
Expand Down Expand Up @@ -1422,4 +1439,4 @@ void FrameDumpTestScreen::update() {
}
RecreateViews();
}
}
}
5 changes: 2 additions & 3 deletions Windows/GEDebugger/GEDebugger.cpp
Expand Up @@ -1212,11 +1212,10 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
break;

case IDC_GEDBG_RECORD:
GPURecord::SetCallback([](const Path &path) {
// Opens a Windows Explorer window with the file.
GPURecord::RecordNextFrame([](const Path &path) {
// Opens a Windows Explorer window with the file, when done.
System_ShowFileInFolder(path);
});
GPURecord::Activate();
break;

case IDC_GEDBG_FLUSH:
Expand Down
1 change: 1 addition & 0 deletions assets/lang/en_US.ini
Expand Up @@ -302,6 +302,7 @@ Block address = Block address
By Address = By address
Control Debug = Control Debug
Copy savestates to memstick root = Copy save states to Memory Stick root
Create frame dump = Create frame dump
Create/Open textures.ini file for current game = Create/Open textures.ini file for current game
Current = Current
Dev Tools = Development tools
Expand Down

0 comments on commit d2d8688

Please sign in to comment.