diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0c13417ba..f3f8a32f8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -143,6 +143,7 @@ add_library(core video_thread.cpp video_thread.h video_thread_commands.h + video_thread_private.h ) set(RECOMPILER_SRCS diff --git a/src/core/core.cpp b/src/core/core.cpp index d6ff46716..b106e516b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -11,6 +11,7 @@ #include "system.h" #include "system_private.h" #include "video_thread.h" +#include "video_thread_private.h" #include "util/gpu_device.h" #include "util/http_cache.h" @@ -714,7 +715,7 @@ bool Core::CoreThreadInitialize(Error* error) LogStartupInformation(); - VideoThread::Internal::ProcessStartup(); + VideoThread::ProcessStartup(); Achievements::Initialize(); @@ -740,7 +741,7 @@ void Core::CoreThreadShutdown() HTTPCache::Shutdown(); - VideoThread::Internal::ProcessShutdown(); + VideoThread::ProcessShutdown(); s_locals.core_thread_handle = {}; diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index fcc2717c8..b3e1f4c42 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -179,6 +179,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 3afaeecdb..2dd895aca 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -160,6 +160,7 @@ + diff --git a/src/core/fullscreenui_widgets.cpp b/src/core/fullscreenui_widgets.cpp index 380ced3f0..b1e07c907 100644 --- a/src/core/fullscreenui_widgets.cpp +++ b/src/core/fullscreenui_widgets.cpp @@ -6354,7 +6354,7 @@ void FullscreenUI::LoadingScreenProgressCallback::Close() else { // since this was pushing frames, we need to restore the context. do that by pushing a frame ourselves - VideoThread::Internal::PresentFrameAndRestoreContext(); + VideoThread::PresentFrameAndRestoreContext(); } m_last_progress_percent = -1; diff --git a/src/core/host.h b/src/core/host.h index 7487cea9a..fcb9af02c 100644 --- a/src/core/host.h +++ b/src/core/host.h @@ -17,6 +17,8 @@ namespace Threading { class ThreadHandle; } +enum class WindowInfoType : u8; + namespace Host { /// Returns true if the specified resource file exists. @@ -87,4 +89,10 @@ void WaitForAllAsyncTasks(); /// Commits any changes made to the base settings layer to the host. void CommitBaseSettingChanges(); +/// Returns the window type for the host. +WindowInfoType GetRenderWindowInfoType(); + +/// Changes the screensaver inhibit state. +bool SetScreensaverInhibit(bool inhibit, Error* error); + } // namespace Host diff --git a/src/core/performance_counters.cpp b/src/core/performance_counters.cpp index 776c19a50..a9f8741e1 100644 --- a/src/core/performance_counters.cpp +++ b/src/core/performance_counters.cpp @@ -156,7 +156,7 @@ void PerformanceCounters::Reset() s_state.last_frame_number = frame_number; s_state.last_internal_frame_number = internal_frame_number; s_state.last_core_thread_time = Host::GetCoreThreadHandle().GetCPUTime(); - s_state.last_video_thread_time = VideoThread::Internal::GetThreadHandle().GetCPUTime(); + s_state.last_video_thread_time = VideoThread::GetThreadHandle().GetCPUTime(); s_state.average_frame_time_accumulator = 0.0f; s_state.minimum_frame_time_accumulator = 0.0f; @@ -207,7 +207,7 @@ void PerformanceCounters::Update(GPUBackend* gpu, u32 frame_number, u32 internal s_state.speed = (s_state.vps / System::GetVideoFrameRate()) * 100.0f; const u64 core_thread_time = Host::GetCoreThreadHandle().GetCPUTime(); - const u64 video_thread_time = VideoThread::Internal::GetThreadHandle().GetCPUTime(); + const u64 video_thread_time = VideoThread::GetThreadHandle().GetCPUTime(); const u64 core_thread_delta = core_thread_time - s_state.last_core_thread_time; const u64 video_thread_delta = video_thread_time - s_state.last_video_thread_time; s_state.last_core_thread_time = core_thread_time; diff --git a/src/core/settings.cpp b/src/core/settings.cpp index d1cea7830..74a9d1113 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -6,9 +6,9 @@ #include "controller.h" #include "core.h" #include "gte_types.h" +#include "host.h" #include "imgui_overlays.h" #include "system.h" -#include "video_thread.h" #include "util/gpu_device.h" #include "util/imgui_manager.h" diff --git a/src/core/system.cpp b/src/core/system.cpp index 03d72efb8..2ee78b35b 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -221,7 +221,7 @@ static void UpdateSessionTime(const std::string& prev_serial); namespace { -struct ALIGN_TO_CACHE_LINE StateVars +struct StateVars { TickCount ticks_per_second = 0; TickCount max_slice_ticks = 0; @@ -311,7 +311,7 @@ struct ALIGN_TO_CACHE_LINE StateVars } // namespace -static StateVars s_state; +ALIGN_TO_CACHE_LINE static StateVars s_state; } // namespace System @@ -3584,7 +3584,7 @@ void System::UpdateSpeedLimiterState() core_thread.SetTimeConstraints(s_state.optimal_frame_pacing, new_scheduler_period, typical_time, new_scheduler_period); } - const Threading::ThreadHandle& video_thread = VideoThread::Internal::GetThreadHandle(); + const Threading::ThreadHandle& video_thread = VideoThread::GetThreadHandle(); if (video_thread) { video_thread.SetTimeConstraints(s_state.optimal_frame_pacing, new_scheduler_period, typical_time, diff --git a/src/core/video_presenter.cpp b/src/core/video_presenter.cpp index 15a286622..49cbd29a4 100644 --- a/src/core/video_presenter.cpp +++ b/src/core/video_presenter.cpp @@ -1808,7 +1808,7 @@ void VideoPresenter::ReloadPostProcessingSettings(bool display, bool internal, b // trigger represent of frame if (VideoThread::IsSystemPaused()) - VideoThread::Internal::PresentFrameAndRestoreContext(); + VideoThread::PresentFrameAndRestoreContext(); }); } diff --git a/src/core/video_thread.cpp b/src/core/video_thread.cpp index e76c8f953..8db926184 100644 --- a/src/core/video_thread.cpp +++ b/src/core/video_thread.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "video_thread.h" @@ -16,6 +16,7 @@ #include "system_private.h" #include "video_presenter.h" #include "video_thread_commands.h" +#include "video_thread_private.h" #include "util/gpu_device.h" #include "util/imgui_manager.h" @@ -133,7 +134,7 @@ static State s_state; } // namespace VideoThread -const Threading::ThreadHandle& VideoThread::Internal::GetThreadHandle() +const Threading::ThreadHandle& VideoThread::GetThreadHandle() { return s_state.thread; } @@ -146,7 +147,7 @@ void VideoThread::ResetCommandFIFO() s_state.command_fifo_read_ptr.store(0, std::memory_order_release); } -void VideoThread::Internal::ProcessStartup() +void VideoThread::ProcessStartup() { s_state.thread_spin_time = Timer::ConvertNanosecondsToValue(THREAD_SPIN_TIME_US * 1000.0); s_state.command_fifo_data = Common::make_unique_aligned_for_overwrite(HOST_CACHE_LINE_SIZE, COMMAND_QUEUE_SIZE); @@ -157,7 +158,7 @@ void VideoThread::Internal::ProcessStartup() s_state.thread.Start(&VideoThread::VideoThreadEntryPoint); } -void VideoThread::Internal::ProcessShutdown() +void VideoThread::ProcessShutdown() { INFO_LOG("Shutting down video thread..."); SyncThread(false); @@ -434,7 +435,7 @@ void VideoThread::VideoThreadEntryPoint() } else { - VideoThread::Internal::DoRunIdle(); + DoRunIdle(); continue; } } @@ -524,7 +525,7 @@ void VideoThread::VideoThreadEntryPoint() } } -void VideoThread::Internal::DoRunIdle() +void VideoThread::DoRunIdle() { if (!g_gpu_device->HasMainSwapChain()) [[unlikely]] { @@ -1044,7 +1045,7 @@ void VideoThread::DestroyGPUPresenterOnThread() VideoPresenter::Shutdown(); } -bool VideoThread::Internal::PresentFrameAndRestoreContext() +bool VideoThread::PresentFrameAndRestoreContext() { DebugAssert(IsOnThread()); @@ -1142,7 +1143,7 @@ void VideoThread::UpdateSettingsOnThread(GPUSettings&& new_settings) } if (ImGuiManager::UpdateDebugWindowConfig()) - Internal::PresentFrameAndRestoreContext(); + PresentFrameAndRestoreContext(); else s_state.gpu_backend->RestoreDeviceContext(); } @@ -1235,7 +1236,7 @@ void VideoThread::UpdateSettings(bool gpu_settings_changed, bool device_settings if (s_state.gpu_backend) { if (ImGuiManager::UpdateDebugWindowConfig()) - Internal::PresentFrameAndRestoreContext(); + PresentFrameAndRestoreContext(); } }); #endif @@ -1509,8 +1510,8 @@ void VideoThread::RenderWindowResizedOnThread() { // Hackity hack, on some systems, presenting a single frame isn't enough to actually get it // displayed. Two seems to be good enough. Maybe something to do with direct scanout. - Internal::PresentFrameAndRestoreContext(); - Internal::PresentFrameAndRestoreContext(); + PresentFrameAndRestoreContext(); + PresentFrameAndRestoreContext(); } } @@ -1553,7 +1554,7 @@ void VideoThread::PresentCurrentFrame() // But we shouldn't be not running idle without a GPU backend. if (s_state.gpu_backend) - Internal::PresentFrameAndRestoreContext(); + PresentFrameAndRestoreContext(); }); } diff --git a/src/core/video_thread.h b/src/core/video_thread.h index b06ebdb77..6d3229c71 100644 --- a/src/core/video_thread.h +++ b/src/core/video_thread.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #pragma once @@ -18,7 +18,6 @@ class ThreadHandle; enum class RenderAPI : u8; enum class GPUVSyncMode : u8; -enum class WindowInfoType : u8; enum class GPURenderer : u8; enum class VideoThreadCommandType : u8; @@ -102,35 +101,10 @@ void PushCommandAndWakeThread(VideoThreadCommand* cmd); void PushCommandAndSync(VideoThreadCommand* cmd, bool spin); void SyncThread(bool spin); -namespace Internal { +/// Returns a handle to the video thread. const Threading::ThreadHandle& GetThreadHandle(); -void ProcessStartup(); -void ProcessShutdown(); -void DoRunIdle(); -bool PresentFrameAndRestoreContext(); -} // namespace Internal -} // namespace VideoThread - -namespace Host { - -/// Called when the core is creating a render device. -/// This could also be fullscreen transition. -std::optional AcquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen, - Error* error); - -/// Returns the window type for the host. -WindowInfoType GetRenderWindowInfoType(); -/// Called when the core is finished with a render window. -void ReleaseRenderWindow(); - -/// Called before a fullscreen transition occurs. -bool CanChangeFullscreenMode(bool new_fullscreen_state); - -/// Called when the pause state changes, or fullscreen UI opens. -void OnVideoThreadRunIdleChanged(bool is_active); - -/// Changes the screensaver inhibit state. -bool SetScreensaverInhibit(bool inhibit, Error* error); +/// Presents the current frame and restores the GPU context, only carefully call on the video thread. +bool PresentFrameAndRestoreContext(); -} // namespace Host +} // namespace VideoThread diff --git a/src/core/video_thread_private.h b/src/core/video_thread_private.h new file mode 100644 index 000000000..fd782928d --- /dev/null +++ b/src/core/video_thread_private.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin +// SPDX-License-Identifier: CC-BY-NC-ND-4.0 + +#pragma once + +#include "video_thread.h" + +namespace VideoThread { + +void ProcessStartup(); +void ProcessShutdown(); +void DoRunIdle(); + +} // namespace VideoThread + +namespace Host { + +/// Called when the core is creating a render device. +/// This could also be fullscreen transition. +std::optional AcquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen, + Error* error); + +/// Called when the core is finished with a render window. +void ReleaseRenderWindow(); + +/// Called before a fullscreen transition occurs. +bool CanChangeFullscreenMode(bool new_fullscreen_state); + +/// Called when the pause state changes, or fullscreen UI opens. +void OnVideoThreadRunIdleChanged(bool is_active); + +} // namespace Host diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 55567abb2..1dee84a00 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -35,6 +35,7 @@ #include "core/system_private.h" #include "core/video_presenter.h" #include "core/video_thread.h" +#include "core/video_thread_private.h" #include "common/assert.h" #include "common/crash_handler.h" @@ -2252,7 +2253,7 @@ void CoreThread::run() // have to double-check the condition after processing events, because the events could shut us down if (!VideoThread::IsUsingThread() && VideoThread::IsRunningIdle()) - VideoThread::Internal::DoRunIdle(); + VideoThread::DoRunIdle(); } else { diff --git a/src/duckstation-qt/qtwindowinfo.cpp b/src/duckstation-qt/qtwindowinfo.cpp index be3d47c3a..dce4403c1 100644 --- a/src/duckstation-qt/qtwindowinfo.cpp +++ b/src/duckstation-qt/qtwindowinfo.cpp @@ -5,7 +5,7 @@ #include "qtutils.h" #include "core/core.h" -#include "core/video_thread.h" +#include "core/host.h" #include "util/gpu_device.h" diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index 5729a3510..eecf08a91 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -18,6 +18,7 @@ #include "core/system_private.h" #include "core/video_presenter.h" #include "core/video_thread.h" +#include "core/video_thread_private.h" #include "scmversion/scmversion.h"