mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add break-on-count (with rudimentary UI), break on block transfer
This commit is contained in:
parent
3a97479116
commit
db13c09c41
10 changed files with 67 additions and 32 deletions
|
@ -248,9 +248,10 @@ public:
|
|||
virtual void ClearBreakNext() = 0;
|
||||
virtual void SetBreakNext(GPUDebug::BreakNext next) = 0 ;
|
||||
virtual void SetBreakCount(int c, bool relative = false) = 0 ;
|
||||
virtual GPUDebug::BreakNext GetBreakNext() = 0 ;
|
||||
virtual GPUDebug::BreakNext GetBreakNext() const = 0;
|
||||
virtual int GetBreakCount() const = 0;
|
||||
virtual bool SetRestrictPrims(std::string_view rule) = 0 ;
|
||||
virtual const char *GetRestrictPrims() = 0 ;
|
||||
virtual std::string_view GetRestrictPrims() = 0;
|
||||
|
||||
virtual GPURecord::Recorder *GetRecorder() = 0;
|
||||
virtual GPUBreakpoints *GetBreakpoints() = 0;
|
||||
|
|
|
@ -36,6 +36,7 @@ const char *BreakNextToString(BreakNext next) {
|
|||
case BreakNext::VSYNC: return "VSYNC";
|
||||
case BreakNext::PRIM: return "PRIM";
|
||||
case BreakNext::CURVE: return "CURVE";
|
||||
case BreakNext::BLOCK_TRANSFER: return "BLOCK_TRANSFER";
|
||||
case BreakNext::COUNT: return "COUNT";
|
||||
default: return "N/A";
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ enum class BreakNext {
|
|||
VSYNC,
|
||||
PRIM,
|
||||
CURVE,
|
||||
BLOCK_TRANSFER,
|
||||
COUNT,
|
||||
};
|
||||
|
||||
|
|
|
@ -2017,10 +2017,6 @@ void GPUCommon::ClearBreakNext() {
|
|||
GPUStepping::ResumeFromStepping();
|
||||
}
|
||||
|
||||
GPUDebug::BreakNext GPUCommon::GetBreakNext() {
|
||||
return breakNext_;
|
||||
}
|
||||
|
||||
void GPUCommon::SetBreakNext(GPUDebug::BreakNext next) {
|
||||
breakNext_ = next;
|
||||
breakAtCount_ = -1;
|
||||
|
@ -2034,6 +2030,7 @@ void GPUCommon::SetBreakNext(GPUDebug::BreakNext next) {
|
|||
breakpoints_.AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_VAP, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_TRANSFERSTART, true); // We count block transfers as prims, too.
|
||||
break;
|
||||
case GPUDebug::BreakNext::CURVE:
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
|
@ -2044,6 +2041,9 @@ void GPUCommon::SetBreakNext(GPUDebug::BreakNext next) {
|
|||
// This will take us to the following actual draw.
|
||||
primAfterDraw_ = true;
|
||||
break;
|
||||
case GPUDebug::BreakNext::BLOCK_TRANSFER:
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_TRANSFERSTART, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2075,14 +2075,14 @@ GPUDebug::NotifyResult GPUCommon::NotifyCommand(u32 pc, GPUBreakpoints *breakpoi
|
|||
bool isPrim = false;
|
||||
|
||||
bool process = true;
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_VAP) { // VAP is immediate mode prims.
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_VAP || cmd == GE_CMD_TRANSFERSTART) { // VAP is immediate mode prims.
|
||||
isPrim = true;
|
||||
|
||||
// TODO: Should restricted prim ranges also avoid breakpoints?
|
||||
|
||||
if (!restrictPrimRanges.empty()) {
|
||||
if (!restrictPrimRanges_.empty()) {
|
||||
process = false;
|
||||
for (const auto &range : restrictPrimRanges) {
|
||||
for (const auto &range : restrictPrimRanges_) {
|
||||
if ((primsThisFrame_ + 1) >= range.first && (primsThisFrame_ + 1) <= range.second) {
|
||||
process = true;
|
||||
break;
|
||||
|
@ -2100,12 +2100,12 @@ GPUDebug::NotifyResult GPUCommon::NotifyCommand(u32 pc, GPUBreakpoints *breakpoi
|
|||
debugBreak = breakpoints->IsBreakpoint(pc, op);
|
||||
}
|
||||
|
||||
if (debugBreak && pc == g_skipPcOnce) {
|
||||
INFO_LOG(Log::GeDebugger, "Skipping GE break at %08x (last break was here)", g_skipPcOnce);
|
||||
g_skipPcOnce = 0;
|
||||
if (debugBreak && pc == skipPcOnce_) {
|
||||
INFO_LOG(Log::GeDebugger, "Skipping GE break at %08x (last break was here)", skipPcOnce_);
|
||||
skipPcOnce_ = 0;
|
||||
goto bail;
|
||||
}
|
||||
g_skipPcOnce = 0;
|
||||
skipPcOnce_ = 0;
|
||||
|
||||
if (debugBreak) {
|
||||
breakpoints->ClearTempBreakpoints();
|
||||
|
@ -2119,7 +2119,7 @@ GPUDebug::NotifyResult GPUCommon::NotifyCommand(u32 pc, GPUBreakpoints *breakpoi
|
|||
auto info = DisassembleOp(pc, op);
|
||||
NOTICE_LOG(Log::GeDebugger, "Waiting at %08x, %s", pc, info.desc.c_str());
|
||||
|
||||
g_skipPcOnce = pc;
|
||||
skipPcOnce_ = pc;
|
||||
breakNext_ = BreakNext::NONE;
|
||||
// Not incrementing the prim counter!
|
||||
return NotifyResult::Break; // caller will call GPUStepping::EnterStepping().
|
||||
|
@ -2159,19 +2159,15 @@ void GPUCommon::NotifyDisplay(u32 framebuf, u32 stride, int format) {
|
|||
|
||||
bool GPUCommon::SetRestrictPrims(std::string_view rule) {
|
||||
if (rule.empty() || rule == "*") {
|
||||
restrictPrimRanges.clear();
|
||||
restrictPrimRule.clear();
|
||||
restrictPrimRanges_.clear();
|
||||
restrictPrimRule_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GPUDebug::ParsePrimRanges(rule, &restrictPrimRanges)) {
|
||||
restrictPrimRule = rule;
|
||||
if (GPUDebug::ParsePrimRanges(rule, &restrictPrimRanges_)) {
|
||||
restrictPrimRule_ = rule;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *GPUCommon::GetRestrictPrims() {
|
||||
return restrictPrimRule.c_str();
|
||||
}
|
||||
|
|
|
@ -388,9 +388,16 @@ public:
|
|||
void ClearBreakNext() override;
|
||||
void SetBreakNext(GPUDebug::BreakNext next) override;
|
||||
void SetBreakCount(int c, bool relative = false) override;
|
||||
GPUDebug::BreakNext GetBreakNext() override;
|
||||
GPUDebug::BreakNext GetBreakNext() const override {
|
||||
return breakNext_;
|
||||
}
|
||||
int GetBreakCount() const override {
|
||||
return breakAtCount_;
|
||||
}
|
||||
bool SetRestrictPrims(std::string_view rule) override;
|
||||
const char *GetRestrictPrims() override;
|
||||
std::string_view GetRestrictPrims() override {
|
||||
return restrictPrimRule_;
|
||||
}
|
||||
|
||||
int PrimsThisFrame() const override {
|
||||
return primsThisFrame_;
|
||||
|
@ -545,10 +552,10 @@ protected:
|
|||
|
||||
bool primAfterDraw_ = false;
|
||||
|
||||
uint32_t g_skipPcOnce = 0;
|
||||
uint32_t skipPcOnce_ = 0;
|
||||
|
||||
std::vector<std::pair<int, int>> restrictPrimRanges;
|
||||
std::string restrictPrimRule;
|
||||
std::vector<std::pair<int, int>> restrictPrimRanges_;
|
||||
std::string restrictPrimRule_;
|
||||
|
||||
private:
|
||||
void DoExecuteCall(u32 target);
|
||||
|
|
|
@ -151,6 +151,8 @@ struct ImConfig {
|
|||
int selectedMemCheck = -1;
|
||||
uint64_t selectedTexAddr = 0;
|
||||
|
||||
int breakCount = 0;
|
||||
|
||||
bool displayLatched = false;
|
||||
|
||||
// We use a separate ini file from the main PPSSPP config.
|
||||
|
|
|
@ -784,6 +784,10 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::DRAW);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Block xfer")) {
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::BLOCK_TRANSFER);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Curve")) {
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::CURVE);
|
||||
}
|
||||
|
@ -798,7 +802,26 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
ImGui::SameLine();
|
||||
ImGui::Text("%d/%d", gpuDebug->PrimsThisFrame(), gpuDebug->PrimsLastFrame());
|
||||
|
||||
// TODO: Break on count!
|
||||
if (disableStepButtons) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(160.0f);
|
||||
ImGui::InputInt("Number", &cfg.breakCount);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Break on #")) {
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::COUNT);
|
||||
gpuDebug->SetBreakCount(cfg.breakCount);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Step by")) {
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::COUNT);
|
||||
gpuDebug->SetBreakCount(cfg.breakCount, true); // relative
|
||||
}
|
||||
if (disableStepButtons) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
// Line break
|
||||
if (ImGui::Button("Goto PC")) {
|
||||
|
@ -821,6 +844,10 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
if (showBannerInFrames_ == 0) {
|
||||
ImGui::Text("Step pending (waiting for CPU): %s", GPUDebug::BreakNextToString(gpuDebug->GetBreakNext()));
|
||||
ImGui::SameLine();
|
||||
if (gpuDebug->GetBreakNext() == GPUDebug::BreakNext::COUNT) {
|
||||
ImGui::Text("(%d)", gpuDebug->GetBreakCount());
|
||||
ImGui::SameLine();
|
||||
}
|
||||
if (ImGui::Button("Cancel step")) {
|
||||
gpuDebug->ClearBreakNext();
|
||||
}
|
||||
|
|
|
@ -1116,8 +1116,8 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
|
||||
case IDC_GEDBG_SETPRIMFILTER:
|
||||
{
|
||||
std::string value = gpuDebug->GetRestrictPrims();
|
||||
if (InputBox_GetString(GetModuleHandle(NULL), m_hDlg, L"Prim counter ranges", value, value)) {
|
||||
std::string value;
|
||||
if (InputBox_GetString(GetModuleHandle(NULL), m_hDlg, L"Prim counter ranges", gpuDebug->GetRestrictPrims(), value)) {
|
||||
gpuDebug->SetRestrictPrims(value.c_str());
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -59,7 +59,7 @@ static INT_PTR CALLBACK InputBoxFunc(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
}
|
||||
}
|
||||
|
||||
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultValue, std::string &outvalue, InputBoxFlags flags) {
|
||||
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string_view defaultValue, std::string &outvalue, InputBoxFlags flags) {
|
||||
const wchar_t *defaultTitle = L"Input value";
|
||||
|
||||
g_params.defaultSelected = flags & InputBoxFlags::Selected;
|
||||
|
|
|
@ -12,7 +12,7 @@ enum class InputBoxFlags {
|
|||
ENUM_CLASS_BITOPS(InputBoxFlags);
|
||||
|
||||
// All I/O is in UTF-8
|
||||
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, const std::string &defaultvalue, std::string &outvalue, InputBoxFlags flags = InputBoxFlags::Default);
|
||||
bool InputBox_GetString(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string_view defaultvalue, std::string &outvalue, InputBoxFlags flags = InputBoxFlags::Default);
|
||||
bool InputBox_GetHex(HINSTANCE hInst, HWND hParent, const wchar_t *title, u32 defaultvalue, u32 &outvalue);
|
||||
|
||||
bool UserPasswordBox_GetStrings(HINSTANCE hInst, HWND hParent, const wchar_t *title, std::string *username, std::string *password);
|
||||
|
|
Loading…
Add table
Reference in a new issue