mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #15378 from unknownbrackets/gedebugger-skip
GE Debugger: Add filter to skip prim calls
This commit is contained in:
commit
50350e13ac
6 changed files with 138 additions and 28 deletions
|
@ -15,7 +15,9 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <vector>
|
||||
#include "Common/Log.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
|
@ -32,6 +34,9 @@ static int primsLastFrame = 0;
|
|||
static int primsThisFrame = 0;
|
||||
static int thisFlipNum = 0;
|
||||
|
||||
static std::vector<std::pair<int, int>> restrictPrimRanges;
|
||||
static std::string restrictPrimRule;
|
||||
|
||||
static void Init() {
|
||||
if (!inited) {
|
||||
GPUBreakpoints::Init();
|
||||
|
@ -90,9 +95,9 @@ static bool IsBreakpoint(u32 pc, u32 op) {
|
|||
}
|
||||
}
|
||||
|
||||
void NotifyCommand(u32 pc) {
|
||||
bool NotifyCommand(u32 pc) {
|
||||
if (!active)
|
||||
return;
|
||||
return true;
|
||||
u32 op = Memory::ReadUnchecked_U32(pc);
|
||||
u32 cmd = op >> 24;
|
||||
if (thisFlipNum != gpuStats.numFlips) {
|
||||
|
@ -100,8 +105,20 @@ void NotifyCommand(u32 pc) {
|
|||
primsThisFrame = 0;
|
||||
thisFlipNum = gpuStats.numFlips;
|
||||
}
|
||||
|
||||
bool process = true;
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) {
|
||||
primsThisFrame++;
|
||||
|
||||
if (!restrictPrimRanges.empty()) {
|
||||
process = false;
|
||||
for (const auto &range : restrictPrimRanges) {
|
||||
if (primsThisFrame >= range.first && primsThisFrame <= range.second) {
|
||||
process = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsBreakpoint(pc, op)) {
|
||||
|
@ -111,6 +128,8 @@ void NotifyCommand(u32 pc) {
|
|||
NOTICE_LOG(G3D, "Waiting at %08x, %s", pc, info.desc.c_str());
|
||||
GPUStepping::EnterStepping();
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
void NotifyDraw() {
|
||||
|
@ -131,11 +150,6 @@ void NotifyDisplay(u32 framebuf, u32 stride, int format) {
|
|||
}
|
||||
}
|
||||
|
||||
void NotifyTextureAttachment(u32 texaddr) {
|
||||
if (!active)
|
||||
return;
|
||||
}
|
||||
|
||||
int PrimsThisFrame() {
|
||||
return primsThisFrame;
|
||||
}
|
||||
|
@ -144,4 +158,84 @@ int PrimsLastFrame() {
|
|||
return primsLastFrame;
|
||||
}
|
||||
|
||||
static bool ParseRange(const std::string &s, std::pair<int, int> &range) {
|
||||
int c = sscanf(s.c_str(), "%d-%d", &range.first, &range.second);
|
||||
if (c == 0)
|
||||
return false;
|
||||
if (c == 1)
|
||||
range.second = range.first;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetRestrictPrims(const char *rule) {
|
||||
SetActive(true);
|
||||
if (rule == nullptr || rule[0] == 0 || (rule[0] == '*' && rule[1] == 0)) {
|
||||
restrictPrimRanges.clear();
|
||||
restrictPrimRule.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr int MAX_PRIMS = 0x7FFFFFFF;
|
||||
std::vector<std::string> parts;
|
||||
SplitString(rule, ',', parts);
|
||||
|
||||
// Parse expressions like: 0 or 0-1,4-5 or !2 or !2-3 or !2,!3
|
||||
std::vector<std::pair<int, int>> updated;
|
||||
for (auto &part : parts) {
|
||||
std::pair<int, int> range;
|
||||
if (part.size() > 1 && part[0] == '!') {
|
||||
if (!ParseRange(part.substr(1), range))
|
||||
return false;
|
||||
|
||||
// If there's nothing yet, add everything else.
|
||||
if (updated.empty()) {
|
||||
if (range.first > 0)
|
||||
updated.push_back(std::make_pair(0, range.first - 1));
|
||||
if (range.second < MAX_PRIMS)
|
||||
updated.push_back(std::make_pair(range.second + 1, MAX_PRIMS));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, remove this range from any existing.
|
||||
for (size_t i = 0; i < updated.size(); ++i) {
|
||||
auto &sub = updated[i];
|
||||
if (sub.second < range.first || sub.first > range.second)
|
||||
continue;
|
||||
if (sub.first >= range.first && sub.second <= range.second) {
|
||||
// Entire subrange is inside the deleted entries, nuke.
|
||||
sub.first = -1;
|
||||
sub.second = -1;
|
||||
continue;
|
||||
}
|
||||
if (sub.first < range.first && sub.second > range.second) {
|
||||
// We're slicing a hole in this subrange.
|
||||
int next = sub.second;
|
||||
sub.second = range.first - 1;
|
||||
updated.push_back(std::make_pair(range.second + 1, next));
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we got here, we're simply clipping the subrange.
|
||||
if (sub.first < range.first && sub.second >= range.first && sub.second <= range.second)
|
||||
sub.second = range.first - 1;
|
||||
if (sub.first >= range.first && sub.first <= range.second && sub.second < range.second)
|
||||
sub.first = range.second + 1;
|
||||
}
|
||||
} else {
|
||||
if (!ParseRange(part, range))
|
||||
return false;
|
||||
|
||||
updated.push_back(range);
|
||||
}
|
||||
}
|
||||
|
||||
restrictPrimRanges = updated;
|
||||
restrictPrimRule = rule;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *GetRestrictPrims() {
|
||||
return restrictPrimRule.c_str();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,12 +40,14 @@ void SetBreakNext(BreakNext next);
|
|||
void SetBreakCount(int c, bool relative = false);
|
||||
|
||||
// While debugging is active, these may block.
|
||||
void NotifyCommand(u32 pc);
|
||||
bool NotifyCommand(u32 pc);
|
||||
void NotifyDraw();
|
||||
void NotifyDisplay(u32 framebuf, u32 stride, int format);
|
||||
void NotifyTextureAttachment(u32 texaddr);
|
||||
|
||||
int PrimsThisFrame();
|
||||
int PrimsLastFrame();
|
||||
|
||||
bool SetRestrictPrims(const char *rule);
|
||||
const char *GetRestrictPrims();
|
||||
|
||||
}
|
||||
|
|
|
@ -1097,27 +1097,29 @@ void GPUCommon::SlowRunLoop(DisplayList &list)
|
|||
const bool dumpThisFrame = dumpThisFrame_;
|
||||
while (downcount > 0)
|
||||
{
|
||||
GPUDebug::NotifyCommand(list.pc);
|
||||
GPURecord::NotifyCommand(list.pc);
|
||||
u32 op = Memory::ReadUnchecked_U32(list.pc);
|
||||
u32 cmd = op >> 24;
|
||||
bool process = GPUDebug::NotifyCommand(list.pc);
|
||||
if (process) {
|
||||
GPURecord::NotifyCommand(list.pc);
|
||||
u32 op = Memory::ReadUnchecked_U32(list.pc);
|
||||
u32 cmd = op >> 24;
|
||||
|
||||
u32 diff = op ^ gstate.cmdmem[cmd];
|
||||
PreExecuteOp(op, diff);
|
||||
if (dumpThisFrame) {
|
||||
char temp[256];
|
||||
u32 prev;
|
||||
if (Memory::IsValidAddress(list.pc - 4)) {
|
||||
prev = Memory::ReadUnchecked_U32(list.pc - 4);
|
||||
} else {
|
||||
prev = 0;
|
||||
u32 diff = op ^ gstate.cmdmem[cmd];
|
||||
PreExecuteOp(op, diff);
|
||||
if (dumpThisFrame) {
|
||||
char temp[256];
|
||||
u32 prev;
|
||||
if (Memory::IsValidAddress(list.pc - 4)) {
|
||||
prev = Memory::ReadUnchecked_U32(list.pc - 4);
|
||||
} else {
|
||||
prev = 0;
|
||||
}
|
||||
GeDisassembleOp(list.pc, op, prev, temp, 256);
|
||||
NOTICE_LOG(G3D, "%08x: %s", op, temp);
|
||||
}
|
||||
GeDisassembleOp(list.pc, op, prev, temp, 256);
|
||||
NOTICE_LOG(G3D, "%08x: %s", op, temp);
|
||||
}
|
||||
gstate.cmdmem[cmd] = op;
|
||||
gstate.cmdmem[cmd] = op;
|
||||
|
||||
ExecuteOp(op, diff);
|
||||
ExecuteOp(op, diff);
|
||||
}
|
||||
|
||||
list.pc += 4;
|
||||
--downcount;
|
||||
|
|
|
@ -912,6 +912,15 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
|||
UpdatePreviews();
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_SETPRIMFILTER:
|
||||
{
|
||||
std::string value = GPUDebug::GetRestrictPrims();
|
||||
if (InputBox_GetString(GetModuleHandle(NULL), m_hDlg, L"Prim counter ranges", value, value)) {
|
||||
GPUDebug::SetRestrictPrims(value.c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -665,6 +665,8 @@ BEGIN
|
|||
BEGIN
|
||||
MENUITEM "Rec&ord Next Frame", IDC_GEDBG_RECORD
|
||||
MENUITEM "F&lush Pending Draws", IDC_GEDBG_FLUSH
|
||||
MENUITEM "", 0, MFT_SEPARATOR
|
||||
MENUITEM "Fi<er Prims", IDC_GEDBG_SETPRIMFILTER
|
||||
END
|
||||
|
||||
POPUP "&Step", ID_GEDBG_STEP_MENU
|
||||
|
|
|
@ -325,6 +325,7 @@
|
|||
#define IDC_GEDBG_FLUSH 40212
|
||||
#define IDC_GEDBG_FLUSHAUTO 40213
|
||||
#define IDI_BREAKPOINT_SMALL 40214
|
||||
#define IDC_GEDBG_SETPRIMFILTER 40215
|
||||
|
||||
// Dummy option to let the buffered rendering hotkey cycle through all the options.
|
||||
#define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500
|
||||
|
@ -337,7 +338,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 256
|
||||
#define _APS_NEXT_COMMAND_VALUE 40215
|
||||
#define _APS_NEXT_COMMAND_VALUE 40216
|
||||
#define _APS_NEXT_CONTROL_VALUE 1202
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue