mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Merge pull request #11345 from unknownbrackets/debugger
Expose GE dump recording in WebSocket API
This commit is contained in:
commit
3d1e0e012b
@ -1357,6 +1357,8 @@ set(GPU_SOURCES
|
||||
GPU/Common/SplineCommon.h
|
||||
GPU/Debugger/Breakpoints.cpp
|
||||
GPU/Debugger/Breakpoints.h
|
||||
GPU/Debugger/Debugger.cpp
|
||||
GPU/Debugger/Debugger.h
|
||||
GPU/Debugger/Record.cpp
|
||||
GPU/Debugger/Record.h
|
||||
GPU/Debugger/Stepping.cpp
|
||||
@ -1430,6 +1432,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
||||
Core/Debugger/WebSocket/GameSubscriber.h
|
||||
Core/Debugger/WebSocket/GPUBufferSubscriber.cpp
|
||||
Core/Debugger/WebSocket/GPUBufferSubscriber.h
|
||||
Core/Debugger/WebSocket/GPURecordSubscriber.cpp
|
||||
Core/Debugger/WebSocket/GPURecordSubscriber.h
|
||||
Core/Debugger/WebSocket/HLESubscriber.cpp
|
||||
Core/Debugger/WebSocket/HLESubscriber.h
|
||||
Core/Debugger/WebSocket/LogBroadcaster.cpp
|
||||
|
@ -188,6 +188,7 @@
|
||||
<ClCompile Include="Debugger\WebSocket\GameBroadcaster.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\GameSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\GPUBufferSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\GPURecordSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\HLESubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\LogBroadcaster.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\DisasmSubscriber.cpp" />
|
||||
@ -549,6 +550,7 @@
|
||||
<ClInclude Include="Debugger\WebSocket\GameSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\DisasmSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\GPUBufferSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\GPURecordSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\HLESubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\SteppingSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\WebSocketUtils.h" />
|
||||
|
@ -734,6 +734,9 @@
|
||||
<ClCompile Include="HLE\sceUsbAcc.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\WebSocket\GPURecordSubscriber.cpp">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@ -1361,6 +1364,9 @@
|
||||
<ClInclude Include="HLE\sceUsbAcc.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\WebSocket\GPURecordSubscriber.h">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -53,24 +53,20 @@
|
||||
#include "Core/Debugger/WebSocket/DisasmSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/GameSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/GPUBufferSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/GPURecordSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/HLESubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/SteppingSubscriber.h"
|
||||
|
||||
typedef void *(*SubscriberInit)(DebuggerEventHandlerMap &map);
|
||||
typedef void (*Subscribershutdown)(void *p);
|
||||
struct SubscriberInfo {
|
||||
SubscriberInit init;
|
||||
Subscribershutdown shutdown;
|
||||
};
|
||||
|
||||
static const std::vector<SubscriberInfo> subscribers({
|
||||
{ &WebSocketBreakpointInit, nullptr },
|
||||
{ &WebSocketCPUCoreInit, nullptr },
|
||||
{ &WebSocketDisasmInit, &WebSocketDisasmShutdown },
|
||||
{ &WebSocketGameInit, nullptr },
|
||||
{ &WebSocketGPUBufferInit, nullptr },
|
||||
{ &WebSocketHLEInit, nullptr },
|
||||
{ &WebSocketSteppingInit, &WebSocketSteppingShutdown },
|
||||
typedef DebuggerSubscriber *(*SubscriberInit)(DebuggerEventHandlerMap &map);
|
||||
static const std::vector<SubscriberInit> subscribers({
|
||||
&WebSocketBreakpointInit,
|
||||
&WebSocketCPUCoreInit,
|
||||
&WebSocketDisasmInit,
|
||||
&WebSocketGameInit,
|
||||
&WebSocketGPUBufferInit,
|
||||
&WebSocketGPURecordInit,
|
||||
&WebSocketHLEInit,
|
||||
&WebSocketSteppingInit,
|
||||
});
|
||||
|
||||
// To handle webserver restart, keep track of how many running.
|
||||
@ -132,10 +128,10 @@ void HandleDebuggerRequest(const http::Request &request) {
|
||||
SteppingBroadcaster stepping;
|
||||
|
||||
std::unordered_map<std::string, DebuggerEventHandler> eventHandlers;
|
||||
std::vector<void *> subscriberData;
|
||||
for (auto info : subscribers) {
|
||||
std::vector<DebuggerSubscriber *> subscriberData;
|
||||
for (auto init : subscribers) {
|
||||
std::lock_guard<std::mutex> guard(lifecycleLock);
|
||||
subscriberData.push_back(info.init(eventHandlers));
|
||||
subscriberData.push_back(init(eventHandlers));
|
||||
}
|
||||
|
||||
// There's a tradeoff between responsiveness to incoming events, and polling for changes.
|
||||
@ -178,6 +174,12 @@ void HandleDebuggerRequest(const http::Request &request) {
|
||||
game.Broadcast(ws);
|
||||
stepping.Broadcast(ws);
|
||||
|
||||
for (size_t i = 0; i < subscribers.size(); ++i) {
|
||||
if (subscriberData[i]) {
|
||||
subscriberData[i]->Broadcast(ws);
|
||||
}
|
||||
}
|
||||
|
||||
if (stopRequested) {
|
||||
ws->Close(net::WebSocketClose::GOING_AWAY);
|
||||
}
|
||||
@ -188,11 +190,7 @@ void HandleDebuggerRequest(const http::Request &request) {
|
||||
|
||||
std::lock_guard<std::mutex> guard(lifecycleLock);
|
||||
for (size_t i = 0; i < subscribers.size(); ++i) {
|
||||
if (subscribers[i].shutdown) {
|
||||
subscribers[i].shutdown(subscriberData[i]);
|
||||
} else {
|
||||
assert(!subscriberData[i]);
|
||||
}
|
||||
delete subscriberData[i];
|
||||
}
|
||||
|
||||
delete ws;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
#include "Core/MIPS/MIPSDebugInterface.h"
|
||||
|
||||
void *WebSocketBreakpointInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketBreakpointInit(DebuggerEventHandlerMap &map) {
|
||||
// No need to bind or alloc state, these are all global.
|
||||
map["cpu.breakpoint.add"] = &WebSocketCPUBreakpointAdd;
|
||||
map["cpu.breakpoint.update"] = &WebSocketCPUBreakpointUpdate;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketBreakpointInit(DebuggerEventHandlerMap &map);
|
||||
DebuggerSubscriber *WebSocketBreakpointInit(DebuggerEventHandlerMap &map);
|
||||
|
||||
void WebSocketCPUBreakpointAdd(DebuggerRequest &req);
|
||||
void WebSocketCPUBreakpointUpdate(DebuggerRequest &req);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/MIPSDebugInterface.h"
|
||||
|
||||
void *WebSocketCPUCoreInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketCPUCoreInit(DebuggerEventHandlerMap &map) {
|
||||
// No need to bind or alloc state, these are all global.
|
||||
map["cpu.stepping"] = &WebSocketCPUStepping;
|
||||
map["cpu.resume"] = &WebSocketCPUResume;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketCPUCoreInit(DebuggerEventHandlerMap &map);
|
||||
DebuggerSubscriber *WebSocketCPUCoreInit(DebuggerEventHandlerMap &map);
|
||||
|
||||
void WebSocketCPUStepping(DebuggerRequest &req);
|
||||
void WebSocketCPUResume(DebuggerRequest &req);
|
||||
|
@ -28,11 +28,12 @@
|
||||
#include "Core/MIPS/MIPSAsm.h"
|
||||
#include "Core/MIPS/MIPSDebugInterface.h"
|
||||
|
||||
struct WebSocketDisasmState {
|
||||
class WebSocketDisasmState : public DebuggerSubscriber {
|
||||
public:
|
||||
WebSocketDisasmState() {
|
||||
disasm_.setCpu(currentDebugMIPS);
|
||||
}
|
||||
~WebSocketDisasmState() {
|
||||
~WebSocketDisasmState() override {
|
||||
disasm_.clear();
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ protected:
|
||||
DisassemblyManager disasm_;
|
||||
};
|
||||
|
||||
void *WebSocketDisasmInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketDisasmInit(DebuggerEventHandlerMap &map) {
|
||||
auto p = new WebSocketDisasmState();
|
||||
map["memory.base"] = std::bind(&WebSocketDisasmState::Base, p, std::placeholders::_1);
|
||||
map["memory.disasm"] = std::bind(&WebSocketDisasmState::Disasm, p, std::placeholders::_1);
|
||||
@ -59,10 +60,6 @@ void *WebSocketDisasmInit(DebuggerEventHandlerMap &map) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void WebSocketDisasmShutdown(void *p) {
|
||||
delete static_cast<WebSocketDisasmState *>(p);
|
||||
}
|
||||
|
||||
static DebugInterface *CPUFromRequest(DebuggerRequest &req) {
|
||||
if (!req.HasParam("thread"))
|
||||
return currentDebugMIPS;
|
||||
|
@ -19,5 +19,4 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketDisasmInit(DebuggerEventHandlerMap &map);
|
||||
void WebSocketDisasmShutdown(void *p);
|
||||
DebuggerSubscriber *WebSocketDisasmInit(DebuggerEventHandlerMap &map);
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "Core/Screenshot.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
|
||||
void *WebSocketGPUBufferInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketGPUBufferInit(DebuggerEventHandlerMap &map) {
|
||||
// No need to bind or alloc state, these are all global.
|
||||
map["gpu.buffer.screenshot"] = &WebSocketGPUBufferScreenshot;
|
||||
map["gpu.buffer.renderColor"] = &WebSocketGPUBufferRenderColor;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketGPUBufferInit(DebuggerEventHandlerMap &map);
|
||||
DebuggerSubscriber *WebSocketGPUBufferInit(DebuggerEventHandlerMap &map);
|
||||
|
||||
void WebSocketGPUBufferScreenshot(DebuggerRequest &req);
|
||||
void WebSocketGPUBufferRenderColor(DebuggerRequest &req);
|
||||
|
107
Core/Debugger/WebSocket/GPURecordSubscriber.cpp
Normal file
107
Core/Debugger/WebSocket/GPURecordSubscriber.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2018- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "data/base64.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Core/Debugger/WebSocket/GPURecordSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
#include "Core/System.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
|
||||
struct WebSocketGPURecordState : public DebuggerSubscriber {
|
||||
~WebSocketGPURecordState() override;
|
||||
void Dump(DebuggerRequest &req);
|
||||
|
||||
void Broadcast(net::WebSocketServer *ws) override;
|
||||
|
||||
protected:
|
||||
bool pending_ = false;
|
||||
std::string lastTicket_;
|
||||
std::string lastFilename_;
|
||||
};
|
||||
|
||||
DebuggerSubscriber *WebSocketGPURecordInit(DebuggerEventHandlerMap &map) {
|
||||
auto p = new WebSocketGPURecordState();
|
||||
map["gpu.record.dump"] = std::bind(&WebSocketGPURecordState::Dump, p, std::placeholders::_1);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
WebSocketGPURecordState::~WebSocketGPURecordState() {
|
||||
// Clear the callback to hopefully avoid a crash.
|
||||
if (pending_)
|
||||
GPURecord::SetCallback(nullptr);
|
||||
}
|
||||
|
||||
// Begin recording (gpu.record.dump)
|
||||
//
|
||||
// No parameters.
|
||||
//
|
||||
// Response (same event name):
|
||||
// - uri: data: URI containing debug dump data.
|
||||
//
|
||||
// Note: recording may take a moment.
|
||||
void WebSocketGPURecordState::Dump(DebuggerRequest &req) {
|
||||
if (!PSP_IsInited())
|
||||
return req.Fail("CPU not started");
|
||||
|
||||
if (!GPURecord::Activate())
|
||||
return req.Fail("Recording already in progress");
|
||||
|
||||
pending_ = true;
|
||||
GPURecord::SetCallback([=](const std::string &filename) {
|
||||
lastFilename_ = filename;
|
||||
pending_ = false;
|
||||
});
|
||||
|
||||
const JsonNode *value = req.data.get("ticket");
|
||||
lastTicket_ = value ? json_stringify(value) : "";
|
||||
}
|
||||
|
||||
// This handles the asynchronous gpu.record.dump response.
|
||||
void WebSocketGPURecordState::Broadcast(net::WebSocketServer *ws) {
|
||||
if (!lastFilename_.empty()) {
|
||||
FILE *fp = File::OpenCFile(lastFilename_, "rb");
|
||||
if (!fp) {
|
||||
lastFilename_.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// We write directly to the stream since this is a large chunk of data.
|
||||
ws->AddFragment(false, R"({"event":"gpu.record.dump")");
|
||||
if (!lastTicket_.empty()) {
|
||||
ws->AddFragment(false, R"(,"ticket":)");
|
||||
ws->AddFragment(false, lastTicket_);
|
||||
}
|
||||
ws->AddFragment(false, R"(,"uri":"data:application/octet-stream;base64,)");
|
||||
|
||||
// Divisible by 3 for base64 reasons.
|
||||
const size_t BUF_SIZE = 16383;
|
||||
std::vector<uint8_t> buf;
|
||||
buf.resize(BUF_SIZE);
|
||||
while (!feof(fp)) {
|
||||
size_t bytes = fread(&buf[0], 1, BUF_SIZE, fp);
|
||||
ws->AddFragment(false, Base64Encode(&buf[0], bytes));
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
ws->AddFragment(true, R"("})");
|
||||
|
||||
lastFilename_.clear();
|
||||
lastTicket_.clear();
|
||||
}
|
||||
}
|
22
Core/Debugger/WebSocket/GPURecordSubscriber.h
Normal file
22
Core/Debugger/WebSocket/GPURecordSubscriber.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2018- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
DebuggerSubscriber *WebSocketGPURecordInit(DebuggerEventHandlerMap &map);
|
@ -20,7 +20,7 @@
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
void *WebSocketGameInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketGameInit(DebuggerEventHandlerMap &map) {
|
||||
map["game.status"] = &WebSocketGameStatus;
|
||||
map["version"] = &WebSocketVersion;
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketGameInit(DebuggerEventHandlerMap &map);
|
||||
DebuggerSubscriber *WebSocketGameInit(DebuggerEventHandlerMap &map);
|
||||
|
||||
void WebSocketGameStatus(DebuggerRequest &req);
|
||||
void WebSocketVersion(DebuggerRequest &req);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "Core/MIPS/MIPSStackWalk.h"
|
||||
#include "Core/HLE/sceKernelThread.h"
|
||||
|
||||
void *WebSocketHLEInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketHLEInit(DebuggerEventHandlerMap &map) {
|
||||
map["hle.thread.list"] = &WebSocketHLEThreadList;
|
||||
map["hle.thread.wake"] = &WebSocketHLEThreadWake;
|
||||
map["hle.thread.stop"] = &WebSocketHLEThreadStop;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketHLEInit(DebuggerEventHandlerMap &map);
|
||||
DebuggerSubscriber *WebSocketHLEInit(DebuggerEventHandlerMap &map);
|
||||
|
||||
void WebSocketHLEThreadList(DebuggerRequest &req);
|
||||
void WebSocketHLEThreadWake(DebuggerRequest &req);
|
||||
|
@ -28,11 +28,11 @@
|
||||
|
||||
using namespace MIPSAnalyst;
|
||||
|
||||
struct WebSocketSteppingState {
|
||||
struct WebSocketSteppingState : public DebuggerSubscriber {
|
||||
WebSocketSteppingState() {
|
||||
disasm_.setCpu(currentDebugMIPS);
|
||||
}
|
||||
~WebSocketSteppingState() {
|
||||
~WebSocketSteppingState() override {
|
||||
disasm_.clear();
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ protected:
|
||||
DisassemblyManager disasm_;
|
||||
};
|
||||
|
||||
void *WebSocketSteppingInit(DebuggerEventHandlerMap &map) {
|
||||
DebuggerSubscriber *WebSocketSteppingInit(DebuggerEventHandlerMap &map) {
|
||||
auto p = new WebSocketSteppingState();
|
||||
map["cpu.stepInto"] = std::bind(&WebSocketSteppingState::Into, p, std::placeholders::_1);
|
||||
map["cpu.stepOver"] = std::bind(&WebSocketSteppingState::Over, p, std::placeholders::_1);
|
||||
@ -62,10 +62,6 @@ void *WebSocketSteppingInit(DebuggerEventHandlerMap &map) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void WebSocketSteppingShutdown(void *p) {
|
||||
delete static_cast<WebSocketSteppingState *>(p);
|
||||
}
|
||||
|
||||
static DebugInterface *CPUFromRequest(DebuggerRequest &req, uint32_t *threadID = nullptr) {
|
||||
if (!req.HasParam("thread")) {
|
||||
if (threadID)
|
||||
|
@ -19,5 +19,4 @@
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
void *WebSocketSteppingInit(DebuggerEventHandlerMap &map);
|
||||
void WebSocketSteppingShutdown(void *p);
|
||||
DebuggerSubscriber *WebSocketSteppingInit(DebuggerEventHandlerMap &map);
|
||||
|
@ -98,5 +98,13 @@ private:
|
||||
bool responsePartial_ = false;
|
||||
};
|
||||
|
||||
class DebuggerSubscriber {
|
||||
public:
|
||||
virtual ~DebuggerSubscriber() {}
|
||||
|
||||
// Subscribers can also broadcast if they have simple cases to.
|
||||
virtual void Broadcast(net::WebSocketServer *ws) {}
|
||||
};
|
||||
|
||||
typedef std::function<void(DebuggerRequest &req)> DebuggerEventHandler;
|
||||
typedef std::unordered_map<std::string, DebuggerEventHandler> DebuggerEventHandlerMap;
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "GPU/GPUInterface.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Common/PostShader.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
|
||||
struct FrameBufferState {
|
||||
u32 topaddr;
|
||||
@ -737,7 +738,7 @@ void __DisplayFlip(int cyclesLate) {
|
||||
// 4 here means 1 drawn, 4 skipped - so 12 fps minimum.
|
||||
maxFrameskip = g_Config.iFrameSkip;
|
||||
}
|
||||
if (numSkippedFrames >= maxFrameskip) {
|
||||
if (numSkippedFrames >= maxFrameskip || GPURecord::IsActivePending()) {
|
||||
skipFrame = false;
|
||||
}
|
||||
|
||||
|
@ -50,13 +50,6 @@ public:
|
||||
virtual void SaveSymbolMap() {}
|
||||
virtual void SetWindowTitle(const char *message) {}
|
||||
|
||||
// While debugging is active, it's perfectly fine for these to block.
|
||||
virtual bool GPUDebuggingActive() { return false; }
|
||||
virtual void GPUNotifyCommand(u32 pc) {}
|
||||
virtual void GPUNotifyDisplay(u32 framebuf, u32 stride, int format) {}
|
||||
virtual void GPUNotifyDraw() {}
|
||||
virtual void GPUNotifyTextureAttachment(u32 addr) {}
|
||||
|
||||
virtual bool CanCreateShortcut() {return false;}
|
||||
virtual bool CreateDesktopShortcut(std::string argumentPath, std::string title) {return false;}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "Common/ColorConv.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
@ -28,6 +27,7 @@
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
|
||||
@ -708,7 +708,7 @@ void TextureCacheCommon::AttachFramebufferValid(TexCacheEntry *entry, VirtualFra
|
||||
entry->maxLevel = 0;
|
||||
fbTexInfo_[cachekey] = fbInfo;
|
||||
framebuffer->last_frame_attached = gpuStats.numFlips;
|
||||
host->GPUNotifyTextureAttachment(entry->addr);
|
||||
GPUDebug::NotifyTextureAttachment(entry->addr);
|
||||
} else if (entry->framebuffer == framebuffer) {
|
||||
framebuffer->last_frame_attached = gpuStats.numFlips;
|
||||
}
|
||||
@ -727,7 +727,7 @@ void TextureCacheCommon::AttachFramebufferInvalid(TexCacheEntry *entry, VirtualF
|
||||
entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE;
|
||||
entry->maxLevel = 0;
|
||||
fbTexInfo_[cachekey] = fbInfo;
|
||||
host->GPUNotifyTextureAttachment(entry->addr);
|
||||
GPUDebug::NotifyTextureAttachment(entry->addr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,7 +740,7 @@ void TextureCacheCommon::DetachFramebuffer(TexCacheEntry *entry, u32 address, Vi
|
||||
// Otherwise we never recreate the texture.
|
||||
entry->hash ^= 1;
|
||||
fbTexInfo_.erase(cachekey);
|
||||
host->GPUNotifyTextureAttachment(entry->addr);
|
||||
GPUDebug::NotifyTextureAttachment(entry->addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Config.h"
|
||||
@ -34,10 +33,10 @@
|
||||
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
|
||||
#include "GPU/Common/TransformCommon.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/D3D11/FramebufferManagerD3D11.h"
|
||||
#include "GPU/D3D11/TextureCacheD3D11.h"
|
||||
#include "GPU/D3D11/DrawEngineD3D11.h"
|
||||
@ -690,10 +689,7 @@ rotateVBO:
|
||||
gstate_c.vertBounds.maxU = 0;
|
||||
gstate_c.vertBounds.maxV = 0;
|
||||
|
||||
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
||||
// We only support GPU debugging on Windows, and that's the only use case for this.
|
||||
host->GPUNotifyDraw();
|
||||
#endif
|
||||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::TessellationDataTransferD3D11::PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
@ -55,6 +54,7 @@
|
||||
#include "GPU/GeDisasm.h"
|
||||
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/D3D11/ShaderManagerD3D11.h"
|
||||
#include "GPU/D3D11/GPU_D3D11.h"
|
||||
#include "GPU/D3D11/FramebufferManagerD3D11.h"
|
||||
@ -254,7 +254,7 @@ void GPU_D3D11::BeginFrame() {
|
||||
void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
// TODO: Some games like Spongebob - Yellow Avenger, never change framebuffer, they blit to it.
|
||||
// So breaking on frames doesn't work. Might want to move this to sceDisplay vsync.
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
framebufferManagerD3D11_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
|
100
GPU/Debugger/Debugger.cpp
Normal file
100
GPU/Debugger/Debugger.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2018- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
|
||||
namespace GPUDebug {
|
||||
|
||||
static bool active = false;
|
||||
static bool inited = false;
|
||||
static BreakNext breakNext = BreakNext::NONE;
|
||||
|
||||
static void Init() {
|
||||
if (!inited) {
|
||||
GPUBreakpoints::Init();
|
||||
Core_ListenStopRequest(&GPUStepping::ForceUnpause);
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetActive(bool flag) {
|
||||
Init();
|
||||
|
||||
active = flag;
|
||||
if (!active) {
|
||||
breakNext = BreakNext::NONE;
|
||||
GPUStepping::ResumeFromStepping();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
void SetBreakNext(BreakNext next) {
|
||||
SetActive(true);
|
||||
breakNext = next;
|
||||
if (next == BreakNext::TEX) {
|
||||
GPUBreakpoints::AddTextureChangeTempBreakpoint();
|
||||
} else if (next == BreakNext::PRIM) {
|
||||
GPUBreakpoints::AddCmdBreakpoint(GE_CMD_PRIM, true);
|
||||
GPUBreakpoints::AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
GPUBreakpoints::AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
}
|
||||
GPUStepping::ResumeFromStepping();
|
||||
}
|
||||
|
||||
void NotifyCommand(u32 pc) {
|
||||
if (!active)
|
||||
return;
|
||||
u32 op = Memory::ReadUnchecked_U32(pc);
|
||||
if (breakNext == BreakNext::OP || GPUBreakpoints::IsBreakpoint(pc, op)) {
|
||||
GPUBreakpoints::ClearTempBreakpoints();
|
||||
|
||||
auto info = gpuDebug->DissassembleOp(pc);
|
||||
NOTICE_LOG(G3D, "Waiting at %08x, %s", pc, info.desc.c_str());
|
||||
GPUStepping::EnterStepping();
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyDraw() {
|
||||
if (!active)
|
||||
return;
|
||||
if (breakNext == BreakNext::DRAW) {
|
||||
NOTICE_LOG(G3D, "Waiting at a draw");
|
||||
GPUStepping::EnterStepping();
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyDisplay(u32 framebuf, u32 stride, int format) {
|
||||
if (!active)
|
||||
return;
|
||||
if (breakNext == BreakNext::FRAME) {
|
||||
// This should work fine, start stepping at the first op of the new frame.
|
||||
breakNext = BreakNext::OP;
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyTextureAttachment(u32 texaddr) {
|
||||
if (!active)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
45
GPU/Debugger/Debugger.h
Normal file
45
GPU/Debugger/Debugger.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2018- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace GPUDebug {
|
||||
|
||||
enum class BreakNext {
|
||||
NONE,
|
||||
OP,
|
||||
DRAW,
|
||||
TEX,
|
||||
NONTEX,
|
||||
FRAME,
|
||||
PRIM,
|
||||
};
|
||||
|
||||
void SetActive(bool flag);
|
||||
bool IsActive();
|
||||
|
||||
void SetBreakNext(BreakNext next);
|
||||
|
||||
// While debugging is active, these may block.
|
||||
void NotifyCommand(u32 pc);
|
||||
void NotifyDraw();
|
||||
void NotifyDisplay(u32 framebuf, u32 stride, int format);
|
||||
void NotifyTextureAttachment(u32 texaddr);
|
||||
|
||||
}
|
@ -48,6 +48,7 @@ static const int VERSION = 2;
|
||||
static bool active = false;
|
||||
static bool nextFrame = false;
|
||||
static bool writePending = false;
|
||||
static std::function<void(const std::string &)> writeCallback;
|
||||
|
||||
enum class CommandType : u8 {
|
||||
INIT = 0,
|
||||
@ -409,7 +410,7 @@ static void WriteCompressed(FILE *fp, const void *p, size_t sz) {
|
||||
delete [] compressed;
|
||||
}
|
||||
|
||||
static void WriteRecording() {
|
||||
static std::string WriteRecording() {
|
||||
FlushRegisters();
|
||||
EmitDisplayBuf();
|
||||
|
||||
@ -430,6 +431,8 @@ static void WriteRecording() {
|
||||
WriteCompressed(fp, pushbuf.data(), bufsz);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
static void GetVertDataSizes(int vcount, const void *indices, u32 &vbytes, u32 &ibytes) {
|
||||
@ -637,8 +640,35 @@ bool IsActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
void Activate() {
|
||||
nextFrame = true;
|
||||
bool IsActivePending() {
|
||||
return nextFrame || active;
|
||||
}
|
||||
|
||||
bool Activate() {
|
||||
if (!nextFrame) {
|
||||
nextFrame = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetCallback(const std::function<void(const std::string &)> callback) {
|
||||
writeCallback = callback;
|
||||
}
|
||||
|
||||
static void FinishRecording() {
|
||||
// We're done - this was just to write the result out.
|
||||
std::string filename = WriteRecording();
|
||||
commands.clear();
|
||||
pushbuf.clear();
|
||||
|
||||
NOTICE_LOG(SYSTEM, "Recording finished");
|
||||
writePending = false;
|
||||
active = false;
|
||||
|
||||
if (writeCallback)
|
||||
writeCallback(filename);
|
||||
writeCallback = nullptr;
|
||||
}
|
||||
|
||||
void NotifyCommand(u32 pc) {
|
||||
@ -646,14 +676,7 @@ void NotifyCommand(u32 pc) {
|
||||
return;
|
||||
}
|
||||
if (writePending) {
|
||||
WriteRecording();
|
||||
commands.clear();
|
||||
pushbuf.clear();
|
||||
|
||||
writePending = false;
|
||||
// We're done - this was just to write the result out.
|
||||
NOTICE_LOG(SYSTEM, "Recording finished");
|
||||
active = false;
|
||||
FinishRecording();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -749,12 +772,12 @@ void NotifyUpload(u32 dest, u32 sz) {
|
||||
}
|
||||
|
||||
void NotifyFrame() {
|
||||
if (active && !writePending) {
|
||||
if (active && !writePending && !commands.empty()) {
|
||||
// Delay write until the first command of the next frame, so we get the right display buf.
|
||||
NOTICE_LOG(SYSTEM, "Recording complete - waiting to get display buffer");
|
||||
writePending = true;
|
||||
}
|
||||
if (nextFrame) {
|
||||
if (nextFrame && (gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) {
|
||||
NOTICE_LOG(SYSTEM, "Recording starting...");
|
||||
active = true;
|
||||
nextFrame = false;
|
||||
|
@ -17,13 +17,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace GPURecord {
|
||||
|
||||
bool IsActive();
|
||||
void Activate();
|
||||
bool IsActivePending();
|
||||
bool Activate();
|
||||
// Call only if Activate() returns true.
|
||||
void SetCallback(const std::function<void(const std::string &)> callback);
|
||||
|
||||
void NotifyCommand(u32 pc);
|
||||
void NotifyMemcpy(u32 dest, u32 src, u32 sz);
|
||||
|
@ -38,6 +38,7 @@ enum PauseAction {
|
||||
};
|
||||
|
||||
static bool isStepping;
|
||||
static int stepCounter = 0;
|
||||
|
||||
static std::mutex pauseLock;
|
||||
static std::condition_variable pauseWait;
|
||||
@ -149,7 +150,7 @@ bool SingleStep() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EnterStepping(std::function<void()> callback) {
|
||||
bool EnterStepping() {
|
||||
std::unique_lock<std::mutex> guard(pauseLock);
|
||||
if (coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME) {
|
||||
// Shutting down, don't try to step.
|
||||
@ -170,8 +171,7 @@ bool EnterStepping(std::function<void()> callback) {
|
||||
pauseAction = PAUSE_BREAK;
|
||||
}
|
||||
isStepping = true;
|
||||
|
||||
callback();
|
||||
stepCounter++;
|
||||
|
||||
do {
|
||||
RunPauseAction();
|
||||
@ -187,6 +187,10 @@ bool IsStepping() {
|
||||
return isStepping;
|
||||
}
|
||||
|
||||
int GetSteppingCounter() {
|
||||
return stepCounter;
|
||||
}
|
||||
|
||||
static bool GetBuffer(const GPUDebugBuffer *&buffer, PauseAction type, const GPUDebugBuffer &resultBuffer) {
|
||||
if (!isStepping && coreState != CORE_STEPPING) {
|
||||
return false;
|
||||
|
@ -24,12 +24,12 @@
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
|
||||
namespace GPUStepping {
|
||||
// Should be called from the GPU thread.
|
||||
// Begins stepping and calls callback while inside a lock preparing stepping.
|
||||
// This would be a good place to deliver a message to code that stepping is ready.
|
||||
bool EnterStepping(std::function<void()> callback);
|
||||
// Should be called from the emu thread.
|
||||
// Begins stepping and increments the stepping counter while inside a lock.
|
||||
bool EnterStepping();
|
||||
bool SingleStep();
|
||||
bool IsStepping();
|
||||
int GetSteppingCounter();
|
||||
|
||||
bool GPU_GetOutputFramebuffer(const GPUDebugBuffer *&buffer);
|
||||
bool GPU_GetCurrentFramebuffer(const GPUDebugBuffer *&buffer, GPUDebugFramebufferType type);
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Config.h"
|
||||
@ -36,6 +35,7 @@
|
||||
#include "GPU/Common/TransformCommon.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Directx9/TextureCacheDX9.h"
|
||||
#include "GPU/Directx9/DrawEngineDX9.h"
|
||||
#include "GPU/Directx9/ShaderManagerDX9.h"
|
||||
@ -621,7 +621,7 @@ rotateVBO:
|
||||
gstate_c.vertBounds.maxU = 0;
|
||||
gstate_c.vertBounds.maxV = 0;
|
||||
|
||||
host->GPUNotifyDraw();
|
||||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
void DrawEngineDX9::TessellationDataTransferDX9::SendDataToShader(const float * pos, const float * tex, const float * col, int size, bool hasColor, bool hasTexCoords)
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "GPU/GeDisasm.h"
|
||||
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Directx9/ShaderManagerDX9.h"
|
||||
#include "GPU/Directx9/GPU_DX9.h"
|
||||
#include "GPU/Directx9/FramebufferDX9.h"
|
||||
@ -230,7 +231,7 @@ void GPU_DX9::BeginFrame() {
|
||||
}
|
||||
|
||||
void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
framebufferManagerDX9_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Config.h"
|
||||
@ -37,6 +36,7 @@
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/GLES/FragmentTestCacheGLES.h"
|
||||
#include "GPU/GLES/StateMappingGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
@ -648,9 +648,7 @@ rotateVBO:
|
||||
gstate_c.vertBounds.maxU = 0;
|
||||
gstate_c.vertBounds.maxV = 0;
|
||||
|
||||
#ifndef MOBILE_DEVICE
|
||||
host->GPUNotifyDraw();
|
||||
#endif
|
||||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GeDisasm.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/GPU_GLES.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
@ -443,7 +443,7 @@ void GPU_GLES::BeginFrame() {
|
||||
}
|
||||
|
||||
void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
framebufferManagerGL_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
|
@ -217,6 +217,7 @@
|
||||
<ClInclude Include="D3D11\TextureScalerD3D11.h" />
|
||||
<ClInclude Include="D3D11\VertexShaderGeneratorD3D11.h" />
|
||||
<ClInclude Include="Debugger\Breakpoints.h" />
|
||||
<ClInclude Include="Debugger\Debugger.h" />
|
||||
<ClInclude Include="Debugger\Record.h" />
|
||||
<ClInclude Include="Debugger\Stepping.h" />
|
||||
<ClInclude Include="Directx9\DepalettizeShaderDX9.h" />
|
||||
@ -320,6 +321,7 @@
|
||||
<ClCompile Include="D3D11\TextureScalerD3D11.cpp" />
|
||||
<ClCompile Include="D3D11\VertexShaderGeneratorD3D11.cpp" />
|
||||
<ClCompile Include="Debugger\Breakpoints.cpp" />
|
||||
<ClCompile Include="Debugger\Debugger.cpp" />
|
||||
<ClCompile Include="Debugger\Record.cpp" />
|
||||
<ClCompile Include="Debugger\Stepping.cpp" />
|
||||
<ClCompile Include="Directx9\DepalettizeShaderDX9.cpp" />
|
||||
|
@ -273,6 +273,9 @@
|
||||
<ClInclude Include="Vulkan\DebugVisVulkan.h">
|
||||
<Filter>Vulkan</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\Debugger.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Math3D.cpp">
|
||||
@ -542,5 +545,8 @@
|
||||
<ClCompile Include="Vulkan\DebugVisVulkan.cpp">
|
||||
<Filter>Vulkan</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\Debugger.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -28,6 +28,7 @@
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
|
||||
const CommonCommandTableEntry commonCommandTable[] = {
|
||||
@ -933,7 +934,7 @@ bool GPUCommon::InterpretList(DisplayList &list) {
|
||||
gpuState = list.pc == list.stall ? GPUSTATE_STALL : GPUSTATE_RUNNING;
|
||||
|
||||
debugRecording_ = GPURecord::IsActive();
|
||||
const bool useDebugger = host->GPUDebuggingActive() || debugRecording_;
|
||||
const bool useDebugger = GPUDebug::IsActive() || debugRecording_;
|
||||
const bool useFastRunLoop = !dumpThisFrame_ && !useDebugger;
|
||||
while (gpuState == GPUSTATE_RUNNING) {
|
||||
{
|
||||
@ -1035,7 +1036,7 @@ void GPUCommon::SlowRunLoop(DisplayList &list)
|
||||
const bool dumpThisFrame = dumpThisFrame_;
|
||||
while (downcount > 0)
|
||||
{
|
||||
host->GPUNotifyCommand(list.pc);
|
||||
GPUDebug::NotifyCommand(list.pc);
|
||||
GPURecord::NotifyCommand(list.pc);
|
||||
u32 op = Memory::ReadUnchecked_U32(list.pc);
|
||||
u32 cmd = op >> 24;
|
||||
@ -1586,10 +1587,8 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) {
|
||||
if (!g_Config.bSoftwareSkinning)
|
||||
vtypeCheckMask = 0xFFFFFFFF;
|
||||
|
||||
#ifndef MOBILE_DEVICE
|
||||
if (debugRecording_ || host->GPUDebuggingActive())
|
||||
if (debugRecording_ || GPUDebug::IsActive())
|
||||
goto bail;
|
||||
#endif
|
||||
|
||||
while (src != stall) {
|
||||
uint32_t data = *src;
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/HLE/sceKernelInterrupt.h"
|
||||
#include "Core/HLE/sceGe.h"
|
||||
@ -39,6 +38,7 @@
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
|
||||
const int FB_WIDTH = 480;
|
||||
@ -141,7 +141,7 @@ void SoftGPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for
|
||||
displayFramebuf_ = (framebuf & 0xFF000000) == 0 ? 0x44000000 | framebuf : framebuf;
|
||||
displayStride_ = stride;
|
||||
displayFormat_ = format;
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
}
|
||||
|
||||
// Copies RGBA8 data from RAM to the currently bound render target.
|
||||
|
@ -16,13 +16,12 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Config.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Software/TransformUnit.h"
|
||||
#include "GPU/Software/Clipper.h"
|
||||
#include "GPU/Software/Lighting.h"
|
||||
@ -490,7 +489,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveTy
|
||||
break;
|
||||
}
|
||||
|
||||
host->GPUNotifyDraw();
|
||||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
// TODO: This probably is not the best interface.
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Config.h"
|
||||
@ -44,6 +43,7 @@
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Vulkan/DrawEngineVulkan.h"
|
||||
#include "GPU/Vulkan/TextureCacheVulkan.h"
|
||||
#include "GPU/Vulkan/ShaderManagerVulkan.h"
|
||||
@ -976,7 +976,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
gstate_c.vertBounds.maxU = 0;
|
||||
gstate_c.vertBounds.maxV = 0;
|
||||
|
||||
host->GPUNotifyDraw();
|
||||
GPUDebug::NotifyDraw();
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::UpdateUBOs(FrameData *frame) {
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
@ -36,7 +35,7 @@
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GeDisasm.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Vulkan/ShaderManagerVulkan.h"
|
||||
#include "GPU/Vulkan/GPU_Vulkan.h"
|
||||
#include "GPU/Vulkan/FramebufferVulkan.h"
|
||||
@ -405,7 +404,7 @@ void GPU_Vulkan::UpdateVsyncInterval(bool force) {
|
||||
}
|
||||
|
||||
void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
host->GPUNotifyDisplay(framebuf, stride, format);
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
}
|
||||
|
||||
|
@ -1268,6 +1268,12 @@ void DeveloperToolsScreen::CreateViews() {
|
||||
cpuTests->SetEnabled(TestsAvailable());
|
||||
#endif
|
||||
|
||||
allowDebugger_ = !WebServerStopped(WebServerFlags::DEBUGGER);
|
||||
canAllowDebugger_ = !WebServerStopping(WebServerFlags::DEBUGGER);
|
||||
CheckBox *allowDebugger = new CheckBox(&allowDebugger_, dev->T("Allow remote debugger"));
|
||||
list->Add(allowDebugger)->OnClick.Handle(this, &DeveloperToolsScreen::OnRemoteDebugger);
|
||||
allowDebugger->SetEnabledPtr(&canAllowDebugger_);
|
||||
|
||||
list->Add(new CheckBox(&g_Config.bEnableLogging, dev->T("Enable Logging")))->OnClick.Handle(this, &DeveloperToolsScreen::OnLoggingChanged);
|
||||
list->Add(new CheckBox(&g_Config.bLogFrameDrops, dev->T("Log Dropped Frame Statistics")));
|
||||
list->Add(new Choice(dev->T("Logging Channels")))->OnClick.Handle(this, &DeveloperToolsScreen::OnLogConfig);
|
||||
@ -1284,12 +1290,6 @@ void DeveloperToolsScreen::CreateViews() {
|
||||
createTextureIni->SetEnabled(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
allowDebugger_ = !WebServerStopped(WebServerFlags::DEBUGGER);
|
||||
canAllowDebugger_ = !WebServerStopping(WebServerFlags::DEBUGGER);
|
||||
CheckBox *allowDebugger = new CheckBox(&allowDebugger_, dev->T("Allow remote debugger"));
|
||||
list->Add(allowDebugger)->OnClick.Handle(this, &DeveloperToolsScreen::OnRemoteDebugger);
|
||||
allowDebugger->SetEnabledPtr(&canAllowDebugger_);
|
||||
}
|
||||
|
||||
void DeveloperToolsScreen::onFinish(DialogResult result) {
|
||||
|
@ -332,6 +332,7 @@
|
||||
<ClInclude Include="..\..\GPU\D3D11\TextureScalerD3D11.h" />
|
||||
<ClInclude Include="..\..\GPU\D3D11\VertexShaderGeneratorD3D11.h" />
|
||||
<ClInclude Include="..\..\GPU\Debugger\Breakpoints.h" />
|
||||
<ClInclude Include="..\..\GPU\Debugger\Debugger.h" />
|
||||
<ClInclude Include="..\..\GPU\Debugger\Record.h" />
|
||||
<ClInclude Include="..\..\GPU\Debugger\Stepping.h" />
|
||||
<ClInclude Include="..\..\GPU\Directx9\PixelShaderGeneratorDX9.h" />
|
||||
@ -390,6 +391,7 @@
|
||||
<ClCompile Include="..\..\GPU\D3D11\TextureScalerD3D11.cpp" />
|
||||
<ClCompile Include="..\..\GPU\D3D11\VertexShaderGeneratorD3D11.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Debugger\Breakpoints.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Debugger\Debugger.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Debugger\Record.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Debugger\Stepping.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Directx9\PixelShaderGeneratorDX9.cpp" />
|
||||
|
@ -150,13 +150,18 @@
|
||||
<ClCompile Include="..\..\GPU\Debugger\Breakpoints.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\GPU\Debugger\Debugger.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\GPU\Debugger\Stepping.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\GPU\Common\ShaderCommon.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\GPU\Software\Sampler.cpp" />
|
||||
<ClCompile Include="..\..\GPU\Software\Sampler.cpp">
|
||||
<Filter>Software</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\GPU\Debugger\Record.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
@ -291,10 +296,15 @@
|
||||
<ClInclude Include="..\..\GPU\Debugger\Breakpoints.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\GPU\Debugger\Debugger.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\GPU\Debugger\Stepping.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\GPU\Software\Sampler.h" />
|
||||
<ClInclude Include="..\..\GPU\Software\Sampler.h">
|
||||
<Filter>Software</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\GPU\Debugger\Record.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "Windows/GEDebugger/TabVertices.h"
|
||||
#include "Windows/W32Util/ShellUtil.h"
|
||||
#include "Windows/InputBox.h"
|
||||
#include "Windows/WindowsHost.h"
|
||||
#include "Windows/MainWindow.h"
|
||||
#include "Windows/main.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
@ -39,6 +38,7 @@
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
#include <windowsx.h>
|
||||
@ -47,12 +47,9 @@
|
||||
const int POPUP_SUBMENU_ID_GEDBG_PREVIEW = 10;
|
||||
|
||||
using namespace GPUBreakpoints;
|
||||
using namespace GPUDebug;
|
||||
using namespace GPUStepping;
|
||||
|
||||
static bool attached = false;
|
||||
|
||||
static BreakNextType breakNext = BREAK_NONE;
|
||||
|
||||
enum PrimaryDisplayType {
|
||||
PRIMARY_FRAMEBUF,
|
||||
PRIMARY_DEPTHBUF,
|
||||
@ -66,9 +63,6 @@ void CGEDebugger::Init() {
|
||||
|
||||
CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
|
||||
: Dialog((LPCSTR)IDD_GEDEBUGGER, _hInstance, _hParent) {
|
||||
GPUBreakpoints::Init();
|
||||
Core_ListenStopRequest(ForceUnpause);
|
||||
|
||||
// minimum size = a little more than the default
|
||||
RECT windowRect;
|
||||
GetWindowRect(m_hDlg, &windowRect);
|
||||
@ -129,6 +123,8 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
|
||||
int h = g_Config.iGEWindowH == -1 ? minHeight_ : g_Config.iGEWindowH;
|
||||
MoveWindow(m_hDlg,x,y,w,h,FALSE);
|
||||
|
||||
SetTimer(m_hDlg, 1, USER_TIMER_MINIMUM, nullptr);
|
||||
|
||||
UpdateTextureLevel(textureLevel_);
|
||||
}
|
||||
|
||||
@ -318,6 +314,8 @@ void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) {
|
||||
bool bufferResult = false;
|
||||
u32 flags = SimpleGLWindow::ALPHA_IGNORE | SimpleGLWindow::RESIZE_SHRINK_CENTER;
|
||||
|
||||
SetupPreviews();
|
||||
|
||||
primaryBuffer_ = nullptr;
|
||||
if (showClut_) {
|
||||
bufferResult = GPU_GetCurrentTexture(primaryBuffer_, textureLevel_);
|
||||
@ -362,6 +360,8 @@ void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) {
|
||||
void CGEDebugger::UpdateSecondPreview(const GPUgstate &state) {
|
||||
bool bufferResult = false;
|
||||
|
||||
SetupPreviews();
|
||||
|
||||
secondBuffer_ = nullptr;
|
||||
if (showClut_) {
|
||||
bufferResult = GPU_GetCurrentClut(secondBuffer_);
|
||||
@ -404,6 +404,8 @@ void CGEDebugger::PrimaryPreviewHover(int x, int y) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetupPreviews();
|
||||
|
||||
wchar_t desc[256] = {0};
|
||||
|
||||
if (!primaryWindow->HasTex()) {
|
||||
@ -626,14 +628,6 @@ void CGEDebugger::SavePosition()
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::SetBreakNext(BreakNextType type) {
|
||||
attached = true;
|
||||
SetupPreviews();
|
||||
|
||||
breakNext = type;
|
||||
ResumeFromStepping();
|
||||
}
|
||||
|
||||
BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
switch (message) {
|
||||
case WM_INITDIALOG:
|
||||
@ -657,9 +651,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
return TRUE;
|
||||
|
||||
case WM_CLOSE:
|
||||
attached = false;
|
||||
ResumeFromStepping();
|
||||
breakNext = BREAK_NONE;
|
||||
GPUDebug::SetActive(false);
|
||||
|
||||
Show(false);
|
||||
return TRUE;
|
||||
@ -674,6 +666,16 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
if (GPUStepping::IsStepping()) {
|
||||
static int lastCounter = 0;
|
||||
if (lastCounter != GPUStepping::GetSteppingCounter()) {
|
||||
UpdatePreviews();
|
||||
lastCounter = GPUStepping::GetSteppingCounter();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
switch (wParam)
|
||||
{
|
||||
@ -685,7 +687,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
break;
|
||||
case IDC_GEDBG_FBTABS:
|
||||
fbTabs->HandleNotify(lParam);
|
||||
if (attached && gpuDebug != nullptr) {
|
||||
if (GPUDebug::IsActive() && gpuDebug != nullptr) {
|
||||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
@ -695,32 +697,28 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDC_GEDBG_STEPDRAW:
|
||||
SetBreakNext(BREAK_NEXT_DRAW);
|
||||
SetBreakNext(BreakNext::DRAW);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEP:
|
||||
SetBreakNext(BREAK_NEXT_OP);
|
||||
SetBreakNext(BreakNext::OP);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPTEX:
|
||||
AddTextureChangeTempBreakpoint();
|
||||
SetBreakNext(BREAK_NEXT_TEX);
|
||||
SetBreakNext(BreakNext::TEX);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPFRAME:
|
||||
SetBreakNext(BREAK_NEXT_FRAME);
|
||||
SetBreakNext(BreakNext::FRAME);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPPRIM:
|
||||
AddCmdBreakpoint(GE_CMD_PRIM, true);
|
||||
AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
SetBreakNext(BREAK_NEXT_PRIM);
|
||||
SetBreakNext(BreakNext::PRIM);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_BREAKTEX:
|
||||
{
|
||||
attached = true;
|
||||
GPUDebug::SetActive(true);
|
||||
if (!gpuDebug) {
|
||||
break;
|
||||
}
|
||||
@ -739,7 +737,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
case IDC_GEDBG_BREAKTARGET:
|
||||
{
|
||||
attached = true;
|
||||
GPUDebug::SetActive(true);
|
||||
if (!gpuDebug) {
|
||||
break;
|
||||
}
|
||||
@ -758,26 +756,26 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
case IDC_GEDBG_TEXLEVELDOWN:
|
||||
UpdateTextureLevel(textureLevel_ - 1);
|
||||
if (attached && gpuDebug != nullptr) {
|
||||
if (GPUDebug::IsActive() && gpuDebug != nullptr) {
|
||||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_TEXLEVELUP:
|
||||
UpdateTextureLevel(textureLevel_ + 1);
|
||||
if (attached && gpuDebug != nullptr) {
|
||||
if (GPUDebug::IsActive() && gpuDebug != nullptr) {
|
||||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_RESUME:
|
||||
SetupPreviews();
|
||||
primaryWindow->Clear();
|
||||
secondWindow->Clear();
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_FRAMEBUFADDR, L"");
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"");
|
||||
|
||||
ResumeFromStepping();
|
||||
breakNext = BREAK_NONE;
|
||||
SetBreakNext(BreakNext::NONE);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_RECORD:
|
||||
@ -785,14 +783,14 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_FORCEOPAQUE:
|
||||
if (attached && gpuDebug != nullptr) {
|
||||
if (GPUDebug::IsActive() && gpuDebug != nullptr) {
|
||||
forceOpaque_ = SendMessage(GetDlgItem(m_hDlg, IDC_GEDBG_FORCEOPAQUE), BM_GETCHECK, 0, 0) != 0;
|
||||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_SHOWCLUT:
|
||||
if (attached && gpuDebug != nullptr) {
|
||||
if (GPUDebug::IsActive() && gpuDebug != nullptr) {
|
||||
showClut_ = SendMessage(GetDlgItem(m_hDlg, IDC_GEDBG_SHOWCLUT), BM_GETCHECK, 0, 0) != 0;
|
||||
UpdatePreviews();
|
||||
}
|
||||
@ -800,30 +798,13 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GEDBG_BREAK_CMD:
|
||||
{
|
||||
u32 pc = (u32)wParam;
|
||||
ClearTempBreakpoints();
|
||||
auto info = gpuDebug->DissassembleOp(pc);
|
||||
NOTICE_LOG(G3D, "Waiting at %08x, %s", pc, info.desc.c_str());
|
||||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GEDBG_BREAK_DRAW:
|
||||
{
|
||||
NOTICE_LOG(G3D, "Waiting at a draw");
|
||||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GEDBG_STEPDISPLAYLIST:
|
||||
SetBreakNext(BREAK_NEXT_OP);
|
||||
SetBreakNext(BreakNext::OP);
|
||||
break;
|
||||
|
||||
case WM_GEDBG_TOGGLEPCBREAKPOINT:
|
||||
{
|
||||
attached = true;
|
||||
GPUDebug::SetActive(true);
|
||||
u32 pc = (u32)wParam;
|
||||
bool temp;
|
||||
bool isBreak = IsAddressBreakpoint(pc, temp);
|
||||
@ -837,7 +818,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
case WM_GEDBG_RUNTOWPARAM:
|
||||
{
|
||||
attached = true;
|
||||
GPUDebug::SetActive(true);
|
||||
u32 pc = (u32)wParam;
|
||||
AddAddressBreakpoint(pc, true);
|
||||
SendMessage(m_hDlg,WM_COMMAND,IDC_GEDBG_RESUME,0);
|
||||
@ -845,9 +826,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
break;
|
||||
|
||||
case WM_GEDBG_SETCMDWPARAM:
|
||||
{
|
||||
GPU_SetCmdValue((u32)wParam);
|
||||
}
|
||||
GPU_SetCmdValue((u32)wParam);
|
||||
break;
|
||||
|
||||
case WM_GEDBG_UPDATE_WATCH:
|
||||
@ -859,44 +838,3 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The below WindowsHost methods are called on the GPU thread.
|
||||
|
||||
bool WindowsHost::GPUDebuggingActive() {
|
||||
return attached;
|
||||
}
|
||||
|
||||
static void DeliverMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
PostMessage(geDebuggerWindow->GetDlgHandle(), msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static void PauseWithMessage(UINT msg, WPARAM wParam = NULL, LPARAM lParam = NULL) {
|
||||
if (attached) {
|
||||
EnterStepping(std::bind(&DeliverMessage, msg, wParam, lParam));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHost::GPUNotifyCommand(u32 pc) {
|
||||
u32 op = Memory::ReadUnchecked_U32(pc);
|
||||
u8 cmd = op >> 24;
|
||||
|
||||
if (breakNext == BREAK_NEXT_OP || IsBreakpoint(pc, op)) {
|
||||
PauseWithMessage(WM_GEDBG_BREAK_CMD, (WPARAM) pc);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHost::GPUNotifyDisplay(u32 framebuf, u32 stride, int format) {
|
||||
if (breakNext == BREAK_NEXT_FRAME) {
|
||||
// This should work fine, start stepping at the first op of the new frame.
|
||||
breakNext = BREAK_NEXT_OP;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHost::GPUNotifyDraw() {
|
||||
if (breakNext == BREAK_NEXT_DRAW) {
|
||||
PauseWithMessage(WM_GEDBG_BREAK_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsHost::GPUNotifyTextureAttachment(u32 addr) {
|
||||
}
|
||||
|
@ -19,31 +19,20 @@
|
||||
|
||||
#include "Common/CommonWindows.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "Windows/resource.h"
|
||||
#include "Windows/W32Util/DialogManager.h"
|
||||
#include "Windows/W32Util/TabControl.h"
|
||||
#include "Windows/GEDebugger/SimpleGLWindow.h"
|
||||
|
||||
enum {
|
||||
WM_GEDBG_BREAK_CMD = WM_USER + 200,
|
||||
WM_GEDBG_BREAK_DRAW,
|
||||
WM_GEDBG_STEPDISPLAYLIST,
|
||||
WM_GEDBG_STEPDISPLAYLIST = WM_USER + 200,
|
||||
WM_GEDBG_TOGGLEPCBREAKPOINT,
|
||||
WM_GEDBG_RUNTOWPARAM,
|
||||
WM_GEDBG_SETCMDWPARAM,
|
||||
WM_GEDBG_UPDATE_WATCH,
|
||||
};
|
||||
|
||||
enum BreakNextType {
|
||||
BREAK_NONE,
|
||||
BREAK_NEXT_OP,
|
||||
BREAK_NEXT_DRAW,
|
||||
BREAK_NEXT_TEX,
|
||||
BREAK_NEXT_NONTEX,
|
||||
BREAK_NEXT_FRAME,
|
||||
BREAK_NEXT_PRIM,
|
||||
};
|
||||
|
||||
class CtrlDisplayListView;
|
||||
class TabDisplayLists;
|
||||
class TabStateFlags;
|
||||
@ -76,7 +65,6 @@ private:
|
||||
void HandleRedraw(int which);
|
||||
void UpdateSize(WORD width, WORD height);
|
||||
void SavePosition();
|
||||
void SetBreakNext(BreakNextType type);
|
||||
void UpdateTextureLevel(int level);
|
||||
void DescribePrimaryPreview(const GPUgstate &state, wchar_t desc[256]);
|
||||
void DescribeSecondPreview(const GPUgstate &state, wchar_t desc[256]);
|
||||
|
@ -55,11 +55,6 @@ public:
|
||||
void SaveSymbolMap() override;
|
||||
void SetWindowTitle(const char *message) override;
|
||||
|
||||
bool GPUDebuggingActive() override;
|
||||
void GPUNotifyCommand(u32 pc) override;
|
||||
void GPUNotifyDisplay(u32 framebuf, u32 stride, int format) override;
|
||||
void GPUNotifyDraw() override;
|
||||
void GPUNotifyTextureAttachment(u32 addr) override;
|
||||
void ToggleDebugConsoleVisibility() override;
|
||||
|
||||
bool CanCreateShortcut() override;
|
||||
|
@ -242,6 +242,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/GPU/Common/PostShader.cpp \
|
||||
$(SRC)/GPU/Common/ShaderUniforms.cpp \
|
||||
$(SRC)/GPU/Debugger/Breakpoints.cpp \
|
||||
$(SRC)/GPU/Debugger/Debugger.cpp \
|
||||
$(SRC)/GPU/Debugger/Record.cpp \
|
||||
$(SRC)/GPU/Debugger/Stepping.cpp \
|
||||
$(SRC)/GPU/GLES/FramebufferManagerGLES.cpp \
|
||||
@ -309,6 +310,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/Core/Debugger/WebSocket/GameBroadcaster.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/GameSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/GPUBufferSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/GPURecordSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/HLESubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/LogBroadcaster.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/SteppingBroadcaster.cpp \
|
||||
|
@ -168,8 +168,9 @@ SOURCES_CXX += \
|
||||
$(GPUCOMMONDIR)/PostShader.cpp \
|
||||
$(COMMONDIR)/ColorConv.cpp \
|
||||
$(GPUDIR)/Debugger/Breakpoints.cpp \
|
||||
$(GPUDIR)/Debugger/Stepping.cpp \
|
||||
$(GPUDIR)/Debugger/Debugger.cpp \
|
||||
$(GPUDIR)/Debugger/Record.cpp \
|
||||
$(GPUDIR)/Debugger/Stepping.cpp \
|
||||
$(GPUDIR)/Common/TextureCacheCommon.cpp \
|
||||
$(GPUDIR)/Common/TextureScalerCommon.cpp \
|
||||
$(GPUDIR)/Common/SoftwareTransformCommon.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user