mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 15:15:40 +00:00
Add debugging for GPU/Timers
This commit is contained in:
parent
b945d10b04
commit
0f68c8c5d3
|
@ -143,15 +143,6 @@ void GPU::ResetGraphicsAPIState() {}
|
|||
|
||||
void GPU::RestoreGraphicsAPIState() {}
|
||||
|
||||
void GPU::DrawStatistics() {}
|
||||
|
||||
void GPU::DrawDebugMenu()
|
||||
{
|
||||
ImGui::MenuItem("Show VRAM", nullptr, &m_debug_options.show_vram);
|
||||
ImGui::MenuItem("Dump CPU to VRAM Copies", nullptr, &m_debug_options.dump_cpu_to_vram_copies);
|
||||
ImGui::MenuItem("Dump VRAM to CPU Copies", nullptr, &m_debug_options.dump_vram_to_cpu_copies);
|
||||
}
|
||||
|
||||
void GPU::UpdateSettings() {}
|
||||
|
||||
void GPU::UpdateGPUSTAT()
|
||||
|
@ -976,3 +967,70 @@ bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride
|
|||
}
|
||||
return (stbi_write_png(filename, width, height, 4, rgba8_buf.data(), sizeof(u32) * width) != 0);
|
||||
}
|
||||
|
||||
void GPU::DrawDebugWindows()
|
||||
{
|
||||
if (m_debug_options.show_state)
|
||||
DrawDebugStateWindow();
|
||||
}
|
||||
|
||||
void GPU::DrawDebugMenu()
|
||||
{
|
||||
if (ImGui::BeginMenu("GPU"))
|
||||
{
|
||||
ImGui::MenuItem("Show State", nullptr, &m_debug_options.show_state);
|
||||
ImGui::MenuItem("Show VRAM", nullptr, &m_debug_options.show_vram);
|
||||
ImGui::MenuItem("Dump CPU to VRAM Copies", nullptr, &m_debug_options.dump_cpu_to_vram_copies);
|
||||
ImGui::MenuItem("Dump VRAM to CPU Copies", nullptr, &m_debug_options.dump_vram_to_cpu_copies);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void GPU::DrawDebugStateWindow()
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(450, 550), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin("GPU State", &m_debug_options.show_state))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("CRTC", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
const auto& cs = m_crtc_state;
|
||||
ImGui::Text("Resolution: %ux%u", cs.horizontal_resolution, cs.vertical_resolution);
|
||||
ImGui::Text("Dot Clock Divider: %u", cs.dot_clock_divider);
|
||||
ImGui::Text("Vertical Interlace: %s (%s field)", m_GPUSTAT.vertical_interlace ? "Yes" : "No",
|
||||
m_GPUSTAT.interlaced_field ? "odd" : "even");
|
||||
ImGui::Text("Display Enable: %s", m_GPUSTAT.display_enable ? "Yes" : "No");
|
||||
ImGui::Text("Drawing Even Line: %s", m_GPUSTAT.drawing_even_line ? "Yes" : "No");
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("Color Depth: %u-bit", m_GPUSTAT.display_area_color_depth_24 ? 24 : 15);
|
||||
ImGui::Text("Start Offset: (%u, %u)", cs.regs.X.GetValue(), cs.regs.Y.GetValue());
|
||||
ImGui::Text("Display Range: %u-%u, %u-%u", cs.regs.X1.GetValue(), cs.regs.X2.GetValue(), cs.regs.Y1.GetValue(),
|
||||
cs.regs.Y2.GetValue());
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("Visible Resolution: %ux%u", cs.visible_horizontal_resolution, cs.visible_vertical_resolution);
|
||||
ImGui::Text("Ticks Per Scanline: %u (%u visible)", cs.ticks_per_scanline, cs.visible_ticks_per_scanline);
|
||||
ImGui::Text("Scanlines Per Frame: %u", cs.total_scanlines_per_frame);
|
||||
ImGui::Text("Current Scanline: %u (tick %u)", cs.current_scanline, cs.current_tick_in_scanline);
|
||||
ImGui::Text("Horizontal Blank: %s", cs.in_hblank ? "Yes" : "No");
|
||||
ImGui::Text("Vertical Blank: %s", cs.in_vblank ? "Yes" : "No");
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("GPU", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::Text("Dither: %s", m_GPUSTAT.dither_enable ? "Enabled" : "Disabled");
|
||||
ImGui::Text("Draw To Display Area: %s", m_GPUSTAT.dither_enable ? "Yes" : "No");
|
||||
ImGui::Text("Draw Set Mask Bit: %s", m_GPUSTAT.draw_set_mask_bit ? "Yes" : "No");
|
||||
ImGui::Text("Draw To Masked Pixels: %s", m_GPUSTAT.draw_to_masked_pixels ? "Yes" : "No");
|
||||
ImGui::Text("Reverse Flag: %s", m_GPUSTAT.reverse_flag ? "Yes" : "No");
|
||||
ImGui::Text("Texture Disable: %s", m_GPUSTAT.texture_disable ? "Yes" : "No");
|
||||
ImGui::Text("PAL Mode: %s", m_GPUSTAT.pal_mode ? "Yes" : "No");
|
||||
ImGui::Text("Interrupt Request: %s", m_GPUSTAT.interrupt_request ? "Yes" : "No");
|
||||
ImGui::Text("DMA Request: %s", m_GPUSTAT.dma_data_request ? "Yes" : "No");
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ public:
|
|||
virtual void RestoreGraphicsAPIState();
|
||||
|
||||
// Render statistics debug window.
|
||||
virtual void DrawStatistics();
|
||||
virtual void DrawDebugWindows();
|
||||
|
||||
// Manipulating debug options.
|
||||
virtual void DrawDebugMenu();
|
||||
|
@ -162,9 +162,10 @@ protected:
|
|||
|
||||
struct DebugOptions
|
||||
{
|
||||
bool show_vram;
|
||||
bool dump_cpu_to_vram_copies;
|
||||
bool dump_vram_to_cpu_copies;
|
||||
bool show_state = false;
|
||||
bool show_vram = false;
|
||||
bool dump_cpu_to_vram_copies = false;
|
||||
bool dump_vram_to_cpu_copies = false;
|
||||
};
|
||||
|
||||
void SoftReset();
|
||||
|
@ -200,6 +201,9 @@ protected:
|
|||
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices);
|
||||
virtual void FlushRender();
|
||||
|
||||
// Debugging
|
||||
void DrawDebugStateWindow();
|
||||
|
||||
System* m_system = nullptr;
|
||||
DMA* m_dma = nullptr;
|
||||
InterruptController* m_interrupt_controller = nullptr;
|
||||
|
@ -351,5 +355,5 @@ protected:
|
|||
std::vector<u32> m_GP0_command;
|
||||
std::deque<u32> m_GPUREAD_buffer;
|
||||
|
||||
DebugOptions m_debug_options = {};
|
||||
DebugOptions m_debug_options;
|
||||
};
|
||||
|
|
|
@ -587,5 +587,4 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices)
|
|||
}
|
||||
|
||||
LoadVertices(rc, num_vertices);
|
||||
FlushRender();
|
||||
}
|
||||
|
|
|
@ -65,11 +65,24 @@ void GPU_HW_OpenGL::RestoreGraphicsAPIState()
|
|||
glBindVertexArray(m_vao_id);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::DrawStatistics()
|
||||
void GPU_HW_OpenGL::DrawDebugWindows()
|
||||
{
|
||||
GPU_HW::DrawStatistics();
|
||||
GPU_HW::DrawDebugWindows();
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(300.0f, 130.0f), ImGuiCond_Once);
|
||||
if (m_show_renderer_statistics)
|
||||
DrawRendererStatistics();
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::DrawDebugMenu()
|
||||
{
|
||||
GPU_HW::DrawDebugMenu();
|
||||
|
||||
ImGui::MenuItem("GPU Renderer", nullptr, &m_show_renderer_statistics);
|
||||
}
|
||||
|
||||
void GPU_HW_OpenGL::DrawRendererStatistics()
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(300.0f, 130.0f), ImGuiCond_FirstUseEver);
|
||||
|
||||
const bool is_null_frame = m_stats.num_batches == 0;
|
||||
if (!is_null_frame)
|
||||
|
@ -78,7 +91,7 @@ void GPU_HW_OpenGL::DrawStatistics()
|
|||
m_stats = {};
|
||||
}
|
||||
|
||||
if (ImGui::Begin("GPU Render Statistics"))
|
||||
if (ImGui::Begin("GPU Renderer Statistics", &m_show_renderer_statistics))
|
||||
{
|
||||
ImGui::Columns(2);
|
||||
ImGui::SetColumnWidth(0, 200.0f);
|
||||
|
|
|
@ -19,7 +19,8 @@ public:
|
|||
void ResetGraphicsAPIState() override;
|
||||
void RestoreGraphicsAPIState() override;
|
||||
|
||||
void DrawStatistics() override;
|
||||
void DrawDebugWindows() override;
|
||||
void DrawDebugMenu() override;
|
||||
void UpdateSettings() override;
|
||||
|
||||
protected:
|
||||
|
@ -40,6 +41,8 @@ private:
|
|||
u32 num_vertices;
|
||||
};
|
||||
|
||||
void DrawRendererStatistics();
|
||||
|
||||
std::tuple<s32, s32> ConvertToFramebufferCoordinates(s32 x, s32 y);
|
||||
|
||||
void SetMaxResolutionScale();
|
||||
|
@ -72,6 +75,7 @@ private:
|
|||
|
||||
bool m_vram_read_texture_dirty = true;
|
||||
bool m_drawing_area_changed = true;
|
||||
bool m_show_renderer_statistics = false;
|
||||
|
||||
std::array<std::array<std::array<std::array<GL::Program, 2>, 3>, 2>, 4> m_render_programs;
|
||||
GL::Program m_reinterpret_rgb8_program;
|
||||
|
|
|
@ -897,5 +897,5 @@ void SPU::DrawDebugWindow()
|
|||
void SPU::DrawDebugMenu()
|
||||
{
|
||||
// TODO: Show RAM, etc.
|
||||
ImGui::MenuItem("Show State", nullptr, &m_show_spu_state);
|
||||
ImGui::MenuItem("SPU", nullptr, &m_show_spu_state);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "spu.h"
|
||||
#include "timers.h"
|
||||
#include <cstdio>
|
||||
#include <imgui.h>
|
||||
Log_SetChannel(System);
|
||||
|
||||
System::System(HostInterface* host_interface, const Settings& settings)
|
||||
|
@ -320,3 +321,17 @@ void System::RemoveMedia()
|
|||
{
|
||||
m_cdrom->RemoveMedia();
|
||||
}
|
||||
|
||||
void System::DrawDebugMenus()
|
||||
{
|
||||
m_gpu->DrawDebugMenu();
|
||||
m_spu->DrawDebugMenu();
|
||||
m_timers->DrawDebugMenu();
|
||||
}
|
||||
|
||||
void System::DrawDebugWindows()
|
||||
{
|
||||
m_gpu->DrawDebugWindows();
|
||||
m_spu->DrawDebugWindow();
|
||||
m_timers->DrawDebugWindow();
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
bool InsertMedia(const char* path);
|
||||
void RemoveMedia();
|
||||
|
||||
void DrawDebugMenus();
|
||||
void DrawDebugWindows();
|
||||
|
||||
private:
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "common/state_wrapper.h"
|
||||
#include "interrupt_controller.h"
|
||||
#include "system.h"
|
||||
#include <imgui.h>
|
||||
Log_SetChannel(Timers);
|
||||
|
||||
Timers::Timers() = default;
|
||||
|
@ -140,7 +141,7 @@ void Timers::Execute(TickCount sysclk_ticks)
|
|||
}
|
||||
else if (m_states[2].counting_enabled)
|
||||
{
|
||||
AddTicks(2, m_states[2].external_counting_enabled ? sysclk_ticks / 8 : sysclk_ticks);
|
||||
AddTicks(2, sysclk_ticks);
|
||||
}
|
||||
|
||||
UpdateDowncount();
|
||||
|
@ -290,3 +291,81 @@ void Timers::UpdateDowncount()
|
|||
|
||||
m_system->SetDowncount(min_ticks);
|
||||
}
|
||||
|
||||
void Timers::DrawDebugMenu()
|
||||
{
|
||||
ImGui::MenuItem("Timers", nullptr, &m_debug_show_state);
|
||||
}
|
||||
|
||||
void Timers::DrawDebugWindow()
|
||||
{
|
||||
if (!m_debug_show_state)
|
||||
return;
|
||||
|
||||
static constexpr u32 NUM_COLUMNS = 10;
|
||||
static constexpr std::array<const char*, NUM_COLUMNS> column_names = {
|
||||
{"#", "Value", "Target", "Sync", "Reset", "IRQ", "IRQRepeat", "IRQToggle", "Clock Source", "Reached"}};
|
||||
static constexpr std::array<const char*, 4> sync_mode_names = {
|
||||
{"PauseOnGate", "ResetOnGate", "ResetAndRunOnGate", "FreeRunOnGate"}};
|
||||
static constexpr std::array<std::array<const char*, 4>, 3> clock_source_names = {
|
||||
{{{"SysClk", "DotClk", "SysClk", "DotClk"}},
|
||||
{{"SysClk", "HBlank", "SysClk", "HBlank"}},
|
||||
{{"SysClk", "DotClk", "SysClk/8", "SysClk/8"}}}};
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(800, 100), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin("Timer State", &m_debug_show_state))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Columns(NUM_COLUMNS);
|
||||
ImGui::SetColumnWidth(0, 20.0f);
|
||||
ImGui::SetColumnWidth(1, 50.0f);
|
||||
ImGui::SetColumnWidth(2, 50.0f);
|
||||
ImGui::SetColumnWidth(3, 100.0f);
|
||||
ImGui::SetColumnWidth(4, 80.0f);
|
||||
ImGui::SetColumnWidth(5, 80.0f);
|
||||
ImGui::SetColumnWidth(6, 80.0f);
|
||||
ImGui::SetColumnWidth(7, 80.0f);
|
||||
ImGui::SetColumnWidth(8, 80.0f);
|
||||
ImGui::SetColumnWidth(9, 80.0f);
|
||||
|
||||
for (const char* title : column_names)
|
||||
{
|
||||
ImGui::TextUnformatted(title);
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < NUM_TIMERS; i++)
|
||||
{
|
||||
const CounterState& cs = m_states[i];
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,
|
||||
cs.counting_enabled ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0.5f, 0.5f, 0.5f, 1.0f));
|
||||
ImGui::Text("%u", i);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%u", cs.counter);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%u", cs.target);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s",
|
||||
cs.mode.sync_enable ? sync_mode_names[static_cast<u8>(cs.mode.sync_mode.GetValue())] : "Disabled");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s", cs.mode.reset_at_target ? "@Target" : "@Overflow");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s%s", cs.mode.irq_at_target ? "Target " : "", cs.mode.irq_on_overflow ? "Overflow" : "");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s", cs.mode.irq_repeat ? "Yes" : "No");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s", cs.mode.irq_pulse_n ? "Yes" : "No");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s%s", clock_source_names[i][cs.mode.clock_source], cs.external_counting_enabled ? " (External)" : "");
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("%s", cs.mode.reached_target ? "Target " : "", cs.mode.reached_overflow ? "Overflow" : "");
|
||||
ImGui::NextColumn();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::Columns(1);
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ public:
|
|||
|
||||
void SetGate(u32 timer, bool state);
|
||||
|
||||
void DrawDebugMenu();
|
||||
void DrawDebugWindow();
|
||||
|
||||
// dot clock/hblank/sysclk div 8
|
||||
bool IsUsingExternalClock(u32 timer) const { return m_states[timer].external_counting_enabled; }
|
||||
void AddTicks(u32 timer, TickCount ticks);
|
||||
|
@ -78,4 +81,6 @@ private:
|
|||
|
||||
std::array<CounterState, NUM_TIMERS> m_states{};
|
||||
u32 m_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8
|
||||
|
||||
bool m_debug_show_state = false;
|
||||
};
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "core/digital_controller.h"
|
||||
#include "core/gpu.h"
|
||||
#include "core/memory_card.h"
|
||||
#include "core/spu.h"
|
||||
#include "core/system.h"
|
||||
#include "icon.h"
|
||||
#include "sdl_audio_stream.h"
|
||||
|
@ -496,10 +495,7 @@ void SDLInterface::DrawImGui()
|
|||
{
|
||||
DrawMainMenuBar();
|
||||
|
||||
if (m_show_gpu_statistics)
|
||||
m_system->GetGPU()->DrawStatistics();
|
||||
|
||||
m_system->GetSPU()->DrawDebugWindow();
|
||||
m_system->DrawDebugWindows();
|
||||
|
||||
DrawOSDMessages();
|
||||
|
||||
|
@ -585,22 +581,7 @@ void SDLInterface::DrawMainMenuBar()
|
|||
|
||||
if (ImGui::BeginMenu("Debug"))
|
||||
{
|
||||
if (ImGui::BeginMenu("GPU"))
|
||||
{
|
||||
ImGui::MenuItem("Show Statistics", nullptr, &m_show_gpu_statistics);
|
||||
ImGui::Separator();
|
||||
|
||||
m_system->GetGPU()->DrawDebugMenu();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("SPU"))
|
||||
{
|
||||
m_system->GetSPU()->DrawDebugMenu();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
m_system->DrawDebugMenus();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,4 @@ private:
|
|||
u32 m_last_internal_frame_number = 0;
|
||||
u32 m_last_global_tick_counter = 0;
|
||||
Timer m_fps_timer;
|
||||
|
||||
// UI options
|
||||
bool m_show_gpu_statistics = false;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue