mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 02:09:05 +02:00
Merge pull request #17971 from hrydgard/easier-ge-frame-dump
Add "Create frame dump" to the in-game developer menu
This commit is contained in:
6 files changed
+43
-22
No files matched your search
@@ -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)
|
||||
@@ -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) : "";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
+21
-4
@@ -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"
|
||||
@@ -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);
|
||||
@@ -1422,4 +1439,4 @@ void FrameDumpTestScreen::update() {
|
||||
}
|
||||
RecreateViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user