From 8362b8e43b0dfe5a299d552f85106057a51e414d Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 4 Oct 2019 15:00:32 +1000 Subject: [PATCH] UI: Beginning of customizable settings, debug menu --- src/core/core.vcxproj | 2 ++ src/core/core.vcxproj.filters | 2 ++ src/core/gpu.cpp | 18 ++++++++---- src/core/gpu.h | 42 +++++++++++++++++++--------- src/core/gpu_hw_opengl.cpp | 46 ++++++++++++++----------------- src/core/gpu_hw_opengl.h | 4 +-- src/core/host_interface.cpp | 4 ++- src/core/settings.cpp | 3 ++ src/core/settings.h | 18 ++++++++++++ src/core/system.cpp | 13 +++++---- src/core/system.h | 15 +++++++--- src/duckstation/sdl_interface.cpp | 46 ++++++++++++++++++++++++++++++- src/duckstation/sdl_interface.h | 3 ++ 13 files changed, 158 insertions(+), 58 deletions(-) create mode 100644 src/core/settings.cpp create mode 100644 src/core/settings.h diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 74a866a63..cb0e1ac12 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -51,6 +51,7 @@ + @@ -75,6 +76,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 67d1d3705..4ac36b39f 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -20,6 +20,7 @@ + @@ -45,6 +46,7 @@ + diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 0c3b05c30..87d896d73 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -6,10 +6,9 @@ #include "stb_image_write.h" #include "system.h" #include "timers.h" +#include Log_SetChannel(GPU); -bool GPU::DUMP_CPU_TO_VRAM_COPIES = false; -bool GPU::DUMP_VRAM_TO_CPU_COPIES = false; static u32 s_cpu_to_vram_dump_id = 1; static u32 s_vram_to_cpu_dump_id = 1; @@ -129,7 +128,16 @@ bool GPU::DoState(StateWrapper& sw) return !sw.HasError(); } -void GPU::RenderUI() {} +void GPU::RenderStatistics() {} + +void GPU::RenderDebugMenu() +{ + 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() { @@ -678,7 +686,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand() return true; } - if (DUMP_CPU_TO_VRAM_COPIES) + if (m_debug_options.dump_cpu_to_vram_copies) { DumpVRAMToFile(SmallString::FromFormat("cpu_to_vram_copy_%u.png", s_cpu_to_vram_dump_id++), copy_width, copy_height, sizeof(u16) * copy_width, &m_GP0_command[3], true); @@ -718,7 +726,7 @@ bool GPU::HandleCopyRectangleVRAMToCPUCommand() for (const u32 bits : temp) m_GPUREAD_buffer.push_back(bits); - if (DUMP_VRAM_TO_CPU_COPIES) + if (m_debug_options.dump_vram_to_cpu_copies) { DumpVRAMToFile(SmallString::FromFormat("vram_to_cpu_copy_%u.png", s_cpu_to_vram_dump_id++), width, height, sizeof(u16) * width, temp.data(), true); diff --git a/src/core/gpu.h b/src/core/gpu.h index 472241c33..67544e8d9 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -16,13 +16,33 @@ class Timers; class GPU { public: + static constexpr float DISPLAY_ASPECT_RATIO = 4.0f / 3.0f; + enum : u32 + { + VRAM_WIDTH = 1024, + VRAM_HEIGHT = 512, + VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16), + TEXTURE_PAGE_WIDTH = 256, + TEXTURE_PAGE_HEIGHT = 256, + DOT_TIMER_INDEX = 0, + HBLANK_TIMER_INDEX = 1 + }; + GPU(); virtual ~GPU(); virtual bool Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers); virtual void Reset(); virtual bool DoState(StateWrapper& sw); - virtual void RenderUI(); + + // Render statistics debug window. + virtual void RenderStatistics(); + + // Manipulating debug options. + virtual void RenderDebugMenu(); + + // Called when settings change. + virtual void UpdateSettings(); u32 ReadRegister(u32 offset); void WriteRegister(u32 offset, u32 value); @@ -37,15 +57,6 @@ public: void Execute(TickCount ticks); protected: - static constexpr float DISPLAY_ASPECT_RATIO = 4.0f / 3.0f; - static constexpr u32 VRAM_WIDTH = 1024; - static constexpr u32 VRAM_HEIGHT = 512; - static constexpr u32 VRAM_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u16); - static constexpr u32 TEXTURE_PAGE_WIDTH = 256; - static constexpr u32 TEXTURE_PAGE_HEIGHT = 256; - static constexpr u32 DOT_TIMER_INDEX = 0; - static constexpr u32 HBLANK_TIMER_INDEX = 1; - static constexpr s32 S11ToS32(u32 value) { if (value & (UINT16_C(1) << 10)) @@ -156,6 +167,13 @@ protected: s32 y() const { return S11ToS32(y_s11); } }; + struct DebugOptions + { + bool show_vram; + bool dump_cpu_to_vram_copies; + bool dump_vram_to_cpu_copies; + }; + void SoftReset(); // Sets dots per scanline @@ -331,7 +349,5 @@ protected: std::vector m_GP0_command; std::deque m_GPUREAD_buffer; - // debug options - static bool DUMP_CPU_TO_VRAM_COPIES; - static bool DUMP_VRAM_TO_CPU_COPIES; + DebugOptions m_debug_options = {}; }; diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index eaab29c70..897e40fb4 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -35,9 +35,9 @@ void GPU_HW_OpenGL::Reset() ClearFramebuffer(); } -void GPU_HW_OpenGL::RenderUI() +void GPU_HW_OpenGL::RenderStatistics() { - GPU_HW::RenderUI(); + GPU_HW::RenderStatistics(); ImGui::SetNextWindowSize(ImVec2(300.0f, 130.0f), ImGuiCond_Once); @@ -48,7 +48,7 @@ void GPU_HW_OpenGL::RenderUI() m_stats = {}; } - if (ImGui::Begin("GL Render Statistics")) + if (ImGui::Begin("GPU Render Statistics")) { ImGui::Columns(2); ImGui::SetColumnWidth(0, 200.0f); @@ -72,33 +72,27 @@ void GPU_HW_OpenGL::RenderUI() ImGui::NextColumn(); ImGui::Text("%s", is_null_frame ? "Yes" : "No"); ImGui::NextColumn(); - - ImGui::Columns(1); - - ImGui::Checkbox("Show VRAM##gpu_gl_show_vram", &m_show_vram); - - static constexpr std::array internal_resolution_items = { - {"1x Internal Resolution", "2x Internal Resolution", "3x Internal Resolution", "4x Internal Resolution", - "5x Internal Resolution", "6x Internal Resolution", "7x Internal Resolution", "8x Internal Resolution", - "9x Internal Resolution", "10x Internal Resolution", "11x Internal Resolution", "12x Internal Resolution", - "13x Internal Resolution", "14x Internal Resolution", "15x Internal Resolution", "16x Internal Resolution"}}; - - int internal_resolution_item = - std::clamp(static_cast(m_resolution_scale) - 1, 0, static_cast(internal_resolution_items.size())); - if (ImGui::Combo("##gpu_internal_resolution", &internal_resolution_item, internal_resolution_items.data(), - static_cast(internal_resolution_items.size()))) - { - m_resolution_scale = static_cast(internal_resolution_item + 1); - m_system->GetHostInterface()->AddOSDMessage( - TinyString::FromFormat("Internal resolution changed to %ux, recompiling programs", m_resolution_scale)); - CreateFramebuffer(); - CompilePrograms(); - } } ImGui::End(); } +void GPU_HW_OpenGL::UpdateSettings() +{ + GPU_HW::UpdateSettings(); + + if (m_resolution_scale != m_system->GetSettings().gpu_resolution_scale) + { + m_resolution_scale = m_system->GetSettings().gpu_resolution_scale; + CreateFramebuffer(); + CompilePrograms(); + + m_system->GetHostInterface()->AddOSDMessage(TinyString::FromFormat("Changed internal resolution to %ux (%ux%u)", + m_resolution_scale, m_vram_texture->GetWidth(), + m_vram_texture->GetHeight())); + } +} + void GPU_HW_OpenGL::InvalidateVRAMReadCache() { m_vram_read_texture_dirty = true; @@ -357,7 +351,7 @@ void GPU_HW_OpenGL::UpdateDisplay() const u32 texture_height = m_vram_texture->GetHeight(); // TODO: 24-bit support. - if (m_show_vram) + if (m_debug_options.show_vram) { m_system->GetHostInterface()->SetDisplayTexture(m_vram_texture.get(), 0, 0, texture_width, texture_height, 1.0f); } diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h index 3efde427f..5869faa08 100644 --- a/src/core/gpu_hw_opengl.h +++ b/src/core/gpu_hw_opengl.h @@ -15,7 +15,8 @@ public: bool Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, Timers* timers) override; void Reset() override; - void RenderUI() override; + void RenderStatistics() override; + void UpdateSettings() override; protected: void UpdateDisplay() override; @@ -73,5 +74,4 @@ private: GLStats m_stats = {}; GLStats m_last_stats = {}; - bool m_show_vram = false; }; diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 7330cae07..fcbec0e90 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -10,7 +10,9 @@ HostInterface::~HostInterface() = default; bool HostInterface::InitializeSystem(const char* filename, const char* exp1_filename) { - m_system = std::make_unique(this); + Settings settings; + + m_system = std::make_unique(this, settings); if (!m_system->Initialize()) { m_system.reset(); diff --git a/src/core/settings.cpp b/src/core/settings.cpp new file mode 100644 index 000000000..96aa9b689 --- /dev/null +++ b/src/core/settings.cpp @@ -0,0 +1,3 @@ +#include "settings.h" + +Settings::Settings() = default; \ No newline at end of file diff --git a/src/core/settings.h b/src/core/settings.h new file mode 100644 index 000000000..4b662d32f --- /dev/null +++ b/src/core/settings.h @@ -0,0 +1,18 @@ +#pragma once +#include "types.h" + +enum class GPUBackend +{ + OpenGL +}; + +struct Settings +{ + Settings(); + + GPUBackend gpu_backend = GPUBackend::OpenGL; + u32 gpu_resolution_scale = 1; + + // TODO: Controllers, memory cards, etc. +}; + diff --git a/src/core/system.cpp b/src/core/system.cpp index 760ad68c0..7727378f7 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -15,7 +15,8 @@ #include Log_SetChannel(System); -System::System(HostInterface* host_interface) : m_host_interface(host_interface) +System::System(HostInterface* host_interface, const Settings& settings) + : m_host_interface(host_interface), m_settings(settings) { m_cpu = std::make_unique(); m_bus = std::make_unique(); @@ -32,6 +33,11 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface) System::~System() = default; +void System::UpdateSettings() +{ + m_gpu->UpdateSettings(); +} + bool System::Initialize() { if (!m_cpu->Initialize(m_bus.get())) @@ -145,11 +151,6 @@ void System::RunFrame() } } -void System::RenderUI() -{ - m_gpu->RenderUI(); -} - bool System::LoadEXE(const char* filename) { #pragma pack(push, 1) diff --git a/src/core/system.h b/src/core/system.h index afb5f6228..399257410 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -1,4 +1,5 @@ #pragma once +#include "settings.h" #include "types.h" #include @@ -7,8 +8,7 @@ class StateWrapper; class HostInterface; -namespace CPU -{ +namespace CPU { class Core; } @@ -26,16 +26,22 @@ class MDEC; class System { public: - System(HostInterface* host_interface); + System(HostInterface* host_interface, const Settings& settings); ~System(); HostInterface* GetHostInterface() const { return m_host_interface; } + CPU::Core* GetCPU() const { return m_cpu.get(); } + Bus* GetBus() const { return m_bus.get(); } + GPU* GetGPU() const { return m_gpu.get(); } u32 GetFrameNumber() const { return m_frame_number; } u32 GetInternalFrameNumber() const { return m_internal_frame_number; } void IncrementFrameNumber() { m_frame_number++; } void IncrementInternalFrameNumber() { m_internal_frame_number++; } + Settings& GetSettings() { return m_settings; } + void UpdateSettings(); + bool Initialize(); void Reset(); @@ -43,7 +49,6 @@ public: bool SaveState(ByteStream* state); void RunFrame(); - void RenderUI(); bool LoadEXE(const char* filename); bool SetExpansionROM(const char* filename); @@ -74,4 +79,6 @@ private: std::unique_ptr m_mdec; u32 m_frame_number = 1; u32 m_internal_frame_number = 1; + + Settings m_settings; }; diff --git a/src/duckstation/sdl_interface.cpp b/src/duckstation/sdl_interface.cpp index af86718c8..284367af1 100644 --- a/src/duckstation/sdl_interface.cpp +++ b/src/duckstation/sdl_interface.cpp @@ -3,6 +3,7 @@ #include "YBaseLib/Error.h" #include "YBaseLib/Log.h" #include "core/digital_controller.h" +#include "core/gpu.h" #include "core/memory_card.h" #include "core/system.h" #include "icon.h" @@ -458,7 +459,8 @@ void SDLInterface::RenderImGui() { RenderMainMenuBar(); - m_system->RenderUI(); + if (m_show_gpu_statistics) + m_system->GetGPU()->RenderStatistics(); RenderOSDMessages(); @@ -518,6 +520,48 @@ void SDLInterface::RenderMainMenuBar() ImGui::EndMenu(); } + if (ImGui::BeginMenu("Settings")) + { + if (ImGui::BeginMenu("GPU")) + { + if (ImGui::BeginMenu("Internal Resolution")) + { + const u32 current_internal_resolution = m_system->GetSettings().gpu_resolution_scale; + for (u32 scale = 1; scale <= 16; scale++) + { + bool selected = current_internal_resolution == scale; + if (ImGui::MenuItem( + TinyString::FromFormat("%ux (%ux%u)", scale, scale * GPU::VRAM_WIDTH, scale * GPU::VRAM_HEIGHT), + nullptr, &selected)) + { + m_system->GetSettings().gpu_resolution_scale = scale; + m_system->UpdateSettings(); + } + } + + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Debug")) + { + if (ImGui::BeginMenu("GPU")) + { + ImGui::MenuItem("Show Statistics", nullptr, &m_show_gpu_statistics); + ImGui::Separator(); + + m_system->GetGPU()->RenderDebugMenu(); + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + ImGui::SetCursorPosX(ImGui::GetIO().DisplaySize.x - 170.0f); ImGui::Text("FPS: %.2f", m_fps); diff --git a/src/duckstation/sdl_interface.h b/src/duckstation/sdl_interface.h index 5e3adf3f6..aebdc0a3f 100644 --- a/src/duckstation/sdl_interface.h +++ b/src/duckstation/sdl_interface.h @@ -87,4 +87,7 @@ private: u32 m_last_frame_number = 0; u32 m_last_internal_frame_number = 0; Timer m_fps_timer; + + // UI options + bool m_show_gpu_statistics = false; };