Refactoring settings/support changing GPU renderer at runtime
This commit is contained in:
parent
ca48b21ffc
commit
9b56499afa
|
@ -49,6 +49,9 @@ public:
|
||||||
void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF));
|
void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF));
|
||||||
void SetExpansionROM(std::vector<u8> data);
|
void SetExpansionROM(std::vector<u8> data);
|
||||||
|
|
||||||
|
// changing interfaces
|
||||||
|
void SetGPU(GPU* gpu) { m_gpu = gpu; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
|
|
|
@ -1178,11 +1178,8 @@ void CDROM::DrawDebugWindow()
|
||||||
static const ImVec4 active_color{1.0f, 1.0f, 1.0f, 1.0f};
|
static const ImVec4 active_color{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
static const ImVec4 inactive_color{0.4f, 0.4f, 0.4f, 1.0f};
|
static const ImVec4 inactive_color{0.4f, 0.4f, 0.4f, 1.0f};
|
||||||
|
|
||||||
if (!m_show_cdrom_state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(800, 500), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(800, 500), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("CDROM State", &m_show_cdrom_state))
|
if (!ImGui::Begin("CDROM State", &m_system->GetSettings().debugging.show_cdrom_state))
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
|
@ -1320,8 +1317,3 @@ void CDROM::DrawDebugWindow()
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::DrawDebugMenu()
|
|
||||||
{
|
|
||||||
ImGui::MenuItem("CDROM", nullptr, &m_show_cdrom_state);
|
|
||||||
}
|
|
||||||
|
|
|
@ -49,9 +49,6 @@ public:
|
||||||
// Render statistics debug window.
|
// Render statistics debug window.
|
||||||
void DrawDebugWindow();
|
void DrawDebugWindow();
|
||||||
|
|
||||||
// Manipulating debug options.
|
|
||||||
void DrawDebugMenu();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr u32 PARAM_FIFO_SIZE = 16;
|
static constexpr u32 PARAM_FIFO_SIZE = 16;
|
||||||
static constexpr u32 RESPONSE_FIFO_SIZE = 16;
|
static constexpr u32 RESPONSE_FIFO_SIZE = 16;
|
||||||
|
@ -226,6 +223,4 @@ private:
|
||||||
InlineFIFOQueue<u8, RESPONSE_FIFO_SIZE> m_response_fifo;
|
InlineFIFOQueue<u8, RESPONSE_FIFO_SIZE> m_response_fifo;
|
||||||
HeapFIFOQueue<u8, DATA_FIFO_SIZE> m_data_fifo;
|
HeapFIFOQueue<u8, DATA_FIFO_SIZE> m_data_fifo;
|
||||||
std::vector<u8> m_sector_buffer;
|
std::vector<u8> m_sector_buffer;
|
||||||
|
|
||||||
bool m_show_cdrom_state = false;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,9 @@ public:
|
||||||
|
|
||||||
void SetRequest(Channel channel, bool request);
|
void SetRequest(Channel channel, bool request);
|
||||||
|
|
||||||
|
// changing interfaces
|
||||||
|
void SetGPU(GPU* gpu) { m_gpu = gpu; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr PhysicalMemoryAddress ADDRESS_MASK = UINT32_C(0x00FFFFFF);
|
static constexpr PhysicalMemoryAddress ADDRESS_MASK = UINT32_C(0x00FFFFFF);
|
||||||
static constexpr u32 TRANSFER_TICKS = 10;
|
static constexpr u32 TRANSFER_TICKS = 10;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "YBaseLib/Log.h"
|
#include "YBaseLib/Log.h"
|
||||||
#include "common/state_wrapper.h"
|
#include "common/state_wrapper.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
#include "host_interface.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
#include "stb_image_write.h"
|
#include "stb_image_write.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
@ -25,6 +26,17 @@ bool GPU::Initialize(System* system, DMA* dma, InterruptController* interrupt_co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU::UpdateResolutionScale()
|
||||||
|
{
|
||||||
|
const u32 new_scale = std::min(m_system->GetSettings().gpu_resolution_scale, m_max_resolution_scale);
|
||||||
|
if (m_resolution_scale == new_scale)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_resolution_scale = new_scale;
|
||||||
|
m_system->GetHostInterface()->AddOSDMessage(TinyString::FromFormat(
|
||||||
|
"Changed internal resolution to %ux (%ux%u)", m_resolution_scale, VRAM_WIDTH * new_scale, VRAM_HEIGHT * new_scale));
|
||||||
|
}
|
||||||
|
|
||||||
void GPU::Reset()
|
void GPU::Reset()
|
||||||
{
|
{
|
||||||
SoftReset();
|
SoftReset();
|
||||||
|
@ -144,8 +156,6 @@ void GPU::ResetGraphicsAPIState() {}
|
||||||
|
|
||||||
void GPU::RestoreGraphicsAPIState() {}
|
void GPU::RestoreGraphicsAPIState() {}
|
||||||
|
|
||||||
void GPU::UpdateSettings() {}
|
|
||||||
|
|
||||||
void GPU::UpdateGPUSTAT()
|
void GPU::UpdateGPUSTAT()
|
||||||
{
|
{
|
||||||
m_GPUSTAT.ready_to_send_vram = !m_GPUREAD_buffer.empty();
|
m_GPUSTAT.ready_to_send_vram = !m_GPUREAD_buffer.empty();
|
||||||
|
@ -762,29 +772,10 @@ 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);
|
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()
|
void GPU::DrawDebugStateWindow()
|
||||||
{
|
{
|
||||||
ImGui::SetNextWindowSize(ImVec2(450, 550), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(450, 550), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("GPU State", &m_debug_options.show_state))
|
if (!ImGui::Begin("GPU State", &m_system->GetSettings().debugging.show_gpu_state))
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
|
@ -827,4 +818,8 @@ void GPU::DrawDebugStateWindow()
|
||||||
ImGui::Text("Interrupt Request: %s", m_GPUSTAT.interrupt_request ? "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");
|
ImGui::Text("DMA Request: %s", m_GPUSTAT.dma_data_request ? "Yes" : "No");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU::DrawRendererStatsWindow() {}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class StateWrapper;
|
class StateWrapper;
|
||||||
|
@ -40,14 +41,10 @@ public:
|
||||||
virtual void RestoreGraphicsAPIState();
|
virtual void RestoreGraphicsAPIState();
|
||||||
|
|
||||||
// Render statistics debug window.
|
// Render statistics debug window.
|
||||||
virtual void DrawDebugWindows();
|
void DrawDebugStateWindow();
|
||||||
|
virtual void DrawRendererStatsWindow();
|
||||||
// Manipulating debug options.
|
|
||||||
virtual void DrawDebugMenu();
|
|
||||||
|
|
||||||
// Called when settings change.
|
|
||||||
virtual void UpdateSettings();
|
|
||||||
|
|
||||||
|
// MMIO access
|
||||||
u32 ReadRegister(u32 offset);
|
u32 ReadRegister(u32 offset);
|
||||||
void WriteRegister(u32 offset, u32 value);
|
void WriteRegister(u32 offset, u32 value);
|
||||||
|
|
||||||
|
@ -55,13 +52,22 @@ public:
|
||||||
void DMARead(u32* words, u32 word_count);
|
void DMARead(u32* words, u32 word_count);
|
||||||
void DMAWrite(const u32* words, u32 word_count);
|
void DMAWrite(const u32* words, u32 word_count);
|
||||||
|
|
||||||
|
// Resolution scaling.
|
||||||
|
u32 GetResolutionScale() const { return m_resolution_scale; }
|
||||||
|
u32 GetMaxResolutionScale() const { return m_max_resolution_scale; }
|
||||||
|
virtual void UpdateResolutionScale();
|
||||||
|
|
||||||
|
// Ticks for hblank/vblank.
|
||||||
|
void Execute(TickCount ticks);
|
||||||
|
|
||||||
// gpu_hw_opengl.cpp
|
// gpu_hw_opengl.cpp
|
||||||
static std::unique_ptr<GPU> CreateHardwareOpenGLRenderer();
|
static std::unique_ptr<GPU> CreateHardwareOpenGLRenderer();
|
||||||
|
|
||||||
void Execute(TickCount ticks);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Helper/format conversion functions.
|
// Helper/format conversion functions.
|
||||||
|
static constexpr u8 Convert5To8(u8 x5) { return (x5 << 3) | (x5 & 7); }
|
||||||
|
static constexpr u8 Convert8To5(u8 x8) { return (x8 >> 3); }
|
||||||
|
|
||||||
static constexpr u32 RGBA5551ToRGBA8888(u16 color)
|
static constexpr u32 RGBA5551ToRGBA8888(u16 color)
|
||||||
{
|
{
|
||||||
u8 r = Truncate8(color & 31);
|
u8 r = Truncate8(color & 31);
|
||||||
|
@ -88,6 +94,21 @@ protected:
|
||||||
return r | (g << 5) | (b << 10) | (a << 15);
|
return r | (g << 5) | (b << 10) | (a << 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr std::tuple<u8, u8> UnpackTexcoord(u16 texcoord)
|
||||||
|
{
|
||||||
|
return std::make_tuple(static_cast<u8>(texcoord), static_cast<u8>(texcoord >> 8));
|
||||||
|
}
|
||||||
|
static constexpr u16 PackTexcoord(u8 x, u8 y) { return ZeroExtend16(x) | (ZeroExtend16(y) << 8); }
|
||||||
|
|
||||||
|
static constexpr std::tuple<u8, u8, u8> UnpackColorRGB24(u32 rgb24)
|
||||||
|
{
|
||||||
|
return std::make_tuple(static_cast<u8>(rgb24), static_cast<u8>(rgb24 >> 8), static_cast<u8>(rgb24 >> 16));
|
||||||
|
}
|
||||||
|
static constexpr u32 PackColorRGB24(u8 r, u8 g, u8 b)
|
||||||
|
{
|
||||||
|
return ZeroExtend32(r) | (ZeroExtend32(g) << 8) | (ZeroExtend32(b) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
static bool DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer,
|
static bool DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride, const void* buffer,
|
||||||
bool remove_alpha);
|
bool remove_alpha);
|
||||||
|
|
||||||
|
@ -160,12 +181,49 @@ protected:
|
||||||
BitField<u32, s32, 16, 12> y;
|
BitField<u32, s32, 16, 12> y;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DebugOptions
|
union VRAMPixel
|
||||||
{
|
{
|
||||||
bool show_state = false;
|
u16 bits;
|
||||||
bool show_vram = false;
|
|
||||||
bool dump_cpu_to_vram_copies = false;
|
BitField<u16, u8, 0, 5> r;
|
||||||
bool dump_vram_to_cpu_copies = false;
|
BitField<u16, u8, 5, 5> g;
|
||||||
|
BitField<u16, u8, 10, 5> b;
|
||||||
|
BitField<u16, bool, 15, 1> c;
|
||||||
|
|
||||||
|
u8 GetR8() const { return Convert5To8(r); }
|
||||||
|
u8 GetG8() const { return Convert5To8(g); }
|
||||||
|
u8 GetB8() const { return Convert5To8(b); }
|
||||||
|
|
||||||
|
void Set(u8 r_, u8 g_, u8 b_, bool c_ = false)
|
||||||
|
{
|
||||||
|
bits = (ZeroExtend16(r_)) | (ZeroExtend16(g_) << 5) | (ZeroExtend16(b_) << 10) | (static_cast<u16>(c_) << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClampAndSet(u8 r_, u8 g_, u8 b_, bool c_ = false)
|
||||||
|
{
|
||||||
|
Set(std::min<u8>(r_, 0x1F), std::min<u8>(g_, 0x1F), std::min<u8>(b_, 0x1F), c_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetRGB24(u32 rgb24, bool c_ = false)
|
||||||
|
{
|
||||||
|
bits = Truncate16(((rgb24 >> 3) & 0x1F) | (((rgb24 >> 11) & 0x1F) << 5) | (((rgb24 >> 19) & 0x1F) << 10)) |
|
||||||
|
(static_cast<u16>(c_) << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetRGB24(u8 r8, u8 g8, u8 b8, bool c_ = false)
|
||||||
|
{
|
||||||
|
bits = (ZeroExtend16(r8 >> 3)) | (ZeroExtend16(g8 >> 3) << 5) | (ZeroExtend16(b8 >> 3) << 10) |
|
||||||
|
(static_cast<u16>(c_) << 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ToRGB24() const
|
||||||
|
{
|
||||||
|
const u32 r_ = ZeroExtend32(r.GetValue());
|
||||||
|
const u32 g_ = ZeroExtend32(g.GetValue());
|
||||||
|
const u32 b_ = ZeroExtend32(b.GetValue());
|
||||||
|
|
||||||
|
return ((r_ << 3) | (r_ & 7)) | (((g_ << 3) | (g_ & 7)) << 8) | (((b_ << 3) | (b_ & 7)) << 16);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void SoftReset();
|
void SoftReset();
|
||||||
|
@ -194,14 +252,15 @@ protected:
|
||||||
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32* command_ptr);
|
virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32* command_ptr);
|
||||||
virtual void FlushRender();
|
virtual void FlushRender();
|
||||||
|
|
||||||
// Debugging
|
|
||||||
void DrawDebugStateWindow();
|
|
||||||
|
|
||||||
System* m_system = nullptr;
|
System* m_system = nullptr;
|
||||||
DMA* m_dma = nullptr;
|
DMA* m_dma = nullptr;
|
||||||
InterruptController* m_interrupt_controller = nullptr;
|
InterruptController* m_interrupt_controller = nullptr;
|
||||||
Timers* m_timers = nullptr;
|
Timers* m_timers = nullptr;
|
||||||
|
|
||||||
|
// Resolution scale.
|
||||||
|
u32 m_resolution_scale = 1;
|
||||||
|
u32 m_max_resolution_scale = 1;
|
||||||
|
|
||||||
union GPUSTAT
|
union GPUSTAT
|
||||||
{
|
{
|
||||||
u32 bits;
|
u32 bits;
|
||||||
|
@ -351,8 +410,6 @@ protected:
|
||||||
std::vector<u32> m_GP0_buffer;
|
std::vector<u32> m_GP0_buffer;
|
||||||
std::deque<u32> m_GPUREAD_buffer;
|
std::deque<u32> m_GPUREAD_buffer;
|
||||||
|
|
||||||
DebugOptions m_debug_options;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using GP0CommandHandler = bool (GPU::*)(const u32*&, u32);
|
using GP0CommandHandler = bool (GPU::*)(const u32*&, u32);
|
||||||
using GP0CommandHandlerTable = std::array<GP0CommandHandler, 256>;
|
using GP0CommandHandlerTable = std::array<GP0CommandHandler, 256>;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "YBaseLib/String.h"
|
#include "YBaseLib/String.h"
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
|
#include "system.h"
|
||||||
Log_SetChannel(GPU);
|
Log_SetChannel(GPU);
|
||||||
|
|
||||||
static u32 s_cpu_to_vram_dump_id = 1;
|
static u32 s_cpu_to_vram_dump_id = 1;
|
||||||
|
@ -291,7 +292,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand(const u32*& command_ptr, u32 comma
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_debug_options.dump_cpu_to_vram_copies)
|
if (m_system->GetSettings().debugging.dump_cpu_to_vram_copies)
|
||||||
{
|
{
|
||||||
DumpVRAMToFile(SmallString::FromFormat("cpu_to_vram_copy_%u.png", s_cpu_to_vram_dump_id++), copy_width, copy_height,
|
DumpVRAMToFile(SmallString::FromFormat("cpu_to_vram_copy_%u.png", s_cpu_to_vram_dump_id++), copy_width, copy_height,
|
||||||
sizeof(u16) * copy_width, &command_ptr[3], true);
|
sizeof(u16) * copy_width, &command_ptr[3], true);
|
||||||
|
@ -333,7 +334,7 @@ bool GPU::HandleCopyRectangleVRAMToCPUCommand(const u32*& command_ptr, u32 comma
|
||||||
for (const u32 bits : temp)
|
for (const u32 bits : temp)
|
||||||
m_GPUREAD_buffer.push_back(bits);
|
m_GPUREAD_buffer.push_back(bits);
|
||||||
|
|
||||||
if (m_debug_options.dump_vram_to_cpu_copies)
|
if (m_system->GetSettings().debugging.dump_vram_to_cpu_copies)
|
||||||
{
|
{
|
||||||
DumpVRAMToFile(SmallString::FromFormat("vram_to_cpu_copy_%u.png", s_vram_to_cpu_dump_id++), width, height,
|
DumpVRAMToFile(SmallString::FromFormat("vram_to_cpu_copy_%u.png", s_vram_to_cpu_dump_id++), width, height,
|
||||||
sizeof(u16) * width, temp.data(), true);
|
sizeof(u16) * width, temp.data(), true);
|
||||||
|
|
|
@ -46,17 +46,9 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command
|
||||||
hw_vert.texpage = texpage;
|
hw_vert.texpage = texpage;
|
||||||
|
|
||||||
if (textured)
|
if (textured)
|
||||||
{
|
|
||||||
hw_vert.texcoord = Truncate16(command_ptr[buffer_pos++]);
|
hw_vert.texcoord = Truncate16(command_ptr[buffer_pos++]);
|
||||||
// auto [u, v] = HWVertex::DecodeTexcoord(hw_vert.texcoord);
|
|
||||||
// u = (u & (~(m_render_state.texture_window_mask_x * 8))) | ((m_render_state.texture_window_offset_x &
|
|
||||||
// m_render_state.texture_window_mask_x) * 8); v = (v & (~(m_render_state.texture_window_mask_y * 8))) |
|
|
||||||
// ((m_render_state.texture_window_offset_y & m_render_state.texture_window_mask_y) * 8);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
hw_vert.texcoord = 0;
|
hw_vert.texcoord = 0;
|
||||||
}
|
|
||||||
|
|
||||||
hw_vert.padding = 0;
|
hw_vert.padding = 0;
|
||||||
|
|
||||||
|
@ -82,8 +74,7 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command
|
||||||
const VertexPosition vp{command_ptr[buffer_pos++]};
|
const VertexPosition vp{command_ptr[buffer_pos++]};
|
||||||
const s32 pos_left = vp.x;
|
const s32 pos_left = vp.x;
|
||||||
const s32 pos_top = vp.y;
|
const s32 pos_top = vp.y;
|
||||||
const auto [tex_left, tex_top] =
|
const auto [tex_left, tex_top] = UnpackTexcoord(rc.texture_enable ? Truncate16(command_ptr[buffer_pos++]) : 0);
|
||||||
HWVertex::DecodeTexcoord(rc.texture_enable ? Truncate16(command_ptr[buffer_pos++]) : 0);
|
|
||||||
s32 rectangle_width;
|
s32 rectangle_width;
|
||||||
s32 rectangle_height;
|
s32 rectangle_height;
|
||||||
switch (rc.rectangle_size)
|
switch (rc.rectangle_size)
|
||||||
|
@ -112,16 +103,12 @@ void GPU_HW::LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command
|
||||||
const u8 tex_right = static_cast<u8>(tex_left + (rectangle_width - 1));
|
const u8 tex_right = static_cast<u8>(tex_left + (rectangle_width - 1));
|
||||||
const u8 tex_bottom = static_cast<u8>(tex_top + (rectangle_height - 1));
|
const u8 tex_bottom = static_cast<u8>(tex_top + (rectangle_height - 1));
|
||||||
|
|
||||||
m_batch.vertices.push_back(
|
m_batch.vertices.push_back(HWVertex{pos_left, pos_top, color, texpage, PackTexcoord(tex_left, tex_top)});
|
||||||
HWVertex{pos_left, pos_top, color, texpage, HWVertex::EncodeTexcoord(tex_left, tex_top)});
|
|
||||||
if (restart_strip)
|
if (restart_strip)
|
||||||
m_batch.vertices.push_back(m_batch.vertices.back());
|
m_batch.vertices.push_back(m_batch.vertices.back());
|
||||||
m_batch.vertices.push_back(
|
m_batch.vertices.push_back(HWVertex{pos_right, pos_top, color, texpage, PackTexcoord(tex_right, tex_top)});
|
||||||
HWVertex{pos_right, pos_top, color, texpage, HWVertex::EncodeTexcoord(tex_right, tex_top)});
|
m_batch.vertices.push_back(HWVertex{pos_left, pos_bottom, color, texpage, PackTexcoord(tex_left, tex_bottom)});
|
||||||
m_batch.vertices.push_back(
|
m_batch.vertices.push_back(HWVertex{pos_right, pos_bottom, color, texpage, PackTexcoord(tex_right, tex_bottom)});
|
||||||
HWVertex{pos_left, pos_bottom, color, texpage, HWVertex::EncodeTexcoord(tex_left, tex_bottom)});
|
|
||||||
m_batch.vertices.push_back(
|
|
||||||
HWVertex{pos_right, pos_bottom, color, texpage, HWVertex::EncodeTexcoord(tex_right, tex_bottom)});
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -538,9 +525,9 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32
|
||||||
const u32 max_added_vertices = num_vertices + 2;
|
const u32 max_added_vertices = num_vertices + 2;
|
||||||
const bool buffer_overflow = (m_batch.vertices.size() + max_added_vertices) >= MAX_BATCH_VERTEX_COUNT;
|
const bool buffer_overflow = (m_batch.vertices.size() + max_added_vertices) >= MAX_BATCH_VERTEX_COUNT;
|
||||||
const bool rc_changed =
|
const bool rc_changed =
|
||||||
m_batch.render_command_bits != rc.bits && (m_batch.transparency_enable != rc_transparency_enable ||
|
m_batch.render_command_bits != rc.bits &&
|
||||||
m_batch.texture_enable != rc_texture_enable || m_batch.texture_blending_enable != rc_texture_blend_enable ||
|
(m_batch.transparency_enable != rc_transparency_enable || m_batch.texture_enable != rc_texture_enable ||
|
||||||
m_batch.primitive != rc_primitive);
|
m_batch.texture_blending_enable != rc_texture_blend_enable || m_batch.primitive != rc_primitive);
|
||||||
const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip);
|
const bool restart_line_strip = (rc_primitive == HWRenderBatch::Primitive::LineStrip);
|
||||||
const bool needs_flush =
|
const bool needs_flush =
|
||||||
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
|
!IsFlushed() && (m_render_state.IsTextureColorModeChanged() || m_render_state.IsTransparencyModeChanged() ||
|
||||||
|
|
|
@ -22,12 +22,6 @@ protected:
|
||||||
u32 texpage;
|
u32 texpage;
|
||||||
u16 texcoord;
|
u16 texcoord;
|
||||||
u16 padding;
|
u16 padding;
|
||||||
|
|
||||||
static constexpr std::tuple<u8, u8> DecodeTexcoord(u16 texcoord)
|
|
||||||
{
|
|
||||||
return std::make_tuple(static_cast<u8>(texcoord), static_cast<u8>(texcoord >> 8));
|
|
||||||
}
|
|
||||||
static constexpr u16 EncodeTexcoord(u8 x, u8 y) { return ZeroExtend16(x) | (ZeroExtend16(y) << 8); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HWRenderBatch
|
struct HWRenderBatch
|
||||||
|
@ -99,7 +93,6 @@ protected:
|
||||||
std::string GenerateFillFragmentShader();
|
std::string GenerateFillFragmentShader();
|
||||||
std::string GenerateDisplayFragmentShader(bool depth_24bit, bool interlaced);
|
std::string GenerateDisplayFragmentShader(bool depth_24bit, bool interlaced);
|
||||||
|
|
||||||
u32 m_resolution_scale = 1;
|
|
||||||
HWRenderBatch m_batch = {};
|
HWRenderBatch m_batch = {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -65,23 +65,18 @@ void GPU_HW_OpenGL::RestoreGraphicsAPIState()
|
||||||
glBindVertexArray(m_vao_id);
|
glBindVertexArray(m_vao_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_OpenGL::DrawDebugWindows()
|
void GPU_HW_OpenGL::UpdateResolutionScale()
|
||||||
{
|
{
|
||||||
GPU_HW::DrawDebugWindows();
|
GPU_HW::UpdateResolutionScale();
|
||||||
|
|
||||||
if (m_show_renderer_statistics)
|
CreateFramebuffer();
|
||||||
DrawRendererStatistics();
|
CompilePrograms();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_OpenGL::DrawDebugMenu()
|
void GPU_HW_OpenGL::DrawRendererStatsWindow()
|
||||||
{
|
{
|
||||||
GPU_HW::DrawDebugMenu();
|
GPU_HW::DrawRendererStatsWindow();
|
||||||
|
|
||||||
ImGui::MenuItem("GPU Renderer", nullptr, &m_show_renderer_statistics);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPU_HW_OpenGL::DrawRendererStatistics()
|
|
||||||
{
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(300.0f, 130.0f), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(300.0f, 130.0f), ImGuiCond_FirstUseEver);
|
||||||
|
|
||||||
const bool is_null_frame = m_stats.num_batches == 0;
|
const bool is_null_frame = m_stats.num_batches == 0;
|
||||||
|
@ -120,22 +115,6 @@ void GPU_HW_OpenGL::DrawRendererStatistics()
|
||||||
ImGui::End();
|
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()
|
void GPU_HW_OpenGL::InvalidateVRAMReadCache()
|
||||||
{
|
{
|
||||||
m_vram_read_texture_dirty = true;
|
m_vram_read_texture_dirty = true;
|
||||||
|
@ -401,7 +380,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
{
|
{
|
||||||
GPU_HW::UpdateDisplay();
|
GPU_HW::UpdateDisplay();
|
||||||
|
|
||||||
if (m_debug_options.show_vram)
|
if (m_system->GetSettings().debugging.show_vram)
|
||||||
{
|
{
|
||||||
m_system->GetHostInterface()->SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(),
|
m_system->GetHostInterface()->SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(),
|
||||||
m_vram_texture->GetHeight(), 1.0f);
|
m_vram_texture->GetHeight(), 1.0f);
|
||||||
|
|
|
@ -18,10 +18,9 @@ public:
|
||||||
|
|
||||||
void ResetGraphicsAPIState() override;
|
void ResetGraphicsAPIState() override;
|
||||||
void RestoreGraphicsAPIState() override;
|
void RestoreGraphicsAPIState() override;
|
||||||
|
void UpdateResolutionScale() override;
|
||||||
|
|
||||||
void DrawDebugWindows() override;
|
void DrawRendererStatsWindow() override;
|
||||||
void DrawDebugMenu() override;
|
|
||||||
void UpdateSettings() override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateDisplay() override;
|
void UpdateDisplay() override;
|
||||||
|
|
|
@ -1,20 +1,33 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
enum class GPUBackend
|
enum class GPURenderer
|
||||||
{
|
{
|
||||||
OpenGL
|
HardwareOpenGL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Settings
|
struct Settings
|
||||||
{
|
{
|
||||||
Settings();
|
Settings();
|
||||||
|
|
||||||
GPUBackend gpu_backend = GPUBackend::OpenGL;
|
GPURenderer gpu_renderer = GPURenderer::HardwareOpenGL;
|
||||||
u32 gpu_resolution_scale = 1;
|
u32 gpu_resolution_scale = 1;
|
||||||
u32 max_gpu_resolution_scale = 1;
|
u32 max_gpu_resolution_scale = 1;
|
||||||
bool gpu_vsync = true;
|
bool gpu_vsync = true;
|
||||||
|
|
||||||
|
struct DebugSettings
|
||||||
|
{
|
||||||
|
bool show_gpu_state = false;
|
||||||
|
bool show_gpu_renderer_stats = false;
|
||||||
|
bool show_vram = false;
|
||||||
|
bool dump_cpu_to_vram_copies = false;
|
||||||
|
bool dump_vram_to_cpu_copies = false;
|
||||||
|
|
||||||
|
bool show_cdrom_state = false;
|
||||||
|
bool show_spu_state = false;
|
||||||
|
bool show_timers_state = false;
|
||||||
|
bool show_mdec_state = false;
|
||||||
|
} debugging;
|
||||||
|
|
||||||
// TODO: Controllers, memory cards, etc.
|
// TODO: Controllers, memory cards, etc.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -931,16 +931,13 @@ void SPU::GenerateSample()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPU::DrawDebugWindow()
|
void SPU::DrawDebugStateWindow()
|
||||||
{
|
{
|
||||||
static const ImVec4 active_color{1.0f, 1.0f, 1.0f, 1.0f};
|
static const ImVec4 active_color{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
static const ImVec4 inactive_color{0.4f, 0.4f, 0.4f, 1.0f};
|
static const ImVec4 inactive_color{0.4f, 0.4f, 0.4f, 1.0f};
|
||||||
|
|
||||||
if (!m_show_spu_state)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("SPU State", &m_show_spu_state))
|
if (!ImGui::Begin("SPU State", &m_system->GetSettings().debugging.show_spu_state))
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
|
@ -1077,9 +1074,3 @@ void SPU::DrawDebugWindow()
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPU::DrawDebugMenu()
|
|
||||||
{
|
|
||||||
// TODO: Show RAM, etc.
|
|
||||||
ImGui::MenuItem("SPU", nullptr, &m_show_spu_state);
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,10 +32,7 @@ public:
|
||||||
void Execute(TickCount ticks);
|
void Execute(TickCount ticks);
|
||||||
|
|
||||||
// Render statistics debug window.
|
// Render statistics debug window.
|
||||||
void DrawDebugWindow();
|
void DrawDebugStateWindow();
|
||||||
|
|
||||||
// Manipulating debug options.
|
|
||||||
void DrawDebugMenu();
|
|
||||||
|
|
||||||
// External input from CD controller.
|
// External input from CD controller.
|
||||||
void AddCDAudioSample(s16 left, s16 right)
|
void AddCDAudioSample(s16 left, s16 right)
|
||||||
|
@ -277,7 +274,6 @@ private:
|
||||||
DMA* m_dma = nullptr;
|
DMA* m_dma = nullptr;
|
||||||
InterruptController* m_interrupt_controller = nullptr;
|
InterruptController* m_interrupt_controller = nullptr;
|
||||||
AudioStream* m_audio_stream = nullptr;
|
AudioStream* m_audio_stream = nullptr;
|
||||||
bool m_show_spu_state = false;
|
|
||||||
|
|
||||||
SPUCNT m_SPUCNT = {};
|
SPUCNT m_SPUCNT = {};
|
||||||
SPUSTAT m_SPUSTAT = {};
|
SPUSTAT m_SPUSTAT = {};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "YBaseLib/AutoReleasePtr.h"
|
||||||
#include "YBaseLib/Log.h"
|
#include "YBaseLib/Log.h"
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "cdrom.h"
|
#include "cdrom.h"
|
||||||
|
@ -23,8 +24,6 @@ System::System(HostInterface* host_interface, const Settings& settings)
|
||||||
m_bus = std::make_unique<Bus>();
|
m_bus = std::make_unique<Bus>();
|
||||||
m_dma = std::make_unique<DMA>();
|
m_dma = std::make_unique<DMA>();
|
||||||
m_interrupt_controller = std::make_unique<InterruptController>();
|
m_interrupt_controller = std::make_unique<InterruptController>();
|
||||||
// m_gpu = std::make_unique<GPU>();
|
|
||||||
m_gpu = GPU::CreateHardwareOpenGLRenderer();
|
|
||||||
m_cdrom = std::make_unique<CDROM>();
|
m_cdrom = std::make_unique<CDROM>();
|
||||||
m_pad = std::make_unique<Pad>();
|
m_pad = std::make_unique<Pad>();
|
||||||
m_timers = std::make_unique<Timers>();
|
m_timers = std::make_unique<Timers>();
|
||||||
|
@ -34,9 +33,31 @@ System::System(HostInterface* host_interface, const Settings& settings)
|
||||||
|
|
||||||
System::~System() = default;
|
System::~System() = default;
|
||||||
|
|
||||||
void System::UpdateSettings()
|
bool System::RecreateGPU()
|
||||||
{
|
{
|
||||||
m_gpu->UpdateSettings();
|
// save current state
|
||||||
|
AutoReleasePtr<ByteStream> state_stream = ByteStream_CreateGrowableMemoryStream();
|
||||||
|
StateWrapper sw(state_stream, StateWrapper::Mode::Write);
|
||||||
|
const bool state_valid = m_gpu->DoState(sw);
|
||||||
|
if (!state_valid)
|
||||||
|
Log_ErrorPrintf("Failed to save old GPU state when switching renderers");
|
||||||
|
|
||||||
|
// create new renderer
|
||||||
|
m_gpu.reset();
|
||||||
|
if (!CreateGPU())
|
||||||
|
{
|
||||||
|
Panic("Failed to recreate GPU");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state_valid)
|
||||||
|
{
|
||||||
|
state_stream->SeekAbsolute(0);
|
||||||
|
sw.SetMode(StateWrapper::Mode::Read);
|
||||||
|
m_gpu->DoState(sw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::Initialize()
|
bool System::Initialize()
|
||||||
|
@ -59,7 +80,7 @@ bool System::Initialize()
|
||||||
if (!m_interrupt_controller->Initialize(m_cpu.get()))
|
if (!m_interrupt_controller->Initialize(m_cpu.get()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_gpu->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_timers.get()))
|
if (!CreateGPU())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_cdrom->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_spu.get()))
|
if (!m_cdrom->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_spu.get()))
|
||||||
|
@ -80,6 +101,28 @@ bool System::Initialize()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool System::CreateGPU()
|
||||||
|
{
|
||||||
|
switch (m_settings.gpu_renderer)
|
||||||
|
{
|
||||||
|
case GPURenderer::HardwareOpenGL:
|
||||||
|
default:
|
||||||
|
m_gpu = GPU::CreateHardwareOpenGLRenderer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_gpu || !m_gpu->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_timers.get()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_bus->SetGPU(m_gpu.get());
|
||||||
|
m_dma->SetGPU(m_gpu.get());
|
||||||
|
|
||||||
|
// the new GPU could have a lower maximum resolution
|
||||||
|
m_settings.gpu_resolution_scale = m_gpu->GetResolutionScale();
|
||||||
|
m_settings.max_gpu_resolution_scale = m_gpu->GetMaxResolutionScale();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool System::DoState(StateWrapper& sw)
|
bool System::DoState(StateWrapper& sw)
|
||||||
{
|
{
|
||||||
if (!sw.DoMarker("System"))
|
if (!sw.DoMarker("System"))
|
||||||
|
@ -326,21 +369,3 @@ void System::RemoveMedia()
|
||||||
{
|
{
|
||||||
m_cdrom->RemoveMedia();
|
m_cdrom->RemoveMedia();
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::DrawDebugMenus()
|
|
||||||
{
|
|
||||||
m_gpu->DrawDebugMenu();
|
|
||||||
m_spu->DrawDebugMenu();
|
|
||||||
m_timers->DrawDebugMenu();
|
|
||||||
m_cdrom->DrawDebugMenu();
|
|
||||||
m_mdec->DrawDebugMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::DrawDebugWindows()
|
|
||||||
{
|
|
||||||
m_gpu->DrawDebugWindows();
|
|
||||||
m_spu->DrawDebugWindow();
|
|
||||||
m_timers->DrawDebugWindow();
|
|
||||||
m_cdrom->DrawDebugWindow();
|
|
||||||
m_mdec->DrawDebugWindow();
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,11 +29,18 @@ public:
|
||||||
System(HostInterface* host_interface, const Settings& settings);
|
System(HostInterface* host_interface, const Settings& settings);
|
||||||
~System();
|
~System();
|
||||||
|
|
||||||
|
// Accessing components.
|
||||||
HostInterface* GetHostInterface() const { return m_host_interface; }
|
HostInterface* GetHostInterface() const { return m_host_interface; }
|
||||||
CPU::Core* GetCPU() const { return m_cpu.get(); }
|
CPU::Core* GetCPU() const { return m_cpu.get(); }
|
||||||
Bus* GetBus() const { return m_bus.get(); }
|
Bus* GetBus() const { return m_bus.get(); }
|
||||||
|
DMA* GetDMA() const { return m_dma.get(); }
|
||||||
|
InterruptController* GetInterruptController() const { return m_interrupt_controller.get(); }
|
||||||
GPU* GetGPU() const { return m_gpu.get(); }
|
GPU* GetGPU() const { return m_gpu.get(); }
|
||||||
|
CDROM* GetCDROM() const { return m_cdrom.get(); }
|
||||||
|
Pad* GetPad() const { return m_pad.get(); }
|
||||||
|
Timers* GetTimers() const { return m_timers.get(); }
|
||||||
SPU* GetSPU() const { return m_spu.get(); }
|
SPU* GetSPU() const { return m_spu.get(); }
|
||||||
|
MDEC* GetMDEC() const { return m_mdec.get(); }
|
||||||
|
|
||||||
u32 GetFrameNumber() const { return m_frame_number; }
|
u32 GetFrameNumber() const { return m_frame_number; }
|
||||||
u32 GetInternalFrameNumber() const { return m_internal_frame_number; }
|
u32 GetInternalFrameNumber() const { return m_internal_frame_number; }
|
||||||
|
@ -42,7 +49,6 @@ public:
|
||||||
void IncrementInternalFrameNumber() { m_internal_frame_number++; }
|
void IncrementInternalFrameNumber() { m_internal_frame_number++; }
|
||||||
|
|
||||||
Settings& GetSettings() { return m_settings; }
|
Settings& GetSettings() { return m_settings; }
|
||||||
void UpdateSettings();
|
|
||||||
|
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
@ -50,6 +56,9 @@ public:
|
||||||
bool LoadState(ByteStream* state);
|
bool LoadState(ByteStream* state);
|
||||||
bool SaveState(ByteStream* state);
|
bool SaveState(ByteStream* state);
|
||||||
|
|
||||||
|
/// Recreates the GPU component, saving/loading the state so it is preserved. Call when the GPU renderer changes.
|
||||||
|
bool RecreateGPU();
|
||||||
|
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
|
|
||||||
bool LoadEXE(const char* filename);
|
bool LoadEXE(const char* filename);
|
||||||
|
@ -68,11 +77,9 @@ public:
|
||||||
bool InsertMedia(const char* path);
|
bool InsertMedia(const char* path);
|
||||||
void RemoveMedia();
|
void RemoveMedia();
|
||||||
|
|
||||||
void DrawDebugMenus();
|
|
||||||
void DrawDebugWindows();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool DoState(StateWrapper& sw);
|
bool DoState(StateWrapper& sw);
|
||||||
|
bool CreateGPU();
|
||||||
|
|
||||||
HostInterface* m_host_interface;
|
HostInterface* m_host_interface;
|
||||||
std::unique_ptr<CPU::Core> m_cpu;
|
std::unique_ptr<CPU::Core> m_cpu;
|
||||||
|
|
|
@ -292,16 +292,8 @@ void Timers::UpdateDowncount()
|
||||||
m_system->SetDowncount(min_ticks);
|
m_system->SetDowncount(min_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timers::DrawDebugMenu()
|
void Timers::DrawDebugStateWindow()
|
||||||
{
|
{
|
||||||
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 u32 NUM_COLUMNS = 10;
|
||||||
static constexpr std::array<const char*, NUM_COLUMNS> column_names = {
|
static constexpr std::array<const char*, NUM_COLUMNS> column_names = {
|
||||||
{"#", "Value", "Target", "Sync", "Reset", "IRQ", "IRQRepeat", "IRQToggle", "Clock Source", "Reached"}};
|
{"#", "Value", "Target", "Sync", "Reset", "IRQ", "IRQRepeat", "IRQToggle", "Clock Source", "Reached"}};
|
||||||
|
@ -313,7 +305,7 @@ void Timers::DrawDebugWindow()
|
||||||
{{"SysClk", "DotClk", "SysClk/8", "SysClk/8"}}}};
|
{{"SysClk", "DotClk", "SysClk/8", "SysClk/8"}}}};
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(800, 100), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(800, 100), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("Timer State", &m_debug_show_state))
|
if (!ImGui::Begin("Timer State", &m_system->GetSettings().debugging.show_timers_state))
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -20,8 +20,7 @@ public:
|
||||||
|
|
||||||
void SetGate(u32 timer, bool state);
|
void SetGate(u32 timer, bool state);
|
||||||
|
|
||||||
void DrawDebugMenu();
|
void DrawDebugStateWindow();
|
||||||
void DrawDebugWindow();
|
|
||||||
|
|
||||||
// dot clock/hblank/sysclk div 8
|
// dot clock/hblank/sysclk div 8
|
||||||
bool IsUsingExternalClock(u32 timer) const { return m_states[timer].external_counting_enabled; }
|
bool IsUsingExternalClock(u32 timer) const { return m_states[timer].external_counting_enabled; }
|
||||||
|
@ -81,6 +80,4 @@ private:
|
||||||
|
|
||||||
std::array<CounterState, NUM_TIMERS> m_states{};
|
std::array<CounterState, NUM_TIMERS> m_states{};
|
||||||
u32 m_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8
|
u32 m_sysclk_div_8_carry = 0; // partial ticks for timer 3 with sysclk/8
|
||||||
|
|
||||||
bool m_debug_show_state = false;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,10 +2,15 @@
|
||||||
#include "YBaseLib/ByteStream.h"
|
#include "YBaseLib/ByteStream.h"
|
||||||
#include "YBaseLib/Error.h"
|
#include "YBaseLib/Error.h"
|
||||||
#include "YBaseLib/Log.h"
|
#include "YBaseLib/Log.h"
|
||||||
|
#include "core/cdrom.h"
|
||||||
#include "core/digital_controller.h"
|
#include "core/digital_controller.h"
|
||||||
|
#include "core/dma.h"
|
||||||
#include "core/gpu.h"
|
#include "core/gpu.h"
|
||||||
|
#include "core/mdec.h"
|
||||||
#include "core/memory_card.h"
|
#include "core/memory_card.h"
|
||||||
|
#include "core/spu.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
|
#include "core/timers.h"
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
#include "sdl_audio_stream.h"
|
#include "sdl_audio_stream.h"
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
@ -16,6 +21,9 @@
|
||||||
#include <nfd.h>
|
#include <nfd.h>
|
||||||
Log_SetChannel(SDLInterface);
|
Log_SetChannel(SDLInterface);
|
||||||
|
|
||||||
|
static constexpr std::array<std::pair<GPURenderer, const char*>, 1> s_gpu_renderer_names = {
|
||||||
|
{{GPURenderer::HardwareOpenGL, "Hardware (OpenGL)"}}};
|
||||||
|
|
||||||
SDLInterface::SDLInterface() = default;
|
SDLInterface::SDLInterface() = default;
|
||||||
|
|
||||||
SDLInterface::~SDLInterface()
|
SDLInterface::~SDLInterface()
|
||||||
|
@ -699,7 +707,7 @@ void SDLInterface::DrawImGui()
|
||||||
DrawMainMenuBar();
|
DrawMainMenuBar();
|
||||||
|
|
||||||
if (m_system)
|
if (m_system)
|
||||||
m_system->DrawDebugWindows();
|
DrawDebugWindows();
|
||||||
else
|
else
|
||||||
DrawPoweredOffWindow();
|
DrawPoweredOffWindow();
|
||||||
|
|
||||||
|
@ -777,6 +785,21 @@ void SDLInterface::DrawMainMenuBar()
|
||||||
|
|
||||||
if (ImGui::BeginMenu("GPU", system_enabled))
|
if (ImGui::BeginMenu("GPU", system_enabled))
|
||||||
{
|
{
|
||||||
|
if (ImGui::BeginMenu("Renderer"))
|
||||||
|
{
|
||||||
|
const GPURenderer current = m_system->GetSettings().gpu_renderer;
|
||||||
|
for (const auto& it : s_gpu_renderer_names)
|
||||||
|
{
|
||||||
|
if (ImGui::MenuItem(it.second, nullptr, current == it.first))
|
||||||
|
{
|
||||||
|
m_system->GetSettings().gpu_renderer = it.first;
|
||||||
|
m_system->RecreateGPU();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Internal Resolution"))
|
if (ImGui::BeginMenu("Internal Resolution"))
|
||||||
{
|
{
|
||||||
const u32 current_internal_resolution = m_system->GetSettings().gpu_resolution_scale;
|
const u32 current_internal_resolution = m_system->GetSettings().gpu_resolution_scale;
|
||||||
|
@ -787,7 +810,7 @@ void SDLInterface::DrawMainMenuBar()
|
||||||
nullptr, current_internal_resolution == scale))
|
nullptr, current_internal_resolution == scale))
|
||||||
{
|
{
|
||||||
m_system->GetSettings().gpu_resolution_scale = scale;
|
m_system->GetSettings().gpu_resolution_scale = scale;
|
||||||
m_system->UpdateSettings();
|
m_system->GetGPU()->UpdateResolutionScale();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,13 +827,7 @@ void SDLInterface::DrawMainMenuBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_system)
|
if (m_system)
|
||||||
{
|
DrawDebugMenu();
|
||||||
if (ImGui::BeginMenu("Debug"))
|
|
||||||
{
|
|
||||||
m_system->DrawDebugMenus();
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Help"))
|
if (ImGui::BeginMenu("Help"))
|
||||||
{
|
{
|
||||||
|
@ -955,6 +972,54 @@ void SDLInterface::DrawAboutWindow()
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLInterface::DrawDebugMenu()
|
||||||
|
{
|
||||||
|
if (!ImGui::BeginMenu("Debug", m_system != nullptr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Settings::DebugSettings& debug_settings = m_system->GetSettings().debugging;
|
||||||
|
|
||||||
|
ImGui::MenuItem("Show System State");
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::MenuItem("Show GPU State", nullptr, &debug_settings.show_gpu_state);
|
||||||
|
ImGui::MenuItem("Show GPU Renderer Stats", nullptr, &debug_settings.show_gpu_renderer_stats);
|
||||||
|
ImGui::MenuItem("Show VRAM", nullptr, &debug_settings.show_vram);
|
||||||
|
ImGui::MenuItem("Dump CPU to VRAM Copies", nullptr, &debug_settings.dump_cpu_to_vram_copies);
|
||||||
|
ImGui::MenuItem("Dump VRAM to CPU Copies", nullptr, &debug_settings.dump_vram_to_cpu_copies);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::MenuItem("Show CDROM State", nullptr, &debug_settings.show_cdrom_state);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::MenuItem("Show SPU State", nullptr, &debug_settings.show_spu_state);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::MenuItem("Show Timers State", nullptr, &debug_settings.show_timers_state);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::MenuItem("Show MDEC State", nullptr, &debug_settings.show_mdec_state);
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLInterface::DrawDebugWindows()
|
||||||
|
{
|
||||||
|
const Settings::DebugSettings& debug_settings = m_system->GetSettings().debugging;
|
||||||
|
|
||||||
|
if (debug_settings.show_gpu_state)
|
||||||
|
m_system->GetGPU()->DrawDebugStateWindow();
|
||||||
|
if (debug_settings.show_gpu_renderer_stats)
|
||||||
|
m_system->GetGPU()->DrawRendererStatsWindow();
|
||||||
|
if (debug_settings.show_cdrom_state)
|
||||||
|
m_system->GetCDROM()->DrawDebugWindow();
|
||||||
|
if (debug_settings.show_timers_state)
|
||||||
|
m_system->GetTimers()->DrawDebugStateWindow();
|
||||||
|
if (debug_settings.show_spu_state)
|
||||||
|
m_system->GetSPU()->DrawDebugStateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
void SDLInterface::AddOSDMessage(const char* message, float duration /*= 2.0f*/)
|
void SDLInterface::AddOSDMessage(const char* message, float duration /*= 2.0f*/)
|
||||||
{
|
{
|
||||||
OSDMessage msg;
|
OSDMessage msg;
|
||||||
|
|
|
@ -82,6 +82,8 @@ private:
|
||||||
void DrawPoweredOffWindow();
|
void DrawPoweredOffWindow();
|
||||||
void DrawAboutWindow();
|
void DrawAboutWindow();
|
||||||
void DrawOSDMessages();
|
void DrawOSDMessages();
|
||||||
|
void DrawDebugMenu();
|
||||||
|
void DrawDebugWindows();
|
||||||
|
|
||||||
SDL_Window* m_window = nullptr;
|
SDL_Window* m_window = nullptr;
|
||||||
SDL_GLContext m_gl_context = nullptr;
|
SDL_GLContext m_gl_context = nullptr;
|
||||||
|
|
Loading…
Reference in New Issue