From 26db661a05b6353107f841700eb925aa382201a3 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 21 Dec 2024 14:10:46 +1000 Subject: [PATCH 1/5] GPU: Remove global indirection --- src/core/bus.cpp | 4 +- src/core/dma.cpp | 10 ++-- src/core/gpu.cpp | 26 +++++----- src/core/gpu.h | 3 +- src/core/gpu_dump.cpp | 6 +-- src/core/gpu_hw_texture_cache.cpp | 1 - src/core/gpu_sw_rasterizer.inl | 80 +++++++++++++++++-------------- src/core/guncon.cpp | 6 +-- src/core/imgui_overlays.cpp | 8 ++-- src/core/justifier.cpp | 16 +++---- src/core/system.cpp | 31 ++++++------ src/core/timers.cpp | 12 ++--- src/duckstation-qt/qthost.cpp | 2 +- 13 files changed, 107 insertions(+), 98 deletions(-) diff --git a/src/core/bus.cpp b/src/core/bus.cpp index ea2fe98517..9686ba82df 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -1875,7 +1875,7 @@ template u32 Bus::HWHandlers::GPURead(PhysicalMemoryAddress address) { const u32 offset = address & GPU_MASK; - u32 value = g_gpu->ReadRegister(FIXUP_WORD_OFFSET(size, offset)); + u32 value = g_gpu.ReadRegister(FIXUP_WORD_OFFSET(size, offset)); value = FIXUP_WORD_READ_VALUE(size, offset, value); BUS_CYCLES(2); return value; @@ -1885,7 +1885,7 @@ template void Bus::HWHandlers::GPUWrite(PhysicalMemoryAddress address, u32 value) { const u32 offset = address & GPU_MASK; - g_gpu->WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); + g_gpu.WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); } template diff --git a/src/core/dma.cpp b/src/core/dma.cpp index d980df4c98..21e71758a3 100644 --- a/src/core/dma.cpp +++ b/src/core/dma.cpp @@ -802,9 +802,9 @@ TickCount DMA::TransferMemoryToDevice(u32 address, u32 increment, u32 word_count { case Channel::GPU: { - if (g_gpu->BeginDMAWrite()) [[likely]] + if (g_gpu.BeginDMAWrite()) [[likely]] { - if (GPUDump::Recorder* dump = g_gpu->GetGPUDump()) [[unlikely]] + if (GPUDump::Recorder* dump = g_gpu.GetGPUDump()) [[unlikely]] { // No wraparound? dump->BeginGP0Packet(word_count); @@ -831,10 +831,10 @@ TickCount DMA::TransferMemoryToDevice(u32 address, u32 increment, u32 word_count { u32 value; std::memcpy(&value, &ram_pointer[address], sizeof(u32)); - g_gpu->DMAWrite(address, value); + g_gpu.DMAWrite(address, value); address = (address + increment) & mask; } - g_gpu->EndDMAWrite(); + g_gpu.EndDMAWrite(); } } break; @@ -900,7 +900,7 @@ TickCount DMA::TransferDeviceToMemory(u32 address, u32 increment, u32 word_count switch (channel) { case Channel::GPU: - g_gpu->DMARead(dest_pointer, word_count); + g_gpu.DMARead(dest_pointer, word_count); break; case Channel::CDROM: diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index 367d8282b1..6c0948473c 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -45,7 +45,7 @@ LOG_CHANNEL(GPU); -std::unique_ptr g_gpu; +ALIGN_TO_CACHE_LINE GPU g_gpu; // aligning VRAM to 4K is fine, since the ARM64 instructions compute 4K page aligned addresses // or it would be, except we want to import the memory for readbacks on metal.. @@ -60,13 +60,13 @@ u16 g_gpu_clut[GPU_CLUT_SIZE]; const GPU::GP0CommandHandlerTable GPU::s_GP0_command_handler_table = GPU::GenerateGP0CommandHandlerTable(); static TimingEvent s_crtc_tick_event( - "GPU CRTC Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->CRTCTickEvent(ticks); }, + "GPU CRTC Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu.CRTCTickEvent(ticks); }, nullptr); static TimingEvent s_command_tick_event( - "GPU Command Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->CommandTickEvent(ticks); }, + "GPU Command Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu.CommandTickEvent(ticks); }, nullptr); static TimingEvent s_frame_done_event( - "Frame Done", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->FrameDoneEvent(ticks); }, + "Frame Done", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu.FrameDoneEvent(ticks); }, nullptr); // #define PSX_GPU_STATS @@ -77,14 +77,7 @@ static u32 s_active_gpu_cycles_frames = 0; GPU::GPU() = default; -GPU::~GPU() -{ - s_command_tick_event.Deactivate(); - s_crtc_tick_event.Deactivate(); - s_frame_done_event.Deactivate(); - - StopRecordingGPUDump(); -} +GPU::~GPU() = default; void GPU::Initialize() { @@ -104,6 +97,15 @@ void GPU::Initialize() #endif } +void GPU::Shutdown() +{ + s_command_tick_event.Deactivate(); + s_crtc_tick_event.Deactivate(); + s_frame_done_event.Deactivate(); + + StopRecordingGPUDump(); +} + void GPU::UpdateSettings(const Settings& old_settings) { m_force_progressive_scan = (g_settings.display_deinterlacing_mode == DisplayDeinterlacingMode::Progressive); diff --git a/src/core/gpu.h b/src/core/gpu.h index a1258f6b53..c663d5071a 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -95,6 +95,7 @@ class GPU final ~GPU(); void Initialize(); + void Shutdown(); void Reset(bool clear_vram); bool DoState(StateWrapper& sw, bool update_display); void DoMemoryState(StateWrapper& sw, System::MemorySaveState& mss, bool update_display); @@ -561,6 +562,6 @@ class GPU final static const GP0CommandHandlerTable s_GP0_command_handler_table; }; -extern std::unique_ptr g_gpu; +extern GPU g_gpu; extern u16 g_vram[VRAM_SIZE / sizeof(u16)]; extern u16 g_gpu_clut[GPU_CLUT_SIZE]; diff --git a/src/core/gpu_dump.cpp b/src/core/gpu_dump.cpp index 5b32be867b..25a70acddf 100644 --- a/src/core/gpu_dump.cpp +++ b/src/core/gpu_dump.cpp @@ -76,7 +76,7 @@ std::unique_ptr GPUDump::Recorder::Create(std::string path, s ret = std::unique_ptr(new Recorder(std::move(fp), num_frames, std::move(path))); ret->WriteHeaders(serial); - g_gpu->WriteCurrentVideoModeToDump(ret.get()); + g_gpu.WriteCurrentVideoModeToDump(ret.get()); ret->WriteCurrentVRAM(); // Write start of stream. @@ -285,7 +285,7 @@ void GPUDump::Recorder::WriteHeaders(std::string_view serial) // Write textual video mode. BeginPacket(PacketType::TextualVideoFormat); - WriteString(g_gpu->IsInPALMode() ? "PAL" : "NTSC"); + WriteString(g_gpu.IsInPALMode() ? "PAL" : "NTSC"); EndPacket(); // Write DuckStation version. @@ -520,7 +520,7 @@ void GPUDump::Player::ProcessPacket(const PacketRef& pkt) if (pkt.type <= PacketType::VSyncEvent) { // gp0/gp1/vsync => direct to gpu - g_gpu->ProcessGPUDumpPacket(pkt.type, pkt.data); + g_gpu.ProcessGPUDumpPacket(pkt.type, pkt.data); return; } } diff --git a/src/core/gpu_hw_texture_cache.cpp b/src/core/gpu_hw_texture_cache.cpp index cba1b7985a..0b7a3182e2 100644 --- a/src/core/gpu_hw_texture_cache.cpp +++ b/src/core/gpu_hw_texture_cache.cpp @@ -3483,7 +3483,6 @@ void GPUTextureCache::ReloadTextureReplacements(bool show_info) PurgeUnreferencedTexturesFromCache(); - DebugAssert(g_gpu); UpdateVRAMTrackingState(); InvalidateSources(); diff --git a/src/core/gpu_sw_rasterizer.inl b/src/core/gpu_sw_rasterizer.inl index 3deb0a9b87..67d0e34f8a 100644 --- a/src/core/gpu_sw_rasterizer.inl +++ b/src/core/gpu_sw_rasterizer.inl @@ -506,10 +506,11 @@ struct PixelVectors } // namespace template -ALWAYS_INLINE_RELEASE static void -ShadePixel(const PixelVectors& pv, GPUTextureMode texture_mode, GPUTransparencyMode transparency_mode, - u32 start_x, u32 y, GSVectorNi vertex_color_rg, GSVectorNi vertex_color_ba, GSVectorNi texcoord_x, - GSVectorNi texcoord_y, GSVectorNi preserve_mask, GSVectorNi dither) +ALWAYS_INLINE_RELEASE static void ShadePixel(const PixelVectors& RESTRICT pv, + GPUTextureMode texture_mode, GPUTransparencyMode transparency_mode, + u32 start_x, u32 y, GSVectorNi vertex_color_rg, GSVectorNi vertex_color_ba, + GSVectorNi texcoord_x, GSVectorNi texcoord_y, GSVectorNi preserve_mask, + GSVectorNi dither) { static constexpr GSVectorNi coord_mask_x = GSVectorNi::cxpr(VRAM_WIDTH_MASK); static constexpr GSVectorNi coord_mask_y = GSVectorNi::cxpr(VRAM_HEIGHT_MASK); @@ -693,7 +694,7 @@ ShadePixel(const PixelVectors& pv, GPUTextureMode texture_mode, } template -static void DrawRectangle(const GPUBackendDrawRectangleCommand* cmd) +static void DrawRectangle(const GPUBackendDrawRectangleCommand* RESTRICT cmd) { const s32 origin_x = cmd->x; const s32 origin_y = cmd->y; @@ -765,8 +766,9 @@ static void DrawRectangle(const GPUBackendDrawRectangleCommand* cmd) // TODO: Vectorize line draw. template -static void DrawLine(const GPUBackendDrawLineCommand* cmd, const GPUBackendDrawLineCommand::Vertex* p0, - const GPUBackendDrawLineCommand::Vertex* p1) +static void DrawLine(const GPUBackendDrawLineCommand* RESTRICT cmd, + const GPUBackendDrawLineCommand::Vertex* RESTRICT p0, + const GPUBackendDrawLineCommand::Vertex* RESTRICT p1) { static constexpr u32 XY_SHIFT = 32; static constexpr u32 RGB_SHIFT = 12; @@ -971,8 +973,8 @@ struct TrianglePart #ifndef USE_VECTOR template -static void DrawSpan(const GPUBackendDrawCommand* cmd, s32 y, s32 x_start, s32 x_bound, UVStepper uv, - const UVSteps& uvstep, RGBStepper rgb, const RGBSteps& rgbstep) +static void DrawSpan(const GPUBackendDrawCommand* RESTRICT cmd, s32 y, s32 x_start, s32 x_bound, UVStepper uv, + const UVSteps& RESTRICT uvstep, RGBStepper rgb, const RGBSteps& RESTRICT rgbstep) { s32 width = x_bound - x_start; s32 current_x = TruncateGPUVertexPosition(x_start); @@ -1011,9 +1013,10 @@ static void DrawSpan(const GPUBackendDrawCommand* cmd, s32 y, s32 x_start, s32 x } template -ALWAYS_INLINE_RELEASE static void DrawTrianglePart(const GPUBackendDrawCommand* cmd, const TrianglePart& tp, - const UVStepper& uv, const UVSteps& uvstep, const RGBStepper& rgb, - const RGBSteps& rgbstep) +ALWAYS_INLINE_RELEASE static void DrawTrianglePart(const GPUBackendDrawCommand* RESTRICT cmd, + const TrianglePart& RESTRICT tp, const UVStepper& RESTRICT uv, + const UVSteps& RESTRICT uvstep, const RGBStepper& RESTRICT rgb, + const RGBSteps& RESTRICT rgbstep) { static constexpr auto unfp_xy = [](s64 xfp) -> s32 { return static_cast(static_cast(xfp) >> 32); }; @@ -1150,9 +1153,10 @@ struct TriangleVectors : PixelVectors } // namespace template -ALWAYS_INLINE_RELEASE static void DrawSpan(const GPUBackendDrawCommand* cmd, s32 y, s32 x_start, s32 x_bound, - UVStepper uv, const UVSteps& uvstep, RGBStepper rgb, const RGBSteps& rgbstep, - const TriangleVectors& tv) +ALWAYS_INLINE_RELEASE static void DrawSpan(const GPUBackendDrawCommand* RESTRICT cmd, s32 y, s32 x_start, s32 x_bound, + UVStepper uv, const UVSteps& RESTRICT uvstep, RGBStepper rgb, + const RGBSteps& RESTRICT rgbstep, + const TriangleVectors& RESTRICT tv) { s32 width = x_bound - x_start; s32 current_x = TruncateGPUVertexPosition(x_start); @@ -1255,9 +1259,10 @@ ALWAYS_INLINE_RELEASE static void DrawSpan(const GPUBackendDrawCommand* cmd, s32 } template -ALWAYS_INLINE_RELEASE static void DrawTrianglePart(const GPUBackendDrawCommand* cmd, const TrianglePart& tp, - const UVStepper& uv, const UVSteps& uvstep, const RGBStepper& rgb, - const RGBSteps& rgbstep) +ALWAYS_INLINE_RELEASE static void DrawTrianglePart(const GPUBackendDrawCommand* RESTRICT cmd, + const TrianglePart& RESTRICT tp, const UVStepper& RESTRICT uv, + const UVSteps& RESTRICT uvstep, const RGBStepper& RESTRICT rgb, + const RGBSteps& RESTRICT rgbstep) { static constexpr auto unfp_xy = [](s64 xfp) -> s32 { return static_cast(static_cast(xfp) >> 32); }; @@ -1356,13 +1361,15 @@ ALWAYS_INLINE_RELEASE static void DrawTrianglePart(const GPUBackendDrawCommand* #endif // USE_VECTOR template -static void DrawTriangle(const GPUBackendDrawCommand* cmd, const GPUBackendDrawPolygonCommand::Vertex* v0, - const GPUBackendDrawPolygonCommand::Vertex* v1, const GPUBackendDrawPolygonCommand::Vertex* v2) +static void DrawTriangle(const GPUBackendDrawCommand* RESTRICT cmd, + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT v0, + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT v1, + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT v2) { #ifdef CHECK_VECTOR - const GPUBackendDrawPolygonCommand::Vertex* orig_v0 = v0; - const GPUBackendDrawPolygonCommand::Vertex* orig_v1 = v1; - const GPUBackendDrawPolygonCommand::Vertex* orig_v2 = v2; + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT orig_v0 = v0; + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT orig_v1 = v1; + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT orig_v2 = v2; #endif // Sort vertices so that v0 is the top vertex, v1 is the bottom vertex, and v2 is the side vertex. @@ -1417,8 +1424,8 @@ static void DrawTriangle(const GPUBackendDrawCommand* cmd, const GPUBackendDrawP const u32 ofi = BoolToUInt32(!right_facing); TrianglePart triparts[2]; - TrianglePart& tpo = triparts[vo]; - TrianglePart& tpp = triparts[vo ^ 1]; + TrianglePart& RESTRICT tpo = triparts[vo]; + TrianglePart& RESTRICT tpp = triparts[vo ^ 1]; tpo.start_y = vertices[0 ^ vo]->y; tpo.end_y = vertices[1 ^ vo]->y; tpp.start_y = vertices[1 ^ vp]->y; @@ -1469,7 +1476,7 @@ static void DrawTriangle(const GPUBackendDrawCommand* cmd, const GPUBackendDrawP // Undo the start of the vertex, so that when we add the offset for each line, it starts at the beginning value. UVStepper uv; RGBStepper rgb; - const GPUBackendDrawPolygonCommand::Vertex* top_left_vertex = vertices[tl]; + const GPUBackendDrawPolygonCommand::Vertex* RESTRICT top_left_vertex = vertices[tl]; if constexpr (texture_enable) { uv.Init(top_left_vertex->u, top_left_vertex->v); @@ -1542,7 +1549,7 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in { const u32 row = (y + yoffs) % VRAM_HEIGHT; - u16* row_ptr = &g_vram[row * VRAM_WIDTH + x]; + u16* RESTRICT row_ptr = &g_vram[row * VRAM_WIDTH + x]; u32 xoffs = 0; for (; xoffs < aligned_width; xoffs += vector_width, row_ptr += vector_width) GSVector4i::store(row_ptr, fill); @@ -1563,7 +1570,7 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in if ((row & u32(1)) == active_field) continue; - u16* row_ptr = &g_vram[row * VRAM_WIDTH + x]; + u16* RESTRICT row_ptr = &g_vram[row * VRAM_WIDTH + x]; u32 xoffs = 0; for (; xoffs < aligned_width; xoffs += vector_width, row_ptr += vector_width) GSVector4i::store(row_ptr, fill); @@ -1579,7 +1586,7 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in if ((row & u32(1)) == active_field) continue; - u16* row_ptr = &g_vram[row * VRAM_WIDTH]; + u16* RESTRICT row_ptr = &g_vram[row * VRAM_WIDTH]; for (u32 xoffs = 0; xoffs < width; xoffs++) { const u32 col = (x + xoffs) % VRAM_WIDTH; @@ -1593,7 +1600,7 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in for (u32 yoffs = 0; yoffs < height; yoffs++) { const u32 row = (y + yoffs) % VRAM_HEIGHT; - u16* row_ptr = &g_vram[row * VRAM_WIDTH]; + u16* RESTRICT row_ptr = &g_vram[row * VRAM_WIDTH]; for (u32 xoffs = 0; xoffs < width; xoffs++) { const u32 col = (x + xoffs) % VRAM_WIDTH; @@ -1622,7 +1629,7 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in if ((row & u32(1)) == active_field) continue; - u16* row_ptr = &g_vram[row * VRAM_WIDTH]; + u16* RESTRICT row_ptr = &g_vram[row * VRAM_WIDTH]; for (u32 xoffs = 0; xoffs < width; xoffs++) { const u32 col = (x + xoffs) % VRAM_WIDTH; @@ -1635,7 +1642,7 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in for (u32 yoffs = 0; yoffs < height; yoffs++) { const u32 row = (y + yoffs) % VRAM_HEIGHT; - u16* row_ptr = &g_vram[row * VRAM_WIDTH]; + u16* RESTRICT row_ptr = &g_vram[row * VRAM_WIDTH]; for (u32 xoffs = 0; xoffs < width; xoffs++) { const u32 col = (x + xoffs) % VRAM_WIDTH; @@ -1646,12 +1653,13 @@ static void FillVRAMImpl(u32 x, u32 y, u32 width, u32 height, u32 color, bool in #endif } -static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) +static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* RESTRICT data, bool set_mask, + bool check_mask) { // Fast path when the copy is not oversized. if ((x + width) <= VRAM_WIDTH && (y + height) <= VRAM_HEIGHT && !set_mask && !check_mask) { - const u16* src_ptr = static_cast(data); + const u16* RESTRICT src_ptr = static_cast(data); u16* dst_ptr = &g_vram[y * VRAM_WIDTH + x]; for (u32 yoffs = 0; yoffs < height; yoffs++) { @@ -1664,7 +1672,7 @@ static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* data, { // Slow path when we need to handle wrap-around. // During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or } - const u16* src_ptr = static_cast(data); + const u16* RESTRICT src_ptr = static_cast(data); const u16 mask_and = check_mask ? 0x8000u : 0x0000u; const u16 mask_or = set_mask ? 0x8000u : 0x0000u; @@ -1713,7 +1721,7 @@ static void WriteVRAMImpl(u32 x, u32 y, u32 width, u32 height, const void* data, for (; col < width;) { // TODO: Handle unaligned reads... - u16* pixel_ptr = &dst_row_ptr[(x + col++) % VRAM_WIDTH]; + u16* RESTRICT pixel_ptr = &dst_row_ptr[(x + col++) % VRAM_WIDTH]; if (((*pixel_ptr) & mask_and) == 0) *pixel_ptr = *(src_ptr++) | mask_or; } diff --git a/src/core/guncon.cpp b/src/core/guncon.cpp index c2a75c452d..88ef2ede70 100644 --- a/src/core/guncon.cpp +++ b/src/core/guncon.cpp @@ -207,12 +207,12 @@ void GunCon::UpdatePosition() float display_x, display_y; const auto& [window_x, window_y] = (m_has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() : InputManager::GetPointerAbsolutePosition(m_cursor_index); - g_gpu->ConvertScreenCoordinatesToDisplayCoordinates(window_x, window_y, &display_x, &display_y); + g_gpu.ConvertScreenCoordinatesToDisplayCoordinates(window_x, window_y, &display_x, &display_y); // are we within the active display area? u32 tick, line; if (display_x < 0 || display_y < 0 || - !g_gpu->ConvertDisplayCoordinatesToBeamTicksAndLines(display_x, display_y, m_x_scale, &tick, &line) || + !g_gpu.ConvertDisplayCoordinatesToBeamTicksAndLines(display_x, display_y, m_x_scale, &tick, &line) || m_shoot_offscreen) { DEBUG_LOG("Lightgun out of range for window coordinates {:.0f},{:.0f}", window_x, window_y); @@ -222,7 +222,7 @@ void GunCon::UpdatePosition() } // 8MHz units for X = 44100*768*11/7 = 53222400 / 8000000 = 6.6528 - const double divider = static_cast(g_gpu->GetCRTCFrequency()) / 8000000.0; + const double divider = static_cast(g_gpu.GetCRTCFrequency()) / 8000000.0; m_position_x = static_cast(static_cast(tick) / static_cast(divider)); m_position_y = static_cast(line); DEBUG_LOG("Lightgun window coordinates {:.0f},{:.0f} -> tick {} line {} 8mhz ticks {}", display_x, display_y, tick, diff --git a/src/core/imgui_overlays.cpp b/src/core/imgui_overlays.cpp index 1fa9b5a795..c9de11ddb8 100644 --- a/src/core/imgui_overlays.cpp +++ b/src/core/imgui_overlays.cpp @@ -85,7 +85,7 @@ static constexpr const char* DEBUG_WINDOW_CONFIG_SECTION = "DebugWindows"; static constexpr const std::array s_debug_window_info = {{ {"SPU", "SPU State", ":icons/applications-system.png", &SPU::DrawDebugStateWindow, 800, 915}, {"CDROM", "CD-ROM State", ":icons/applications-system.png", &CDROM::DrawDebugWindow, 800, 540}, - {"GPU", "GPU State", ":icons/applications-system.png", [](float sc) { g_gpu->DrawDebugStateWindow(sc); }, 450, 550}, + {"GPU", "GPU State", ":icons/applications-system.png", [](float sc) { g_gpu.DrawDebugStateWindow(sc); }, 450, 550}, {"DMA", "DMA State", ":icons/applications-system.png", &DMA::DrawDebugStateWindow, 860, 180}, {"MDEC", "MDEC State", ":icons/applications-system.png", &MDEC::DrawDebugStateWindow, 300, 350}, {"Timers", "Timers State", ":icons/applications-system.png", &Timers::DrawDebugStateWindow, 800, 95}, @@ -323,9 +323,9 @@ void ImGuiManager::DrawPerformanceOverlay(const GPUBackend* gpu, float& position if (g_gpu_settings.display_show_resolution) { const u32 resolution_scale = gpu->GetResolutionScale(); - const auto [display_width, display_height] = g_gpu->GetFullDisplayResolution(); // NOTE: Racey read. - const bool interlaced = g_gpu->IsInterlacedDisplayEnabled(); - const bool pal = g_gpu->IsInPALMode(); + const auto [display_width, display_height] = g_gpu.GetFullDisplayResolution(); // NOTE: Racey read. + const bool interlaced = g_gpu.IsInterlacedDisplayEnabled(); + const bool pal = g_gpu.IsInPALMode(); text.format("{}x{} {} {} [{}x]", display_width * resolution_scale, display_height * resolution_scale, pal ? "PAL" : "NTSC", interlaced ? "Interlaced" : "Progressive", resolution_scale); DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255)); diff --git a/src/core/justifier.cpp b/src/core/justifier.cpp index 89fcacd2ea..3c85a9254b 100644 --- a/src/core/justifier.cpp +++ b/src/core/justifier.cpp @@ -215,12 +215,12 @@ void Justifier::UpdatePosition() float display_x, display_y; const auto [window_x, window_y] = (m_has_relative_binds) ? GetAbsolutePositionFromRelativeAxes() : InputManager::GetPointerAbsolutePosition(m_cursor_index); - g_gpu->ConvertScreenCoordinatesToDisplayCoordinates(window_x, window_y, &display_x, &display_y); + g_gpu.ConvertScreenCoordinatesToDisplayCoordinates(window_x, window_y, &display_x, &display_y); // are we within the active display area? u32 tick, line; if (display_x < 0 || display_y < 0 || - !g_gpu->ConvertDisplayCoordinatesToBeamTicksAndLines(display_x, display_y, m_x_scale, &tick, &line) || + !g_gpu.ConvertDisplayCoordinatesToBeamTicksAndLines(display_x, display_y, m_x_scale, &tick, &line) || m_shoot_offscreen) { DEV_LOG("Lightgun out of range for window coordinates {:.0f},{:.0f}", window_x, window_y); @@ -234,11 +234,11 @@ void Justifier::UpdatePosition() m_irq_tick = static_cast(static_cast(tick) + System::ScaleTicksToOverclock(static_cast(m_tick_offset))); m_irq_first_line = static_cast(std::clamp(static_cast(line) + m_first_line_offset, - static_cast(g_gpu->GetCRTCActiveStartLine()), - static_cast(g_gpu->GetCRTCActiveEndLine()))); + static_cast(g_gpu.GetCRTCActiveStartLine()), + static_cast(g_gpu.GetCRTCActiveEndLine()))); m_irq_last_line = static_cast(std::clamp(static_cast(line) + m_last_line_offset, - static_cast(g_gpu->GetCRTCActiveStartLine()), - static_cast(g_gpu->GetCRTCActiveEndLine()))); + static_cast(g_gpu.GetCRTCActiveStartLine()), + static_cast(g_gpu.GetCRTCActiveEndLine()))); DEV_LOG("Lightgun window coordinates {},{} -> dpy {},{} -> tick {} line {} [{}-{}]", window_x, window_y, display_x, display_y, tick, line, m_irq_first_line, m_irq_last_line); @@ -255,7 +255,7 @@ void Justifier::UpdateIRQEvent() return; u32 current_tick, current_line; - g_gpu->GetBeamPosition(¤t_tick, ¤t_line); + g_gpu.GetBeamPosition(¤t_tick, ¤t_line); u32 target_line; if (current_line < m_irq_first_line || current_line >= m_irq_last_line) @@ -263,7 +263,7 @@ void Justifier::UpdateIRQEvent() else target_line = current_line + 1; - const TickCount ticks_until_pos = g_gpu->GetSystemTicksUntilTicksAndLine(m_irq_tick, target_line); + const TickCount ticks_until_pos = g_gpu.GetSystemTicksUntilTicksAndLine(m_irq_tick, target_line); DEBUG_LOG("Triggering IRQ in {} ticks @ tick {} line {}", ticks_until_pos, m_irq_tick, target_line); m_irq_event.Schedule(ticks_until_pos); } diff --git a/src/core/system.cpp b/src/core/system.cpp index d8b9470a3c..ca141a18ec 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -713,7 +713,7 @@ void System::UpdateOverclock() s_state.max_slice_ticks = ScaleTicksToOverclock(MASTER_CLOCK / 10); SPU::CPUClockChanged(); CDROM::CPUClockChanged(); - g_gpu->CPUClockChanged(); + g_gpu.CPUClockChanged(); Timers::CPUClocksChanged(); UpdateThrottlePeriod(); } @@ -1882,9 +1882,8 @@ bool System::Initialize(std::unique_ptr disc, DiscRegion disc_region, b !CDROM::InsertMedia(std::move(disc), disc_region, s_state.running_game_serial, s_state.running_game_title, error)) return false; - // TODO: Drop pointer - g_gpu = std::make_unique(); - g_gpu->Initialize(); + // TODO: Drop class + g_gpu.Initialize(); // This can fail due to the application being closed during startup. if (!GPUThread::CreateGPUBackend(s_state.running_game_serial, @@ -1965,7 +1964,7 @@ void System::DestroySystem() Timers::Shutdown(); Pad::Shutdown(); CDROM::Shutdown(); - g_gpu.reset(); + g_gpu.Shutdown(); DMA::Shutdown(); PIO::Shutdown(); CPU::CodeCache::Shutdown(); @@ -2100,7 +2099,7 @@ void System::FrameDone() } // Late submission of frame. This is needed because the input poll can determine whether we need to rewind. - g_gpu->QueuePresentCurrentFrame(); + g_gpu.QueuePresentCurrentFrame(); SaveMemoryState(AllocateMemoryState()); } @@ -2386,7 +2385,7 @@ bool System::DoState(StateWrapper& sw, bool update_display) if (!sw.DoMarker("InterruptController") || !InterruptController::DoState(sw)) return false; - if (!sw.DoMarker("GPU") || !g_gpu->DoState(sw, update_display)) + if (!sw.DoMarker("GPU") || !g_gpu.DoState(sw, update_display)) return false; if (!sw.DoMarker("CDROM") || !CDROM::DoState(sw)) @@ -2682,7 +2681,7 @@ void System::DoMemoryState(StateWrapper& sw, MemorySaveState& mss, bool update_d SAVE_COMPONENT("DMA", DMA::DoState(sw)); SAVE_COMPONENT("InterruptController", InterruptController::DoState(sw)); - g_gpu->DoMemoryState(sw, mss, update_display); + g_gpu.DoMemoryState(sw, mss, update_display); SAVE_COMPONENT("CDROM", CDROM::DoState(sw)); SAVE_COMPONENT("Pad", Pad::DoState(sw, true)); @@ -2731,7 +2730,7 @@ void System::InternalReset() PIO::Reset(); DMA::Reset(); InterruptController::Reset(); - g_gpu->Reset(true); + g_gpu.Reset(true); CDROM::Reset(); Pad::Reset(); Timers::Reset(); @@ -3957,7 +3956,7 @@ bool System::DumpVRAM(const char* filename) if (!IsValid()) return false; - return g_gpu->DumpVRAMToFile(filename); + return g_gpu.DumpVRAMToFile(filename); } bool System::DumpSPURAM(const char* filename) @@ -5198,7 +5197,7 @@ bool System::StartRecordingGPUDump(const char* path /*= nullptr*/, u32 num_frame if (!path) path = (auto_path = GetScreenshotPath("psxgpu")).c_str(); - return g_gpu->StartRecordingGPUDump(path, num_frames); + return g_gpu.StartRecordingGPUDump(path, num_frames); } void System::StopRecordingGPUDump() @@ -5206,7 +5205,7 @@ void System::StopRecordingGPUDump() if (!IsValid()) return; - g_gpu->StopRecordingGPUDump(); + g_gpu.StopRecordingGPUDump(); } static std::string_view GetCaptureTypeForMessage(bool capture_video, bool capture_audio) @@ -5686,9 +5685,9 @@ void System::RequestDisplaySize(float scale /*= 0.0f*/) } else { - requested_width = static_cast(g_gpu->GetCRTCDisplayWidth()) * scale; - requested_height = static_cast(g_gpu->GetCRTCDisplayHeight()) * scale; - g_gpu->ApplyPixelAspectRatioToSize(g_gpu->ComputePixelAspectRatio(), &requested_width, &requested_height); + requested_width = static_cast(g_gpu.GetCRTCDisplayWidth()) * scale; + requested_height = static_cast(g_gpu.GetCRTCDisplayHeight()) * scale; + g_gpu.ApplyPixelAspectRatioToSize(g_gpu.ComputePixelAspectRatio(), &requested_width, &requested_height); } if (g_settings.display_rotation == DisplayRotation::Rotate90 || @@ -5734,7 +5733,7 @@ void System::UpdateGTEAspectRatio() { // Pre-apply the native aspect ratio correction to the window size. // MatchWindow does not correct the display aspect ratio, so we need to apply it here. - const float correction = g_gpu->ComputeAspectRatioCorrection(); + const float correction = g_gpu.ComputeAspectRatioCorrection(); custom_num = static_cast(std::max(std::round(static_cast(main_window_info.surface_width) / correction), 1.0f)); custom_denom = std::max(main_window_info.surface_height, 1u); diff --git a/src/core/timers.cpp b/src/core/timers.cpp index c58d6e7ca5..4917b2e459 100644 --- a/src/core/timers.cpp +++ b/src/core/timers.cpp @@ -315,8 +315,8 @@ u32 Timers::ReadRegister(u32 offset) if (timer_index < 2 && cs.external_counting_enabled) { // timers 0/1 depend on the GPU - if (timer_index == 0 || g_gpu->IsCRTCScanlinePending()) - g_gpu->SynchronizeCRTC(); + if (timer_index == 0 || g_gpu.IsCRTCScanlinePending()) + g_gpu.SynchronizeCRTC(); } s_state.sysclk_event.InvokeEarly(); @@ -329,8 +329,8 @@ u32 Timers::ReadRegister(u32 offset) if (timer_index < 2 && cs.external_counting_enabled) { // timers 0/1 depend on the GPU - if (timer_index == 0 || g_gpu->IsCRTCScanlinePending()) - g_gpu->SynchronizeCRTC(); + if (timer_index == 0 || g_gpu.IsCRTCScanlinePending()) + g_gpu.SynchronizeCRTC(); } s_state.sysclk_event.InvokeEarly(); @@ -365,8 +365,8 @@ void Timers::WriteRegister(u32 offset, u32 value) if (timer_index < 2 && cs.external_counting_enabled) { // timers 0/1 depend on the GPU - if (timer_index == 0 || g_gpu->IsCRTCScanlinePending()) - g_gpu->SynchronizeCRTC(); + if (timer_index == 0 || g_gpu.IsCRTCScanlinePending()) + g_gpu.SynchronizeCRTC(); } s_state.sysclk_event.InvokeEarly(); diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index ffec2e7e97..8ec0e6593d 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -2081,7 +2081,7 @@ void EmuThread::updatePerformanceCounters(const GPUBackend* gpu_backend) if (gpu_backend) { const u32 render_scale = gpu_backend->GetResolutionScale(); - std::tie(render_width, render_height) = g_gpu->GetFullDisplayResolution(); + std::tie(render_width, render_height) = g_gpu.GetFullDisplayResolution(); render_width *= render_scale; render_height *= render_scale; } From 6b754e67590bafa3b1acfebd3d46503f7aa99382 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 21 Dec 2024 14:40:24 +1000 Subject: [PATCH 2/5] FullscreenUI: Fix CPU/GPU thread race on achievements toggle --- src/core/achievements.cpp | 21 ++++++++++++--------- src/core/fullscreen_ui.cpp | 30 +----------------------------- src/core/fullscreen_ui.h | 2 -- 3 files changed, 13 insertions(+), 40 deletions(-) diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 3efb850ce9..e8f65b49e2 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -2185,12 +2185,7 @@ void Achievements::ConfirmHardcoreModeDisableAsync(const char* trigger, std::fun void Achievements::ClearUIState() { -#ifndef __ANDROID__ - if (FullscreenUI::IsAchievementsWindowOpen() || FullscreenUI::IsLeaderboardsWindowOpen()) - FullscreenUI::ReturnToPreviousWindow(); - CloseLeaderboard(); -#endif s_state.achievement_badge_paths = {}; @@ -2470,10 +2465,14 @@ void Achievements::DrawAchievementsWindow() using ImGuiFullscreen::LayoutScale; using ImGuiFullscreen::UIStyle; + auto lock = Achievements::GetLock(); + + // achievements can get turned off via the main UI if (!s_state.achievement_list) + { + FullscreenUI::ReturnToPreviousWindow(); return; - - auto lock = Achievements::GetLock(); + } static constexpr float alpha = 0.8f; static constexpr float heading_alpha = 0.95f; @@ -2846,7 +2845,12 @@ void Achievements::DrawLeaderboardsWindow() static constexpr float heading_height_unscaled = 110.0f; static constexpr float tab_height_unscaled = 50.0f; - auto lock = Achievements::GetLock(); + const auto lock = Achievements::GetLock(); + if (!s_state.leaderboard_list) + { + FullscreenUI::ReturnToPreviousWindow(); + return; + } const bool is_leaderboard_open = (s_state.open_leaderboard != nullptr); bool close_leaderboard_on_exit = false; @@ -3437,7 +3441,6 @@ void Achievements::CloseLeaderboard() } s_state.open_leaderboard = nullptr; - ImGuiFullscreen::QueueResetFocus(ImGuiFullscreen::FocusResetType::Other); } #if defined(_WIN32) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 7050fe5e07..9f2a3fe3d1 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -634,25 +634,7 @@ bool FullscreenUI::AreAnyDialogsOpen() void FullscreenUI::CheckForConfigChanges(const Settings& old_settings) { - // NOTE: Called on CPU thread. - if (!IsInitialized()) - return; - - // If achievements got disabled, we might have the menu open... - // That means we're going to be reading achievement state. - if (old_settings.achievements_enabled && !g_settings.achievements_enabled) - { - if (!IsInitialized()) - return; - - GPUThread::RunOnThread([]() { - if (s_state.current_main_window == MainWindowType::Achievements || - s_state.current_main_window == MainWindowType::Leaderboards) - { - ReturnToPreviousWindow(); - } - }); - } + // NOTE: Called on GPU thread. } void FullscreenUI::UpdateRunIdleState() @@ -7635,11 +7617,6 @@ void FullscreenUI::OpenAchievementsWindow() }); } -bool FullscreenUI::IsAchievementsWindowOpen() -{ - return (s_state.current_main_window == MainWindowType::Achievements); -} - void FullscreenUI::OpenLeaderboardsWindow() { if (!System::IsValid()) @@ -7674,11 +7651,6 @@ void FullscreenUI::OpenLeaderboardsWindow() }); } -bool FullscreenUI::IsLeaderboardsWindowOpen() -{ - return (s_state.current_main_window == MainWindowType::Leaderboards); -} - #endif // __ANDROID__ LoadingScreenProgressCallback::LoadingScreenProgressCallback() diff --git a/src/core/fullscreen_ui.h b/src/core/fullscreen_ui.h index e84a00b811..896a33aed4 100644 --- a/src/core/fullscreen_ui.h +++ b/src/core/fullscreen_ui.h @@ -29,9 +29,7 @@ void OnRunningGameChanged(); void OpenPauseMenu(); void OpenCheatsMenu(); void OpenAchievementsWindow(); -bool IsAchievementsWindowOpen(); void OpenLeaderboardsWindow(); -bool IsLeaderboardsWindowOpen(); void ReturnToMainWindow(); void ReturnToPreviousWindow(); void SetStandardSelectionFooterText(bool back_instead_of_cancel); From 62285dcf33baaf0b193184af3738af60ed7f7306 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 21 Dec 2024 14:53:13 +1000 Subject: [PATCH 3/5] Settings: Split into GPU and main settings That way the GPU thread copy doesn't need fields it never touches. --- src/core/fullscreen_ui.cpp | 2 +- src/core/fullscreen_ui.h | 4 +- src/core/gpu_backend.cpp | 19 +- src/core/gpu_backend.h | 4 +- src/core/gpu_commands.cpp | 4 +- src/core/gpu_hw.cpp | 4 +- src/core/gpu_hw.h | 2 +- src/core/gpu_hw_texture_cache.cpp | 2 +- src/core/gpu_hw_texture_cache.h | 4 +- src/core/gpu_sw.cpp | 2 +- src/core/gpu_thread.cpp | 9 +- src/core/imgui_overlays.cpp | 26 +-- src/core/settings.cpp | 39 ++-- src/core/settings.h | 286 +++++++++++++++--------------- src/core/system.cpp | 18 +- 15 files changed, 211 insertions(+), 214 deletions(-) diff --git a/src/core/fullscreen_ui.cpp b/src/core/fullscreen_ui.cpp index 9f2a3fe3d1..e9949d5ac5 100644 --- a/src/core/fullscreen_ui.cpp +++ b/src/core/fullscreen_ui.cpp @@ -632,7 +632,7 @@ bool FullscreenUI::AreAnyDialogsOpen() ImGuiFullscreen::IsFileSelectorOpen()); } -void FullscreenUI::CheckForConfigChanges(const Settings& old_settings) +void FullscreenUI::CheckForConfigChanges(const GPUSettings& old_settings) { // NOTE: Called on GPU thread. } diff --git a/src/core/fullscreen_ui.h b/src/core/fullscreen_ui.h index 896a33aed4..b08d3d7dc3 100644 --- a/src/core/fullscreen_ui.h +++ b/src/core/fullscreen_ui.h @@ -13,13 +13,13 @@ class SmallStringBase; -struct Settings; +struct GPUSettings; namespace FullscreenUI { bool Initialize(); bool IsInitialized(); bool HasActiveWindow(); -void CheckForConfigChanges(const Settings& old_settings); +void CheckForConfigChanges(const GPUSettings& old_settings); void OnSystemStarted(); void OnSystemResumed(); void OnSystemDestroyed(); diff --git a/src/core/gpu_backend.cpp b/src/core/gpu_backend.cpp index 087473f89c..ca3bae9fe3 100644 --- a/src/core/gpu_backend.cpp +++ b/src/core/gpu_backend.cpp @@ -103,7 +103,7 @@ bool GPUBackend::Initialize(bool clear_vram, Error* error) return true; } -void GPUBackend::UpdateSettings(const Settings& old_settings) +void GPUBackend::UpdateSettings(const GPUSettings& old_settings) { FlushRender(); @@ -774,8 +774,8 @@ GPUDevice::PresentResult GPUBackend::PresentDisplay() GSVector4i display_rect; GSVector4i draw_rect; CalculateDrawRect(g_gpu_device->GetMainSwapChain()->GetWidth(), g_gpu_device->GetMainSwapChain()->GetHeight(), - !g_gpu_settings.debugging.show_vram, true, &display_rect, &draw_rect); - return RenderDisplay(nullptr, display_rect, draw_rect, !g_gpu_settings.debugging.show_vram); + !g_gpu_settings.gpu_show_vram, true, &display_rect, &draw_rect); + return RenderDisplay(nullptr, display_rect, draw_rect, !g_gpu_settings.gpu_show_vram); } GPUDevice::PresentResult GPUBackend::RenderDisplay(GPUTexture* target, const GSVector4i display_rect, @@ -943,7 +943,7 @@ GPUDevice::PresentResult GPUBackend::RenderDisplay(GPUTexture* target, const GSV if (really_postfx) { - DebugAssert(!g_gpu_settings.debugging.show_vram); + DebugAssert(!g_gpu_settings.gpu_show_vram); // "original size" in postfx includes padding. const float upscale_x = @@ -978,7 +978,7 @@ void GPUBackend::SendDisplayToMediaCapture(MediaCapture* cap) (g_gpu_settings.display_screenshot_mode != DisplayScreenshotMode::UncorrectedInternalResolution); const bool postfx = (g_gpu_settings.display_screenshot_mode != DisplayScreenshotMode::InternalResolution); GSVector4i display_rect, draw_rect; - CalculateDrawRect(target->GetWidth(), target->GetHeight(), !g_gpu_settings.debugging.show_vram, apply_aspect_ratio, + CalculateDrawRect(target->GetWidth(), target->GetHeight(), !g_gpu_settings.gpu_show_vram, apply_aspect_ratio, &display_rect, &draw_rect); // Not cleared by RenderDisplay(). @@ -1228,7 +1228,7 @@ void GPUBackend::CalculateDrawRect(s32 window_width, s32 window_height, bool app { const bool integer_scale = (g_gpu_settings.display_scaling == DisplayScalingMode::NearestInteger || g_gpu_settings.display_scaling == DisplayScalingMode::BilinearInteger); - const bool show_vram = g_gpu_settings.debugging.show_vram; + const bool show_vram = g_gpu_settings.gpu_show_vram; const u32 display_width = show_vram ? VRAM_WIDTH : m_display_width; const u32 display_height = show_vram ? VRAM_HEIGHT : m_display_height; const s32 display_origin_left = show_vram ? 0 : m_display_origin_left; @@ -1421,15 +1421,14 @@ bool GPUBackend::RenderScreenshotToBuffer(u32 width, u32 height, const GSVector4 void GPUBackend::CalculateScreenshotSize(DisplayScreenshotMode mode, u32* width, u32* height, GSVector4i* display_rect, GSVector4i* draw_rect) const { - const bool internal_resolution = - (mode != DisplayScreenshotMode::ScreenResolution || g_gpu_settings.debugging.show_vram); + const bool internal_resolution = (mode != DisplayScreenshotMode::ScreenResolution || g_gpu_settings.gpu_show_vram); if (internal_resolution && m_display_texture_view_width != 0 && m_display_texture_view_height != 0) { if (mode == DisplayScreenshotMode::InternalResolution) { float f_width = static_cast(m_display_texture_view_width); float f_height = static_cast(m_display_texture_view_height); - if (!g_gpu_settings.debugging.show_vram) + if (!g_gpu_settings.gpu_show_vram) GPU::ApplyPixelAspectRatioToSize(m_display_pixel_aspect_ratio, &f_width, &f_height); // DX11 won't go past 16K texture size. @@ -1462,7 +1461,7 @@ void GPUBackend::CalculateScreenshotSize(DisplayScreenshotMode mode, u32* width, { *width = g_gpu_device->HasMainSwapChain() ? g_gpu_device->GetMainSwapChain()->GetWidth() : 1; *height = g_gpu_device->HasMainSwapChain() ? g_gpu_device->GetMainSwapChain()->GetHeight() : 1; - CalculateDrawRect(*width, *height, true, !g_settings.debugging.show_vram, display_rect, draw_rect); + CalculateDrawRect(*width, *height, true, !g_settings.gpu_show_vram, display_rect, draw_rect); } } diff --git a/src/core/gpu_backend.h b/src/core/gpu_backend.h index e75cca3103..2808cce4f1 100644 --- a/src/core/gpu_backend.h +++ b/src/core/gpu_backend.h @@ -22,7 +22,7 @@ class SmallStringBase; class GPUFramebuffer; class GPUPipeline; -struct Settings; +struct GPUSettings; class StateWrapper; namespace System { @@ -77,7 +77,7 @@ class GPUBackend virtual bool Initialize(bool upload_vram, Error* error); - virtual void UpdateSettings(const Settings& old_settings); + virtual void UpdateSettings(const GPUSettings& old_settings); /// Returns the current resolution scale. virtual u32 GetResolutionScale() const = 0; diff --git a/src/core/gpu_commands.cpp b/src/core/gpu_commands.cpp index df7d46df69..5ee6d540e1 100644 --- a/src/core/gpu_commands.cpp +++ b/src/core/gpu_commands.cpp @@ -931,7 +931,7 @@ void GPU::FinishVRAMWrite() if (m_blit_remaining_words == 0) { - if (g_settings.debugging.dump_cpu_to_vram_copies) + if (g_settings.gpu_dump_cpu_to_vram_copies) { DumpVRAMToFile(TinyString::from_format("cpu_to_vram_copy_{}.png", s_cpu_to_vram_dump_id++), m_vram_transfer.width, m_vram_transfer.height, sizeof(u16) * m_vram_transfer.width, m_blit_buffer.data(), true); @@ -995,7 +995,7 @@ bool GPU::HandleCopyRectangleVRAMToCPUCommand() // ensure VRAM shadow is up to date ReadVRAM(m_vram_transfer.x, m_vram_transfer.y, m_vram_transfer.width, m_vram_transfer.height); - if (g_settings.debugging.dump_vram_to_cpu_copies) + if (g_settings.gpu_dump_vram_to_cpu_copies) { DumpVRAMToFile(TinyString::from_format("vram_to_cpu_copy_{}.png", s_vram_to_cpu_dump_id++), m_vram_transfer.width, m_vram_transfer.height, sizeof(u16) * VRAM_WIDTH, diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 75ad8255b2..56af8ede0d 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -439,7 +439,7 @@ void GPU_HW::RestoreDeviceContext() m_batch_ubo_dirty = true; } -void GPU_HW::UpdateSettings(const Settings& old_settings) +void GPU_HW::UpdateSettings(const GPUSettings& old_settings) { GPUBackend::UpdateSettings(old_settings); @@ -3669,7 +3669,7 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) GPUTextureCache::Compact(); - if (g_gpu_settings.debugging.show_vram) + if (g_gpu_settings.gpu_show_vram) { if (IsUsingMultisampling()) { diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index 0b27723638..70606999ef 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -72,7 +72,7 @@ class GPU_HW final : public GPUBackend void RestoreDeviceContext() override; protected: - void UpdateSettings(const Settings& old_settings) override; + void UpdateSettings(const GPUSettings& old_settings) override; void UpdateResolutionScale() override; diff --git a/src/core/gpu_hw_texture_cache.cpp b/src/core/gpu_hw_texture_cache.cpp index 0b7a3182e2..fe703efbb1 100644 --- a/src/core/gpu_hw_texture_cache.cpp +++ b/src/core/gpu_hw_texture_cache.cpp @@ -590,7 +590,7 @@ bool GPUTextureCache::Initialize(GPU_HW* backend) return true; } -void GPUTextureCache::UpdateSettings(bool use_texture_cache, const Settings& old_settings) +void GPUTextureCache::UpdateSettings(bool use_texture_cache, const GPUSettings& old_settings) { if (use_texture_cache) { diff --git a/src/core/gpu_hw_texture_cache.h b/src/core/gpu_hw_texture_cache.h index 9b72cf7b2c..f8023da49f 100644 --- a/src/core/gpu_hw_texture_cache.h +++ b/src/core/gpu_hw_texture_cache.h @@ -9,7 +9,7 @@ class Image; class GPUTexture; class StateWrapper; -struct Settings; +struct GPUSettings; class GPU_HW; ////////////////////////////////////////////////////////////////////////// @@ -104,7 +104,7 @@ struct Source }; bool Initialize(GPU_HW* backend); -void UpdateSettings(bool use_texture_cache, const Settings& old_settings); +void UpdateSettings(bool use_texture_cache, const GPUSettings& old_settings); bool GetStateSize(StateWrapper& sw, u32* size); bool DoState(StateWrapper& sw, bool skip); diff --git a/src/core/gpu_sw.cpp b/src/core/gpu_sw.cpp index b22cf56984..7f33cb423d 100644 --- a/src/core/gpu_sw.cpp +++ b/src/core/gpu_sw.cpp @@ -356,7 +356,7 @@ bool GPU_SW::CopyOut(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height, u3 void GPU_SW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd) { - if (!g_settings.debugging.show_vram) + if (!g_settings.gpu_show_vram) { if (cmd->display_disabled) { diff --git a/src/core/gpu_thread.cpp b/src/core/gpu_thread.cpp index 7f538a932f..668714768b 100644 --- a/src/core/gpu_thread.cpp +++ b/src/core/gpu_thread.cpp @@ -36,9 +36,6 @@ LOG_CHANNEL(GPUThread); -// TODO: Smaller settings struct. -// TODO: Remove g_gpu pointer. - namespace GPUThread { enum : u32 { @@ -83,7 +80,7 @@ static void ReconfigureOnThread(GPUThreadReconfigureCommand* cmd); static bool CreateGPUBackendOnThread(GPURenderer renderer, bool upload_vram, Error* error); static void DestroyGPUBackendOnThread(); -static void UpdateSettingsOnThread(const Settings& old_settings); +static void UpdateSettingsOnThread(const GPUSettings& old_settings); static void UpdateRunIdle(); @@ -932,7 +929,7 @@ void GPUThread::DestroyGPUBackendOnThread() s_state.gpu_backend.reset(); } -void GPUThread::UpdateSettingsOnThread(const Settings& old_settings) +void GPUThread::UpdateSettingsOnThread(const GPUSettings& old_settings) { if (g_gpu_device) { @@ -1008,7 +1005,7 @@ void GPUThread::UpdateSettings(bool gpu_settings_changed, bool device_settings_c RunOnThread([settings = g_settings]() { VERBOSE_LOG("Updating GPU settings on thread..."); - Settings old_settings = std::move(g_gpu_settings); + GPUSettings old_settings = std::move(g_gpu_settings); g_gpu_settings = std::move(settings); UpdateSettingsOnThread(old_settings); diff --git a/src/core/imgui_overlays.cpp b/src/core/imgui_overlays.cpp index c9de11ddb8..160a534ca7 100644 --- a/src/core/imgui_overlays.cpp +++ b/src/core/imgui_overlays.cpp @@ -453,29 +453,29 @@ void ImGuiManager::DrawEnhancementsOverlay(const GPUBackend* gpu) text.append_format(" CDR={}x", g_settings.cdrom_read_speedup); if (g_settings.cdrom_seek_speedup != 1) text.append_format(" CDS={}x", g_settings.cdrom_seek_speedup); - if (g_settings.gpu_resolution_scale != 1) - text.append_format(" IR={}x", g_settings.gpu_resolution_scale); - if (g_settings.gpu_multisamples != 1) + if (g_gpu_settings.gpu_resolution_scale != 1) + text.append_format(" IR={}x", g_gpu_settings.gpu_resolution_scale); + if (g_gpu_settings.gpu_multisamples != 1) { - text.append_format(" {}x{}", g_settings.gpu_multisamples, g_settings.gpu_per_sample_shading ? "SSAA" : "MSAA"); + text.append_format(" {}x{}", g_gpu_settings.gpu_multisamples, g_gpu_settings.gpu_per_sample_shading ? "SSAA" : "MSAA"); } - if (g_settings.gpu_true_color) + if (g_gpu_settings.gpu_true_color) text.append(" TrueCol"); - text.append_format(" DI={}", Settings::GetDisplayDeinterlacingModeName(g_settings.display_deinterlacing_mode)); + text.append_format(" DI={}", Settings::GetDisplayDeinterlacingModeName(g_gpu_settings.display_deinterlacing_mode)); if (g_settings.gpu_force_video_timing == ForceVideoTimingMode::NTSC && System::GetRegion() == ConsoleRegion::PAL) text.append(" PAL60"); if (g_settings.gpu_force_video_timing == ForceVideoTimingMode::PAL && System::GetRegion() != ConsoleRegion::PAL) text.append(" NTSC50"); - if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest) + if (g_gpu_settings.gpu_texture_filter != GPUTextureFilter::Nearest) { - if (g_settings.gpu_sprite_texture_filter != g_settings.gpu_texture_filter) + if (g_gpu_settings.gpu_sprite_texture_filter != g_gpu_settings.gpu_texture_filter) { - text.append_format(" {}/{}", Settings::GetTextureFilterName(g_settings.gpu_texture_filter), - Settings::GetTextureFilterName(g_settings.gpu_sprite_texture_filter)); + text.append_format(" {}/{}", Settings::GetTextureFilterName(g_gpu_settings.gpu_texture_filter), + Settings::GetTextureFilterName(g_gpu_settings.gpu_sprite_texture_filter)); } else { - text.append_format(" {}", Settings::GetTextureFilterName(g_settings.gpu_texture_filter)); + text.append_format(" {}", Settings::GetTextureFilterName(g_gpu_settings.gpu_texture_filter)); } } if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio != DisplayAspectRatio::Auto && @@ -483,8 +483,8 @@ void ImGuiManager::DrawEnhancementsOverlay(const GPUBackend* gpu) { text.append(" WSHack"); } - if (g_settings.gpu_line_detect_mode != GPULineDetectMode::Disabled) - text.append_format(" LD={}", Settings::GetLineDetectModeName(g_settings.gpu_line_detect_mode)); + if (g_gpu_settings.gpu_line_detect_mode != GPULineDetectMode::Disabled) + text.append_format(" LD={}", Settings::GetLineDetectModeName(g_gpu_settings.gpu_line_detect_mode)); if (g_settings.gpu_pgxp_enable) { text.append(" PGXP"); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index b803dd5b98..976ea804ec 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -30,7 +30,7 @@ LOG_CHANNEL(Settings); ALIGN_TO_CACHE_LINE Settings g_settings; -ALIGN_TO_CACHE_LINE Settings g_gpu_settings; +ALIGN_TO_CACHE_LINE GPUSettings g_gpu_settings; const char* SettingInfo::StringDefaultValue() const { @@ -88,6 +88,8 @@ float SettingInfo::FloatStepValue() const return step_value ? StringUtil::FromChars(step_value).value_or(fallback_value) : fallback_value; } +GPUSettings::GPUSettings() = default; + #ifdef DYNAMIC_HOST_PAGE_SIZE // See note in settings.h - 16K ends up faster with LUT because of nearby code/data. const CPUFastmemMode Settings::DEFAULT_CPU_FASTMEM_MODE = @@ -253,6 +255,9 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro gpu_pgxp_depth_buffer = si.GetBoolValue("GPU", "PGXPDepthBuffer", false); gpu_pgxp_disable_2d = si.GetBoolValue("GPU", "PGXPDisableOn2DPolygons", false); SetPGXPDepthClearThreshold(si.GetFloatValue("GPU", "PGXPDepthClearThreshold", DEFAULT_GPU_PGXP_DEPTH_THRESHOLD)); + gpu_show_vram = si.GetBoolValue("Debug", "ShowVRAM"); + gpu_dump_cpu_to_vram_copies = si.GetBoolValue("Debug", "DumpCPUToVRAMCopies"); + gpu_dump_vram_to_cpu_copies = si.GetBoolValue("Debug", "DumpVRAMToCPUCopies"); gpu_dump_fast_replay_mode = si.GetBoolValue("GPU", "DumpFastReplayMode", false); display_deinterlacing_mode = @@ -424,13 +429,9 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro achievements_leaderboard_duration = si.GetIntValue("Cheevos", "LeaderboardsDuration", DEFAULT_LEADERBOARD_NOTIFICATION_TIME); - debugging.show_vram = si.GetBoolValue("Debug", "ShowVRAM"); - debugging.dump_cpu_to_vram_copies = si.GetBoolValue("Debug", "DumpCPUToVRAMCopies"); - debugging.dump_vram_to_cpu_copies = si.GetBoolValue("Debug", "DumpVRAMToCPUCopies"); - #ifndef __ANDROID__ - debugging.enable_gdb_server = si.GetBoolValue("Debug", "EnableGDBServer"); - debugging.gdb_server_port = static_cast(si.GetUIntValue("Debug", "GDBServerPort", DEFAULT_GDB_SERVER_PORT)); + enable_gdb_server = si.GetBoolValue("Debug", "EnableGDBServer"); + gdb_server_port = static_cast(si.GetUIntValue("Debug", "GDBServerPort", DEFAULT_GDB_SERVER_PORT)); #endif texture_replacements.enable_texture_replacements = @@ -585,6 +586,9 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const si.SetBoolValue("GPU", "PGXPDepthBuffer", gpu_pgxp_depth_buffer); si.SetBoolValue("GPU", "PGXPDisableOn2DPolygons", gpu_pgxp_disable_2d); si.SetFloatValue("GPU", "PGXPDepthClearThreshold", GetPGXPDepthClearThreshold()); + si.SetBoolValue("Debug", "ShowVRAM", gpu_show_vram); + si.SetBoolValue("Debug", "DumpCPUToVRAMCopies", gpu_dump_cpu_to_vram_copies); + si.SetBoolValue("Debug", "DumpVRAMToCPUCopies", gpu_dump_vram_to_cpu_copies); si.SetBoolValue("GPU", "DumpFastReplayMode", gpu_dump_fast_replay_mode); si.SetStringValue("GPU", "DeinterlacingMode", GetDisplayDeinterlacingModeName(display_deinterlacing_mode)); @@ -701,17 +705,10 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const si.SetIntValue("Cheevos", "NotificationsDuration", achievements_notification_duration); si.SetIntValue("Cheevos", "LeaderboardsDuration", achievements_leaderboard_duration); - if (!ignore_base) - { - si.SetBoolValue("Debug", "ShowVRAM", debugging.show_vram); - si.SetBoolValue("Debug", "DumpCPUToVRAMCopies", debugging.dump_cpu_to_vram_copies); - si.SetBoolValue("Debug", "DumpVRAMToCPUCopies", debugging.dump_vram_to_cpu_copies); - #ifndef __ANDROID__ - si.SetBoolValue("Debug", "EnableGDBServer", debugging.enable_gdb_server); - si.SetUIntValue("Debug", "GDBServerPort", debugging.gdb_server_port); + si.SetBoolValue("Debug", "EnableGDBServer", enable_gdb_server); + si.SetUIntValue("Debug", "GDBServerPort", gdb_server_port); #endif - } si.SetBoolValue("TextureReplacements", "EnableTextureReplacements", texture_replacements.enable_texture_replacements); si.SetBoolValue("TextureReplacements", "EnableVRAMWriteReplacements", @@ -1083,12 +1080,12 @@ void Settings::FixIncompatibleSettings(const SettingsInterface& si, bool display } #ifndef __ANDROID__ - g_settings.debugging.enable_gdb_server = false; + g_settings.enable_gdb_server = false; #endif - g_settings.debugging.show_vram = false; - g_settings.debugging.dump_cpu_to_vram_copies = false; - g_settings.debugging.dump_vram_to_cpu_copies = false; + g_settings.gpu_show_vram = false; + g_settings.gpu_dump_cpu_to_vram_copies = false; + g_settings.gpu_dump_vram_to_cpu_copies = false; } } @@ -1783,7 +1780,7 @@ const char* Settings::GetDisplayAspectRatioDisplayName(DisplayAspectRatio ar) "DisplayAspectRatio"); } -float Settings::GetDisplayAspectRatioValue() const +float GPUSettings::GetDisplayAspectRatioValue() const { return s_display_aspect_ratio_values[static_cast(display_aspect_ratio)]; } diff --git a/src/core/settings.h b/src/core/settings.h index 8b02e3bce6..96ff897154 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -57,48 +57,17 @@ struct SettingInfo float FloatStepValue() const; }; -struct Settings +struct GPUSettings { - Settings(); - - ConsoleRegion region = DEFAULT_CONSOLE_REGION; + GPUSettings(); - CPUExecutionMode cpu_execution_mode = DEFAULT_CPU_EXECUTION_MODE; - CPUFastmemMode cpu_fastmem_mode = DEFAULT_CPU_FASTMEM_MODE; - bool cpu_overclock_enable : 1 = false; - bool cpu_overclock_active : 1 = false; - bool cpu_recompiler_memory_exceptions : 1 = false; - bool cpu_recompiler_block_linking : 1 = true; - bool cpu_recompiler_icache : 1 = false; - u32 cpu_overclock_numerator = 1; - u32 cpu_overclock_denominator = 1; - - float emulation_speed = 1.0f; - float fast_forward_speed = 0.0f; - float turbo_speed = 0.0f; - bool sync_to_host_refresh_rate : 1 = false; - bool inhibit_screensaver : 1 = true; - bool pause_on_focus_loss : 1 = false; - bool pause_on_controller_disconnection : 1 = false; - bool save_state_on_exit : 1 = true; - bool create_save_state_backups : 1 = DEFAULT_SAVE_STATE_BACKUPS; - bool confim_power_off : 1 = true; - bool load_devices_from_save_states : 1 = false; - bool apply_compatibility_settings : 1 = true; - bool apply_game_settings : 1 = true; - bool disable_all_enhancements : 1 = false; - bool enable_discord_presence : 1 = false; - - bool rewind_enable : 1 = false; - float rewind_save_frequency = 10.0f; - u16 rewind_save_slots = 10; - u8 runahead_frames = 0; + std::string gpu_adapter; GPURenderer gpu_renderer = DEFAULT_GPU_RENDERER; - std::string gpu_adapter; u8 gpu_resolution_scale = 1; u8 gpu_multisamples = 1; u8 gpu_max_queued_frames = DEFAULT_GPU_MAX_QUEUED_FRAMES; + bool gpu_use_thread : 1 = true; bool gpu_use_software_renderer_for_readbacks : 1 = false; bool gpu_use_debug_device : 1 = false; @@ -118,6 +87,11 @@ struct Settings bool gpu_accurate_blending : 1 = false; bool gpu_widescreen_hack : 1 = false; bool gpu_texture_cache : 1 = false; + bool gpu_show_vram : 1 = false; + bool gpu_dump_cpu_to_vram_copies : 1 = false; + bool gpu_dump_vram_to_cpu_copies : 1 = false; + bool gpu_dump_fast_replay_mode : 1 = false; + bool gpu_pgxp_enable : 1 = false; bool gpu_pgxp_culling : 1 = true; bool gpu_pgxp_texture_correction : 1 = true; @@ -127,6 +101,7 @@ struct Settings bool gpu_pgxp_preserve_proj_fp : 1 = false; bool gpu_pgxp_depth_buffer : 1 = false; bool gpu_pgxp_disable_2d : 1 = false; + ForceVideoTimingMode gpu_force_video_timing = DEFAULT_FORCE_VIDEO_TIMING_MODE; GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER; GPUTextureFilter gpu_sprite_texture_filter = DEFAULT_GPU_TEXTURE_FILTER; @@ -176,62 +151,6 @@ struct Settings float gpu_pgxp_tolerance = -1.0f; float gpu_pgxp_depth_clear_threshold = DEFAULT_GPU_PGXP_DEPTH_THRESHOLD / GPU_PGXP_DEPTH_THRESHOLD_SCALE; - SaveStateCompressionMode save_state_compression = DEFAULT_SAVE_STATE_COMPRESSION_MODE; - - u8 cdrom_readahead_sectors = DEFAULT_CDROM_READAHEAD_SECTORS; - CDROMMechaconVersion cdrom_mechacon_version = DEFAULT_CDROM_MECHACON_VERSION; - bool cdrom_region_check : 1 = false; - bool cdrom_subq_skew : 1 = false; - bool cdrom_load_image_to_ram : 1 = false; - bool cdrom_load_image_patches : 1 = false; - bool cdrom_mute_cd_audio : 1 = false; - u32 cdrom_read_speedup = 1; - u32 cdrom_seek_speedup = 1; - - std::string audio_driver; - std::string audio_output_device; - u32 audio_output_volume = 100; - u32 audio_fast_forward_volume = 100; - AudioStreamParameters audio_stream_parameters; - AudioBackend audio_backend = AudioStream::DEFAULT_BACKEND; - bool audio_output_muted : 1 = false; - - bool use_old_mdec_routines : 1 = false; - bool pcdrv_enable : 1 = false; - bool export_shared_memory : 1 = false; - - // timing hacks section - TickCount dma_max_slice_ticks = DEFAULT_DMA_MAX_SLICE_TICKS; - TickCount dma_halt_ticks = DEFAULT_DMA_HALT_TICKS; - u32 gpu_fifo_size = DEFAULT_GPU_FIFO_SIZE; - TickCount gpu_max_run_ahead = DEFAULT_GPU_MAX_RUN_AHEAD; - - // achievements - bool achievements_enabled : 1 = false; - bool achievements_hardcore_mode : 1 = false; - bool achievements_notifications : 1 = true; - bool achievements_leaderboard_notifications : 1 = true; - bool achievements_sound_effects : 1 = true; - bool achievements_overlays : 1 = true; - bool achievements_encore_mode : 1 = false; - bool achievements_spectator_mode : 1 = false; - bool achievements_unofficial_test_mode : 1 = false; - bool achievements_use_raintegration : 1 = false; - s32 achievements_notification_duration = DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME; - s32 achievements_leaderboard_duration = DEFAULT_LEADERBOARD_NOTIFICATION_TIME; - - struct DebugSettings - { -#ifndef __ANDROID__ - u16 gdb_server_port = DEFAULT_GDB_SERVER_PORT; - bool enable_gdb_server : 1 = false; -#endif - - bool show_vram : 1 = false; - bool dump_cpu_to_vram_copies : 1 = false; - bool dump_vram_to_cpu_copies : 1 = false; - } debugging; - // texture replacements struct TextureReplacementSettings { @@ -285,11 +204,143 @@ struct Settings bool operator!=(const TextureReplacementSettings& rhs) const; } texture_replacements; + float GetDisplayAspectRatioValue() const; + + ALWAYS_INLINE bool IsUsingSoftwareRenderer() const { return (gpu_renderer == GPURenderer::Software); } + ALWAYS_INLINE bool IsUsingAccurateBlending() const { return (gpu_accurate_blending && !gpu_true_color); } + + ALWAYS_INLINE bool UsingPGXPCPUMode() const { return gpu_pgxp_enable && gpu_pgxp_cpu; } + ALWAYS_INLINE bool UsingPGXPDepthBuffer() const { return gpu_pgxp_enable && gpu_pgxp_depth_buffer; } + ALWAYS_INLINE float GetPGXPDepthClearThreshold() const + { + return gpu_pgxp_depth_clear_threshold * GPU_PGXP_DEPTH_THRESHOLD_SCALE; + } + ALWAYS_INLINE void SetPGXPDepthClearThreshold(float value) + { + gpu_pgxp_depth_clear_threshold = value / GPU_PGXP_DEPTH_THRESHOLD_SCALE; + } + + static constexpr GPURenderer DEFAULT_GPU_RENDERER = GPURenderer::Automatic; + static constexpr GPUTextureFilter DEFAULT_GPU_TEXTURE_FILTER = GPUTextureFilter::Nearest; + static constexpr GPULineDetectMode DEFAULT_GPU_LINE_DETECT_MODE = GPULineDetectMode::Disabled; + static constexpr GPUDownsampleMode DEFAULT_GPU_DOWNSAMPLE_MODE = GPUDownsampleMode::Disabled; + static constexpr GPUWireframeMode DEFAULT_GPU_WIREFRAME_MODE = GPUWireframeMode::Disabled; + static constexpr GPUDumpCompressionMode DEFAULT_GPU_DUMP_COMPRESSION_MODE = GPUDumpCompressionMode::ZstDefault; + static constexpr float DEFAULT_GPU_PGXP_DEPTH_THRESHOLD = 300.0f; + static constexpr float GPU_PGXP_DEPTH_THRESHOLD_SCALE = 4096.0f; + + static constexpr DisplayDeinterlacingMode DEFAULT_DISPLAY_DEINTERLACING_MODE = DisplayDeinterlacingMode::Progressive; + static constexpr DisplayCropMode DEFAULT_DISPLAY_CROP_MODE = DisplayCropMode::Overscan; + static constexpr DisplayAspectRatio DEFAULT_DISPLAY_ASPECT_RATIO = DisplayAspectRatio::Auto; + static constexpr DisplayAlignment DEFAULT_DISPLAY_ALIGNMENT = DisplayAlignment::Center; + static constexpr DisplayRotation DEFAULT_DISPLAY_ROTATION = DisplayRotation::Normal; + static constexpr DisplayScalingMode DEFAULT_DISPLAY_SCALING = DisplayScalingMode::BilinearSmooth; + static constexpr ForceVideoTimingMode DEFAULT_FORCE_VIDEO_TIMING_MODE = ForceVideoTimingMode::Disabled; + static constexpr DisplayExclusiveFullscreenControl DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL = + DisplayExclusiveFullscreenControl::Automatic; + static constexpr DisplayScreenshotMode DEFAULT_DISPLAY_SCREENSHOT_MODE = DisplayScreenshotMode::ScreenResolution; + static constexpr DisplayScreenshotFormat DEFAULT_DISPLAY_SCREENSHOT_FORMAT = DisplayScreenshotFormat::PNG; + static constexpr u8 DEFAULT_DISPLAY_SCREENSHOT_QUALITY = 85; + static constexpr float DEFAULT_DISPLAY_PRE_FRAME_SLEEP_BUFFER = 2.0f; + static constexpr float DEFAULT_OSD_SCALE = 100.0f; + +#ifndef __ANDROID__ + static constexpr u8 DEFAULT_GPU_MAX_QUEUED_FRAMES = 2; +#else + static constexpr u8 DEFAULT_GPU_MAX_QUEUED_FRAMES = 3; +#endif +}; + +struct Settings : public GPUSettings +{ + Settings(); + + ConsoleRegion region = DEFAULT_CONSOLE_REGION; + + CPUExecutionMode cpu_execution_mode = DEFAULT_CPU_EXECUTION_MODE; + CPUFastmemMode cpu_fastmem_mode = DEFAULT_CPU_FASTMEM_MODE; + bool cpu_overclock_enable : 1 = false; + bool cpu_overclock_active : 1 = false; + bool cpu_recompiler_memory_exceptions : 1 = false; + bool cpu_recompiler_block_linking : 1 = true; + bool cpu_recompiler_icache : 1 = false; + u32 cpu_overclock_numerator = 1; + u32 cpu_overclock_denominator = 1; + + float emulation_speed = 1.0f; + float fast_forward_speed = 0.0f; + float turbo_speed = 0.0f; + bool sync_to_host_refresh_rate : 1 = false; + bool inhibit_screensaver : 1 = true; + bool pause_on_focus_loss : 1 = false; + bool pause_on_controller_disconnection : 1 = false; + bool save_state_on_exit : 1 = true; + bool create_save_state_backups : 1 = DEFAULT_SAVE_STATE_BACKUPS; + bool confim_power_off : 1 = true; + bool load_devices_from_save_states : 1 = false; + bool apply_compatibility_settings : 1 = true; + bool apply_game_settings : 1 = true; + bool disable_all_enhancements : 1 = false; + bool enable_discord_presence : 1 = false; + + bool rewind_enable : 1 = false; + float rewind_save_frequency = 10.0f; + u16 rewind_save_slots = 10; + u8 runahead_frames = 0; + + SaveStateCompressionMode save_state_compression = DEFAULT_SAVE_STATE_COMPRESSION_MODE; + + u8 cdrom_readahead_sectors = DEFAULT_CDROM_READAHEAD_SECTORS; + CDROMMechaconVersion cdrom_mechacon_version = DEFAULT_CDROM_MECHACON_VERSION; + bool cdrom_region_check : 1 = false; + bool cdrom_subq_skew : 1 = false; + bool cdrom_load_image_to_ram : 1 = false; + bool cdrom_load_image_patches : 1 = false; + bool cdrom_mute_cd_audio : 1 = false; + u32 cdrom_read_speedup = 1; + u32 cdrom_seek_speedup = 1; + + std::string audio_driver; + std::string audio_output_device; + u32 audio_output_volume = 100; + u32 audio_fast_forward_volume = 100; + AudioStreamParameters audio_stream_parameters; + AudioBackend audio_backend = AudioStream::DEFAULT_BACKEND; + bool audio_output_muted : 1 = false; + + bool use_old_mdec_routines : 1 = false; + bool pcdrv_enable : 1 = false; + bool export_shared_memory : 1 = false; + + // timing hacks section + TickCount dma_max_slice_ticks = DEFAULT_DMA_MAX_SLICE_TICKS; + TickCount dma_halt_ticks = DEFAULT_DMA_HALT_TICKS; + u32 gpu_fifo_size = DEFAULT_GPU_FIFO_SIZE; + TickCount gpu_max_run_ahead = DEFAULT_GPU_MAX_RUN_AHEAD; + + // achievements + bool achievements_enabled : 1 = false; + bool achievements_hardcore_mode : 1 = false; + bool achievements_notifications : 1 = true; + bool achievements_leaderboard_notifications : 1 = true; + bool achievements_sound_effects : 1 = true; + bool achievements_overlays : 1 = true; + bool achievements_encore_mode : 1 = false; + bool achievements_spectator_mode : 1 = false; + bool achievements_unofficial_test_mode : 1 = false; + bool achievements_use_raintegration : 1 = false; + s32 achievements_notification_duration = DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME; + s32 achievements_leaderboard_duration = DEFAULT_LEADERBOARD_NOTIFICATION_TIME; + +#ifndef __ANDROID__ + u16 gdb_server_port = DEFAULT_GDB_SERVER_PORT; + bool enable_gdb_server : 1 = false; +#endif + bool bios_tty_logging : 1 = false; bool bios_patch_fast_boot : 1 = DEFAULT_FAST_BOOT_VALUE; bool bios_fast_forward_boot : 1 = false; bool enable_8mb_ram : 1 = false; - bool gpu_dump_fast_replay_mode : 1 = false; std::array controller_types{}; std::array memory_card_types{}; @@ -306,33 +357,14 @@ struct Settings std::string pcdrv_root; bool pcdrv_enable_writes = false; - ALWAYS_INLINE bool IsUsingSoftwareRenderer() const { return (gpu_renderer == GPURenderer::Software); } - ALWAYS_INLINE bool IsUsingAccurateBlending() const { return (gpu_accurate_blending && !gpu_true_color); } ALWAYS_INLINE bool IsRunaheadEnabled() const { return (runahead_frames > 0); } - ALWAYS_INLINE PGXPMode GetPGXPMode() - { - return gpu_pgxp_enable ? (gpu_pgxp_cpu ? PGXPMode::CPU : PGXPMode::Memory) : PGXPMode::Disabled; - } - - ALWAYS_INLINE bool UsingPGXPDepthBuffer() const { return gpu_pgxp_enable && gpu_pgxp_depth_buffer; } - ALWAYS_INLINE bool UsingPGXPCPUMode() const { return gpu_pgxp_enable && gpu_pgxp_cpu; } - ALWAYS_INLINE float GetPGXPDepthClearThreshold() const - { - return gpu_pgxp_depth_clear_threshold * GPU_PGXP_DEPTH_THRESHOLD_SCALE; - } - ALWAYS_INLINE void SetPGXPDepthClearThreshold(float value) - { - gpu_pgxp_depth_clear_threshold = value / GPU_PGXP_DEPTH_THRESHOLD_SCALE; - } ALWAYS_INLINE s32 GetAudioOutputVolume(bool fast_forwarding) const { return audio_output_muted ? 0 : (fast_forwarding ? audio_fast_forward_volume : audio_output_volume); } - float GetDisplayAspectRatioValue() const; - ALWAYS_INLINE bool IsPort1MultitapEnabled() const { return (multitap_mode == MultitapMode::Port1Only || multitap_mode == MultitapMode::BothPorts); @@ -498,15 +530,7 @@ struct Settings static const char* GetPIODeviceTypeModeName(PIODeviceType type); static const char* GetPIODeviceTypeModeDisplayName(PIODeviceType type); - static constexpr GPURenderer DEFAULT_GPU_RENDERER = GPURenderer::Automatic; - static constexpr GPUTextureFilter DEFAULT_GPU_TEXTURE_FILTER = GPUTextureFilter::Nearest; - static constexpr GPULineDetectMode DEFAULT_GPU_LINE_DETECT_MODE = GPULineDetectMode::Disabled; - static constexpr GPUDownsampleMode DEFAULT_GPU_DOWNSAMPLE_MODE = GPUDownsampleMode::Disabled; - static constexpr GPUWireframeMode DEFAULT_GPU_WIREFRAME_MODE = GPUWireframeMode::Disabled; - static constexpr GPUDumpCompressionMode DEFAULT_GPU_DUMP_COMPRESSION_MODE = GPUDumpCompressionMode::ZstDefault; static constexpr ConsoleRegion DEFAULT_CONSOLE_REGION = ConsoleRegion::Auto; - static constexpr float DEFAULT_GPU_PGXP_DEPTH_THRESHOLD = 300.0f; - static constexpr float GPU_PGXP_DEPTH_THRESHOLD_SCALE = 4096.0f; // Prefer recompiler when supported. #ifdef ENABLE_RECOMPILER @@ -524,21 +548,6 @@ struct Settings static constexpr CPUFastmemMode DEFAULT_CPU_FASTMEM_MODE = CPUFastmemMode::LUT; #endif - static constexpr DisplayDeinterlacingMode DEFAULT_DISPLAY_DEINTERLACING_MODE = DisplayDeinterlacingMode::Progressive; - static constexpr DisplayCropMode DEFAULT_DISPLAY_CROP_MODE = DisplayCropMode::Overscan; - static constexpr DisplayAspectRatio DEFAULT_DISPLAY_ASPECT_RATIO = DisplayAspectRatio::Auto; - static constexpr DisplayAlignment DEFAULT_DISPLAY_ALIGNMENT = DisplayAlignment::Center; - static constexpr DisplayRotation DEFAULT_DISPLAY_ROTATION = DisplayRotation::Normal; - static constexpr DisplayScalingMode DEFAULT_DISPLAY_SCALING = DisplayScalingMode::BilinearSmooth; - static constexpr ForceVideoTimingMode DEFAULT_FORCE_VIDEO_TIMING_MODE = ForceVideoTimingMode::Disabled; - static constexpr DisplayExclusiveFullscreenControl DEFAULT_DISPLAY_EXCLUSIVE_FULLSCREEN_CONTROL = - DisplayExclusiveFullscreenControl::Automatic; - static constexpr DisplayScreenshotMode DEFAULT_DISPLAY_SCREENSHOT_MODE = DisplayScreenshotMode::ScreenResolution; - static constexpr DisplayScreenshotFormat DEFAULT_DISPLAY_SCREENSHOT_FORMAT = DisplayScreenshotFormat::PNG; - static constexpr u8 DEFAULT_DISPLAY_SCREENSHOT_QUALITY = 85; - static constexpr float DEFAULT_DISPLAY_PRE_FRAME_SLEEP_BUFFER = 2.0f; - static constexpr float DEFAULT_OSD_SCALE = 100.0f; - static constexpr u8 DEFAULT_CDROM_READAHEAD_SECTORS = 8; static constexpr CDROMMechaconVersion DEFAULT_CDROM_MECHACON_VERSION = CDROMMechaconVersion::VC1A; @@ -568,19 +577,14 @@ struct Settings static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = true; static constexpr bool DEFAULT_FAST_BOOT_VALUE = false; static constexpr u16 DEFAULT_GDB_SERVER_PORT = 2345; - - // TODO: Maybe lower? But that means fast CPU threads would always stall, could be a problem for power management. - static constexpr u8 DEFAULT_GPU_MAX_QUEUED_FRAMES = 2; #else static constexpr bool DEFAULT_SAVE_STATE_BACKUPS = false; static constexpr bool DEFAULT_FAST_BOOT_VALUE = true; - static constexpr u8 DEFAULT_GPU_MAX_QUEUED_FRAMES = 3; #endif }; -// TODO: Use smaller copy for GPU thread copy. -ALIGN_TO_CACHE_LINE extern Settings g_settings; // CPU thread copy. -ALIGN_TO_CACHE_LINE extern Settings g_gpu_settings; // GPU thread copy. +ALIGN_TO_CACHE_LINE extern Settings g_settings; // CPU thread copy. +ALIGN_TO_CACHE_LINE extern GPUSettings g_gpu_settings; // GPU thread copy. namespace EmuFolders { extern std::string AppRoot; diff --git a/src/core/system.cpp b/src/core/system.cpp index ca141a18ec..38b7d95234 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -1827,8 +1827,8 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error) PlatformMisc::SuspendScreensaver(); #ifdef ENABLE_GDB_SERVER - if (g_settings.debugging.enable_gdb_server) - GDBServer::Initialize(g_settings.debugging.gdb_server_port); + if (g_settings.enable_gdb_server) + GDBServer::Initialize(g_settings.gdb_server_port); #endif Host::OnSystemStarted(); @@ -4413,7 +4413,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings) g_settings.display_active_end_offset != old_settings.display_active_end_offset || g_settings.display_line_start_offset != old_settings.display_line_start_offset || g_settings.display_line_end_offset != old_settings.display_line_end_offset || - g_settings.debugging.show_vram != old_settings.debugging.show_vram || + g_settings.gpu_show_vram != old_settings.gpu_show_vram || g_settings.rewind_enable != old_settings.rewind_enable || g_settings.runahead_frames != old_settings.runahead_frames || g_settings.texture_replacements.enable_texture_replacements != @@ -4432,7 +4432,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings) GPUThread::PresentCurrentFrame(); } else if (const bool device_settings_changed = g_settings.AreGPUDeviceSettingsChanged(old_settings); - device_settings_changed || g_settings.display_show_fps != old_settings.display_show_fps || + device_settings_changed || g_settings.display_show_fps != old_settings.display_show_fps || g_settings.display_show_speed != old_settings.display_show_speed || g_settings.display_show_gpu_stats != old_settings.display_show_gpu_stats || g_settings.display_show_resolution != old_settings.display_show_resolution || @@ -4550,12 +4550,12 @@ void System::CheckForSettingsChanges(const Settings& old_settings) } #ifdef ENABLE_GDB_SERVER - if (g_settings.debugging.enable_gdb_server != old_settings.debugging.enable_gdb_server || - g_settings.debugging.gdb_server_port != old_settings.debugging.gdb_server_port) + if (g_settings.enable_gdb_server != old_settings.enable_gdb_server || + g_settings.gdb_server_port != old_settings.gdb_server_port) { GDBServer::Shutdown(); - if (g_settings.debugging.enable_gdb_server) - GDBServer::Initialize(g_settings.debugging.gdb_server_port); + if (g_settings.enable_gdb_server) + GDBServer::Initialize(g_settings.gdb_server_port); } #endif } @@ -5678,7 +5678,7 @@ void System::RequestDisplaySize(float scale /*= 0.0f*/) scale = GPUBackend::IsUsingHardwareBackend() ? static_cast(g_settings.gpu_resolution_scale) : 1.0f; float requested_width, requested_height; - if (g_settings.debugging.show_vram) + if (g_settings.gpu_show_vram) { requested_width = static_cast(VRAM_WIDTH) * scale; requested_height = static_cast(VRAM_HEIGHT) * scale; From 01dfc9ae5152e0313f2ab96de967c83f7fed92ba Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 21 Dec 2024 14:54:37 +1000 Subject: [PATCH 4/5] GameDB: PGXP-CPU for Muppet Monster Adventure --- data/resources/gamedb.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/data/resources/gamedb.yaml b/data/resources/gamedb.yaml index 73e8721dc1..beb9679b1d 100644 --- a/data/resources/gamedb.yaml +++ b/data/resources/gamedb.yaml @@ -106687,6 +106687,8 @@ SCES-02403: controllers: - AnalogController - DigitalController + traits: + - ForcePGXPCPUMode # Fixes gaps in geometry. metadata: publisher: "Midway" developer: "Magenta Software Ltd. / Traveller's Tales" @@ -106706,6 +106708,8 @@ SCES-03090: controllers: - AnalogController - DigitalController + traits: + - ForcePGXPCPUMode # Fixes gaps in geometry. metadata: publisher: "Midway" developer: "Magenta Software Ltd. / Traveller's Tales" @@ -106725,6 +106729,8 @@ SCES-03091: controllers: - AnalogController - DigitalController + traits: + - ForcePGXPCPUMode # Fixes gaps in geometry. metadata: publisher: "Midway" developer: "Magenta Software Ltd. / Traveller's Tales" @@ -106744,6 +106750,8 @@ SCES-03092: controllers: - AnalogController - DigitalController + traits: + - ForcePGXPCPUMode # Fixes gaps in geometry. metadata: publisher: "Midway" developer: "Magenta Software Ltd. / Traveller's Tales" @@ -106763,6 +106771,8 @@ SCES-03093: controllers: - AnalogController - DigitalController + traits: + - ForcePGXPCPUMode # Fixes gaps in geometry. metadata: publisher: "Midway" developer: "Magenta Software Ltd. / Traveller's Tales" @@ -106782,6 +106792,8 @@ SLUS-01238: controllers: - AnalogController - DigitalController + traits: + - ForcePGXPCPUMode # Fixes gaps in geometry. metadata: publisher: "Midway" developer: "Magenta Software Ltd. / Traveller's Tales" From e1bd5690acfd4366a3c283462a554b10a66f5d1d Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 21 Dec 2024 15:28:04 +1000 Subject: [PATCH 5/5] Misc: Slightly reduce include pollution from settings.h --- src/core/analog_joystick.cpp | 15 ++++++++------- src/core/cheats.cpp | 1 + src/core/cpu_recompiler_x64.cpp | 1 + src/core/negcon.cpp | 15 ++++++++------- src/core/playstation_mouse.cpp | 1 + src/core/settings.h | 4 ++-- src/core/timing_event.cpp | 1 + 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/core/analog_joystick.cpp b/src/core/analog_joystick.cpp index a4ea53dce4..204af5af76 100644 --- a/src/core/analog_joystick.cpp +++ b/src/core/analog_joystick.cpp @@ -10,6 +10,7 @@ #include "common/bitutils.h" #include "common/log.h" +#include "common/settings_interface.h" #include "common/string_util.h" #include "IconsFontAwesome5.h" @@ -340,14 +341,14 @@ std::unique_ptr AnalogJoystick::Create(u32 index) static const Controller::ControllerBindingInfo s_binding_info[] = { #define BUTTON(name, display_name, icon_name, button, genb) \ - { \ - name, display_name, icon_name, static_cast(button), InputBindingInfo::Type::Button, genb \ - } + {name, display_name, icon_name, static_cast(button), InputBindingInfo::Type::Button, genb} #define AXIS(name, display_name, icon_name, halfaxis, genb) \ - { \ - name, display_name, icon_name, static_cast(AnalogJoystick::Button::Count) + static_cast(halfaxis), \ - InputBindingInfo::Type::HalfAxis, genb \ - } + {name, \ + display_name, \ + icon_name, \ + static_cast(AnalogJoystick::Button::Count) + static_cast(halfaxis), \ + InputBindingInfo::Type::HalfAxis, \ + genb} // clang-format off BUTTON("Up", TRANSLATE_NOOP("AnalogJoystick", "D-Pad Up"), ICON_PF_DPAD_UP, AnalogJoystick::Button::Up, GenericInputBinding::DPadUp), diff --git a/src/core/cheats.cpp b/src/core/cheats.cpp index 1471a6fe36..5375e74085 100644 --- a/src/core/cheats.cpp +++ b/src/core/cheats.cpp @@ -17,6 +17,7 @@ #include "common/file_system.h" #include "common/log.h" #include "common/path.h" +#include "common/settings_interface.h" #include "common/small_string.h" #include "common/string_util.h" #include "common/zip_helpers.h" diff --git a/src/core/cpu_recompiler_x64.cpp b/src/core/cpu_recompiler_x64.cpp index 696a214aaa..1d3495640b 100644 --- a/src/core/cpu_recompiler_x64.cpp +++ b/src/core/cpu_recompiler_x64.cpp @@ -12,6 +12,7 @@ #include "common/align.h" #include "common/assert.h" #include "common/log.h" +#include "common/small_string.h" #include "common/string_util.h" #include diff --git a/src/core/negcon.cpp b/src/core/negcon.cpp index f4f89dcee1..544c8d9235 100644 --- a/src/core/negcon.cpp +++ b/src/core/negcon.cpp @@ -10,6 +10,7 @@ #include "common/assert.h" #include "common/bitutils.h" #include "common/log.h" +#include "common/settings_interface.h" #include "IconsPromptFont.h" @@ -261,14 +262,14 @@ std::unique_ptr NeGcon::Create(u32 index) static const Controller::ControllerBindingInfo s_binding_info[] = { #define BUTTON(name, display_name, icon_name, button, genb) \ - { \ - name, display_name, icon_name, static_cast(button), InputBindingInfo::Type::Button, genb \ - } + {name, display_name, icon_name, static_cast(button), InputBindingInfo::Type::Button, genb} #define AXIS(name, display_name, icon_name, halfaxis, genb) \ - { \ - name, display_name, icon_name, static_cast(NeGcon::Button::Count) + static_cast(halfaxis), \ - InputBindingInfo::Type::HalfAxis, genb \ - } + {name, \ + display_name, \ + icon_name, \ + static_cast(NeGcon::Button::Count) + static_cast(halfaxis), \ + InputBindingInfo::Type::HalfAxis, \ + genb} // clang-format off BUTTON("Up", TRANSLATE_NOOP("NeGcon", "D-Pad Up"), ICON_PF_DPAD_UP, NeGcon::Button::Up, GenericInputBinding::DPadUp), diff --git a/src/core/playstation_mouse.cpp b/src/core/playstation_mouse.cpp index d81a4d8ccc..5bc385f607 100644 --- a/src/core/playstation_mouse.cpp +++ b/src/core/playstation_mouse.cpp @@ -10,6 +10,7 @@ #include "common/assert.h" #include "common/log.h" +#include "common/settings_interface.h" #include "IconsPromptFont.h" diff --git a/src/core/settings.h b/src/core/settings.h index 96ff897154..273909a3d9 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -8,8 +8,6 @@ #include "util/audio_stream.h" #include "common/log.h" -#include "common/settings_interface.h" -#include "common/small_string.h" #include #include @@ -18,6 +16,8 @@ #include #include +class SettingsInterface; + enum class RenderAPI : u8; enum class MediaCaptureBackend : u8; diff --git a/src/core/timing_event.cpp b/src/core/timing_event.cpp index 94aad8581f..3d871a6508 100644 --- a/src/core/timing_event.cpp +++ b/src/core/timing_event.cpp @@ -10,6 +10,7 @@ #include "common/assert.h" #include "common/log.h" +#include "common/small_string.h" #include "common/thirdparty/SmallVector.h" LOG_CHANNEL(TimingEvents);