diff --git a/Common/Render/Text/draw_text.cpp b/Common/Render/Text/draw_text.cpp index 1fa2a070b6..d89a8b080e 100644 --- a/Common/Render/Text/draw_text.cpp +++ b/Common/Render/Text/draw_text.cpp @@ -167,6 +167,9 @@ void TextDrawer::MeasureStringRect(std::string_view str, const Bounds &bounds, f } void TextDrawer::DrawStringRect(DrawBuffer &target, std::string_view str, const Bounds &bounds, uint32_t color, int align) { + if (bounds.w < 0.0f || bounds.h < 0.0f) { + return; + } float x = bounds.x; float y = bounds.y; if (align & ALIGN_HCENTER) { diff --git a/GPU/Debugger/State.cpp b/GPU/Debugger/State.cpp index 4398d79768..ec4a093787 100644 --- a/GPU/Debugger/State.cpp +++ b/GPU/Debugger/State.cpp @@ -12,6 +12,9 @@ #include "Core/System.h" void FormatStateRow(GPUDebugInterface *gpudebug, char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2) { + value &= 0xFFFFFF; + otherValue &= 0xFFFFFF; + otherValue2 &= 0xFFFFFF; switch (fmt) { case CMD_FMT_HEX: snprintf(dest, destSize, "%06x", value); diff --git a/GPU/Debugger/Stepping.cpp b/GPU/Debugger/Stepping.cpp index b4a0a81d10..4395a3275a 100644 --- a/GPU/Debugger/Stepping.cpp +++ b/GPU/Debugger/Stepping.cpp @@ -71,6 +71,7 @@ static int bufferLevel; static bool lastWasFramebuffer; static u32 pauseSetCmdValue; +// This is used only to highlight differences. Should really be owned by the debugger. static GPUgstate lastGState; const char *PauseActionToString(PauseAction action) { @@ -161,21 +162,6 @@ void WaitForPauseAction() { actionWait.wait(guard); } -static void StartStepping() { - if (lastGState.cmdmem[1] == 0) { - lastGState = gstate; - // Play it safe so we don't keep resetting. - lastGState.cmdmem[1] |= 0x01000000; - } - isStepping = true; - stepCounter++; -} - -static void StopStepping() { - lastGState = gstate; - isStepping = false; -} - bool ProcessStepping() { _dbg_assert_(gpuDebug); @@ -215,7 +201,15 @@ bool EnterStepping() { return false; } - StartStepping(); + // StartStepping + if (lastGState.cmdmem[1] == 0) { + lastGState = gstate; + // Play it safe so we don't keep resetting. + lastGState.cmdmem[1] |= 0x01000000; + } + + isStepping = true; + stepCounter++; // Just to be sure. if (pauseAction == PAUSE_CONTINUE) { @@ -227,7 +221,8 @@ bool EnterStepping() { } void ResumeFromStepping() { - StopStepping(); + lastGState = gstate; + isStepping = false; SetPauseAction(PAUSE_CONTINUE, false); } @@ -300,7 +295,7 @@ bool GPU_FlushDrawing() { return true; } -GPUgstate LastState() { +const GPUgstate &LastState() { return lastGState; } diff --git a/GPU/Debugger/Stepping.h b/GPU/Debugger/Stepping.h index 1393ffc7c7..0146053a8a 100644 --- a/GPU/Debugger/Stepping.h +++ b/GPU/Debugger/Stepping.h @@ -46,5 +46,6 @@ namespace GPUStepping { bool GPU_SetCmdValue(u32 op); bool GPU_FlushDrawing(); - GPUgstate LastState(); + // Can be used to highlight differences in a debugger. + const GPUgstate &LastState(); }; diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index 96a3362ba0..452f32c13a 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -746,7 +746,7 @@ static const StateItem g_vertexState[] = { }; void ImGeStateWindow::Snapshot() { - + // Not needed for now, we have GPUStepping::LastState() } // TODO: Separate window or merge into Ge debugger? @@ -769,6 +769,8 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface bool sectionOpen = false; for (size_t i = 0; i < numRows; i++) { const GECmdInfo &info = GECmdInfoByCmd(rows[i].cmd); + const GPUgstate &lastState = GPUStepping::LastState(); + bool diff = lastState.cmdmem[rows[i].cmd] != gstate.cmdmem[rows[i].cmd]; if (rows[i].header) { anySection = true; @@ -788,31 +790,37 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface } const bool enabled = info.enableCmd == 0 || (gstate.cmdmem[info.enableCmd] & 1) == 1; - if (!enabled) + if (diff) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 96, 32, enabled ? 255 : 128)); + } else if (!enabled) { ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 128)); + } if (!rows[i].header) { ImGui::TextUnformatted(info.uiName); ImGui::TableNextColumn(); } if (rows[i].cmd != GE_CMD_NOP) { - char temp[256]; + char temp[128], temp2[128]; - const u32 value = gstate.cmdmem[info.cmd] & 0xFFFFFF; - const u32 otherValue = gstate.cmdmem[info.otherCmd] & 0xFFFFFF; - const u32 otherValue2 = gstate.cmdmem[info.otherCmd2] & 0xFFFFFF; + const u32 value = gstate.cmdmem[info.cmd]; + const u32 otherValue = gstate.cmdmem[info.otherCmd]; - // Special handling for pointer and pointer/width entries + // Special handling for pointer and pointer/width entries - create an address control if (info.fmt == CMD_FMT_PTRWIDTH) { const u32 val = value | (otherValue & 0x00FF0000) << 8; ImClickableAddress(val, control, ImCmd::NONE); ImGui::SameLine(); ImGui::Text("w=%d", otherValue & 0xFFFF); } else { - FormatStateRow(gpuDebug, temp, sizeof(temp), info.fmt, value, true, otherValue, otherValue2); + FormatStateRow(gpuDebug, temp, sizeof(temp), info.fmt, value, true, otherValue, gstate.cmdmem[info.otherCmd2]); ImGui::TextUnformatted(temp); } + if (diff && ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) { + FormatStateRow(gpuDebug, temp2, sizeof(temp2), info.fmt, lastState.cmdmem[info.cmd], true, lastState.cmdmem[info.otherCmd], lastState.cmdmem[info.otherCmd2]); + ImGui::SetTooltip("Previous: %s", temp2); + } } - if (!enabled) + if (diff || !enabled) ImGui::PopStyleColor(); } if (sectionOpen) {