core: Make PICA debugging a toggleable feature (#2254)

This commit is contained in:
PabloMK7 2026-07-03 11:00:56 +02:00 committed by GitHub
parent 77cb5cecd8
commit fcb10fb899
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 87 additions and 51 deletions

View File

@ -32,6 +32,7 @@ foreach(KEY IN ITEMS
"physical_device"
"use_gles"
"renderer_debug"
"pica_debugging"
"dump_command_buffers"
"spirv_shader_gen"
"disable_spirv_optimizer"

View File

@ -314,6 +314,7 @@ void Config::ReadValues() {
Settings::values.record_frame_times =
android_config->GetBoolean("Debugging", Settings::HKeys::record_frame_times.c_str(), false);
ReadSetting("Debugging", Settings::values.renderer_debug);
ReadSetting("Debugging", Settings::values.pica_debugging);
ReadSetting("Debugging", Settings::values.use_gdbstub);
ReadSetting("Debugging", Settings::values.gdbstub_port);
ReadSetting("Debugging", Settings::values.instant_debug_log);

View File

@ -546,6 +546,10 @@ static const char* android_config_default_file_content = (BOOST_HANA_STRING(R"(
# 0 (default): Off, 1: On
)") DECLARE_KEY(renderer_debug) BOOST_HANA_STRING(R"(
# Whether to enable PICA200 debugging (does nothing on Android)
# 0 (default): Off, 1: On
)") DECLARE_KEY(pica_debugging) BOOST_HANA_STRING(R"(
# Flush log output on every message
# Immediately commits the debug log to file. Use this if Azahar crashes and the log output is being cut.
)") DECLARE_KEY(instant_debug_log) BOOST_HANA_STRING(R"(

View File

@ -255,7 +255,13 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
// Register microphone permission check
system.RegisterMicPermissionCheck(&CheckMicPermission);
Pica::g_debug_context = Pica::DebugContext::Construct();
// No PICA debugging on Android
if (Settings::values.pica_debugging) {
Pica::g_debug_context = Pica::DebugContext::Construct();
} else {
Pica::g_debug_context.reset();
}
InputManager::Init();
window->MakeCurrent();

View File

@ -414,7 +414,11 @@ GMainWindow::GMainWindow(Core::System& system_)
LoadTranslation();
Pica::g_debug_context = Pica::DebugContext::Construct();
if (Settings::values.pica_debugging) {
Pica::g_debug_context = Pica::DebugContext::Construct();
} else {
Pica::g_debug_context.reset();
}
setAcceptDrops(true);
ui->setupUi(this);
statusBar()->hide();
@ -706,8 +710,12 @@ void GMainWindow::InitializeWidgets() {
}
void GMainWindow::InitializeDebugWidgets() {
connect(ui->action_Create_Pica_Surface_Viewer, &QAction::triggered, this,
&GMainWindow::OnCreateGraphicsSurfaceViewer);
if (Pica::g_debug_context) {
connect(ui->action_Create_Pica_Surface_Viewer, &QAction::triggered, this,
&GMainWindow::OnCreateGraphicsSurfaceViewer);
} else {
ui->action_Create_Pica_Surface_Viewer->setEnabled(false);
}
QMenu* debug_menu = ui->menu_View_Debugging;
@ -726,35 +734,37 @@ void GMainWindow::InitializeDebugWidgets() {
connect(this, &GMainWindow::EmulationStopping, registersWidget,
&RegistersWidget::OnEmulationStopping);
graphicsWidget = new GPUCommandStreamWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsWidget);
graphicsWidget->hide();
debug_menu->addAction(graphicsWidget->toggleViewAction());
if (Pica::g_debug_context) {
graphicsWidget = new GPUCommandStreamWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsWidget);
graphicsWidget->hide();
debug_menu->addAction(graphicsWidget->toggleViewAction());
graphicsCommandsWidget = new GPUCommandListWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
graphicsCommandsWidget->hide();
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
graphicsCommandsWidget = new GPUCommandListWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
graphicsCommandsWidget->hide();
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
graphicsBreakpointsWidget = new GraphicsBreakPointsWidget(Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsBreakpointsWidget);
graphicsBreakpointsWidget->hide();
debug_menu->addAction(graphicsBreakpointsWidget->toggleViewAction());
graphicsBreakpointsWidget = new GraphicsBreakPointsWidget(Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsBreakpointsWidget);
graphicsBreakpointsWidget->hide();
debug_menu->addAction(graphicsBreakpointsWidget->toggleViewAction());
graphicsVertexShaderWidget =
new GraphicsVertexShaderWidget(system, Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsVertexShaderWidget);
graphicsVertexShaderWidget->hide();
debug_menu->addAction(graphicsVertexShaderWidget->toggleViewAction());
graphicsVertexShaderWidget =
new GraphicsVertexShaderWidget(system, Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsVertexShaderWidget);
graphicsVertexShaderWidget->hide();
debug_menu->addAction(graphicsVertexShaderWidget->toggleViewAction());
graphicsTracingWidget = new GraphicsTracingWidget(system, Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsTracingWidget);
graphicsTracingWidget->hide();
debug_menu->addAction(graphicsTracingWidget->toggleViewAction());
connect(this, &GMainWindow::EmulationStarting, graphicsTracingWidget,
&GraphicsTracingWidget::OnEmulationStarting);
connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget,
&GraphicsTracingWidget::OnEmulationStopping);
graphicsTracingWidget = new GraphicsTracingWidget(system, Pica::g_debug_context, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsTracingWidget);
graphicsTracingWidget->hide();
debug_menu->addAction(graphicsTracingWidget->toggleViewAction());
connect(this, &GMainWindow::EmulationStarting, graphicsTracingWidget,
&GraphicsTracingWidget::OnEmulationStarting);
connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget,
&GraphicsTracingWidget::OnEmulationStopping);
}
waitTreeWidget = new WaitTreeWidget(system, this);
addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
@ -1553,7 +1563,7 @@ void GMainWindow::BootGame(const QString& filename) {
}
// Register debug widgets
if (graphicsWidget->isVisible()) {
if (graphicsWidget && graphicsWidget->isVisible()) {
graphicsWidget->Register();
}
@ -1638,10 +1648,12 @@ void GMainWindow::ShutdownGame() {
// breakpoint after (or before) RequestStop() is called, the emulation would never be able
// to continue out to the main loop and terminate. Thus wait() would hang forever.
// TODO(bunnei): This function is not thread safe, but it's being used as if it were
Pica::g_debug_context->ClearBreakpoints();
if (Pica::g_debug_context) {
Pica::g_debug_context->ClearBreakpoints();
}
// Unregister debug widgets
if (graphicsWidget->isVisible()) {
if (graphicsWidget && graphicsWidget->isVisible()) {
graphicsWidget->Unregister();
}

View File

@ -411,19 +411,19 @@ private:
std::vector<QString> physical_devices;
// Debugger panes
ProfilerWidget* profilerWidget;
ProfilerWidget* profilerWidget{};
#if MICROPROFILE_ENABLED
MicroProfileDialog* microProfileDialog;
MicroProfileDialog* microProfileDialog{};
#endif
RegistersWidget* registersWidget;
GPUCommandStreamWidget* graphicsWidget;
GPUCommandListWidget* graphicsCommandsWidget;
GraphicsBreakPointsWidget* graphicsBreakpointsWidget;
GraphicsVertexShaderWidget* graphicsVertexShaderWidget;
GraphicsTracingWidget* graphicsTracingWidget;
IPCRecorderWidget* ipcRecorderWidget;
LLEServiceModulesWidget* lleServiceModulesWidget;
WaitTreeWidget* waitTreeWidget;
RegistersWidget* registersWidget{};
GPUCommandStreamWidget* graphicsWidget{};
GPUCommandListWidget* graphicsCommandsWidget{};
GraphicsBreakPointsWidget* graphicsBreakpointsWidget{};
GraphicsVertexShaderWidget* graphicsVertexShaderWidget{};
GraphicsTracingWidget* graphicsTracingWidget{};
IPCRecorderWidget* ipcRecorderWidget{};
LLEServiceModulesWidget* lleServiceModulesWidget{};
WaitTreeWidget* waitTreeWidget{};
QAction* actions_recent_files[max_recent_files_item];
std::array<QAction*, Core::SaveStateSlotCount> actions_load_state;

View File

@ -513,6 +513,7 @@ void QtConfig::ReadDebuggingValues() {
ReadBasicSetting(Settings::values.use_gdbstub);
ReadBasicSetting(Settings::values.gdbstub_port);
ReadBasicSetting(Settings::values.renderer_debug);
ReadBasicSetting(Settings::values.pica_debugging);
ReadBasicSetting(Settings::values.dump_command_buffers);
ReadBasicSetting(Settings::values.instant_debug_log);
ReadBasicSetting(Settings::values.enable_rpc_server);
@ -1103,6 +1104,7 @@ void QtConfig::SaveDebuggingValues() {
WriteBasicSetting(Settings::values.use_gdbstub);
WriteBasicSetting(Settings::values.gdbstub_port);
WriteBasicSetting(Settings::values.renderer_debug);
WriteBasicSetting(Settings::values.pica_debugging);
WriteBasicSetting(Settings::values.instant_debug_log);
WriteBasicSetting(Settings::values.enable_rpc_server);
WriteBasicSetting(Settings::values.toggle_unique_data_console_type);

View File

@ -82,8 +82,14 @@ ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent)
});
#endif
connect(ui->toggle_pica_debugging, &QCheckBox::clicked, this, [this](bool checked) {
QMessageBox::information(this, tr("Relaunch Required"),
tr("Please relaunch Azahar for this setting to take effect."));
});
ui->toggle_cpu_jit->setEnabled(!is_powered_on);
ui->toggle_renderer_debug->setEnabled(!is_powered_on);
ui->toggle_pica_debugging->setEnabled(!is_powered_on);
ui->toggle_dump_command_buffers->setEnabled(!is_powered_on);
ui->enable_rpc_server->setEnabled(!is_powered_on);
ui->toggle_unique_data_console_type->setEnabled(!is_powered_on);
@ -135,6 +141,7 @@ void ConfigureDebug::SetConfiguration() {
Settings::values.break_on_unmapped_memory_access.GetValue());
ui->toggle_renderer_debug->setChecked(Settings::values.renderer_debug.GetValue());
ui->toggle_pica_debugging->setChecked(Settings::values.pica_debugging.GetValue());
ui->toggle_dump_command_buffers->setChecked(Settings::values.dump_command_buffers.GetValue());
if (!Settings::IsConfiguringGlobal()) {
@ -181,6 +188,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.break_on_unmapped_memory_access =
ui->break_on_unmapped_memory_access->isChecked();
Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked();
Settings::values.pica_debugging = ui->toggle_pica_debugging->isChecked();
Settings::values.dump_command_buffers = ui->toggle_dump_command_buffers->isChecked();
Settings::values.instant_debug_log = ui->instant_debug_log->isChecked();

View File

@ -250,7 +250,14 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="5" column="0">
<widget class="QCheckBox" name="toggle_pica_debugging">
<property name="text">
<string>Enable PICA200 debugging</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="toggle_dump_command_buffers">
<property name="text">
<string>Dump command buffers</string>

View File

@ -96,6 +96,7 @@ void LogSettings() {
log_setting("Renderer_SpirvShaderGen", values.spirv_shader_gen.GetValue());
log_setting("Renderer_DisableSpirvOptimizer", values.disable_spirv_optimizer.GetValue());
log_setting("Renderer_Debug", values.renderer_debug.GetValue());
log_setting("Renderer_PicaDebugging", values.pica_debugging.GetValue());
log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue());
log_setting("Renderer_ShadersAccurateMul", values.shaders_accurate_mul.GetValue());
log_setting("Renderer_UseShaderJit", values.use_shader_jit.GetValue());

View File

@ -527,6 +527,7 @@ struct Values {
SwitchableSetting<u32> physical_device{0, Keys::physical_device};
Setting<bool> use_gles{false, Keys::use_gles};
Setting<bool> renderer_debug{false, Keys::renderer_debug};
Setting<bool> pica_debugging{false, Keys::pica_debugging};
Setting<bool> dump_command_buffers{false, Keys::dump_command_buffers};
SwitchableSetting<bool> spirv_shader_gen{true, Keys::spirv_shader_gen};
SwitchableSetting<bool> disable_spirv_optimizer{true, Keys::disable_spirv_optimizer};

View File

@ -371,10 +371,6 @@ const Pica::PicaCore& GPU::PicaCore() const {
return impl->pica;
}
Pica::DebugContext& GPU::DebugContext() {
return *Pica::g_debug_context;
}
GraphicsDebugger& GPU::Debugger() {
return impl->gpu_debugger;
}

View File

@ -84,9 +84,6 @@ public:
/// Returns an immutable reference to the PICA GPU.
[[nodiscard]] const Pica::PicaCore& PicaCore() const;
/// Returns a mutable reference to the pica debugging context.
[[nodiscard]] Pica::DebugContext& DebugContext();
/// Returns a mutable reference to the GSP command debugger.
[[nodiscard]] GraphicsDebugger& Debugger();