@@ -74,7 +74,7 @@ static bool SleepGPUThread(bool allow_sleep);
7474
7575static bool CreateDeviceOnThread (RenderAPI api, bool fullscreen, bool preserve_fsui_state, Error* error);
7676static void DestroyDeviceOnThread (bool preserve_fsui_state);
77- static void ResizeDisplayWindowOnThread (u32 width, u32 height, float scale);
77+ static void ResizeDisplayWindowOnThread (u32 width, u32 height, float scale, float refresh_rate );
7878static void UpdateDisplayWindowOnThread (bool fullscreen, bool allow_exclusive_fullscreen);
7979static void DisplayWindowResizedOnThread ();
8080static bool CheckExclusiveFullscreenOnThread ();
@@ -411,7 +411,6 @@ bool GPUThread::SleepGPUThread(bool allow_sleep)
411411void GPUThread::Internal::GPUThreadEntryPoint ()
412412{
413413 s_state.gpu_thread = Threading::ThreadHandle::GetForCallingThread ();
414- std::atomic_thread_fence (std::memory_order_release);
415414
416415 // Take a local copy of the FIFO, that way it's not ping-ponging between the threads.
417416 u8 * const command_fifo_data = s_state.command_fifo_data .get ();
@@ -725,6 +724,8 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool preser
725724 s_state.render_window_info = swap_chain->GetWindowInfo ();
726725 else
727726 s_state.render_window_info = WindowInfo ();
727+ s_state.render_window_info .surface_width = std::max<u16 >(s_state.render_window_info .surface_width , 1 );
728+ s_state.render_window_info .surface_height = std::max<u16 >(s_state.render_window_info .surface_height , 1 );
728729
729730 std::atomic_thread_fence (std::memory_order_release);
730731 UpdateRunIdle ();
@@ -1263,28 +1264,40 @@ bool GPUThread::IsUsingThread()
12631264 return s_state.use_gpu_thread ;
12641265}
12651266
1266- void GPUThread::ResizeDisplayWindow (s32 width, s32 height, float scale)
1267+ void GPUThread::ResizeDisplayWindow (s32 width, s32 height, float scale, float refresh_rate )
12671268{
1268- RunOnThread ([width, height, scale]() { ResizeDisplayWindowOnThread (width, height, scale); });
1269+ s_state.render_window_info .surface_width =
1270+ static_cast <u16 >(std::clamp<s32>(width, 1 , std::numeric_limits<u16 >::max ()));
1271+ s_state.render_window_info .surface_height =
1272+ static_cast <u16 >(std::clamp<s32>(height, 1 , std::numeric_limits<u16 >::max ()));
1273+ s_state.render_window_info .surface_scale = scale;
1274+ s_state.render_window_info .surface_refresh_rate = refresh_rate;
1275+ RunOnThread (
1276+ [width, height, scale, refresh_rate]() { ResizeDisplayWindowOnThread (width, height, scale, refresh_rate); });
1277+ System::DisplayWindowResized ();
12691278}
12701279
1271- void GPUThread::ResizeDisplayWindowOnThread (u32 width, u32 height, float scale)
1280+ void GPUThread::ResizeDisplayWindowOnThread (u32 width, u32 height, float scale, float refresh_rate )
12721281{
12731282 // We should _not_ be getting this without a device, since we should have shut down.
12741283 if (!g_gpu_device || !g_gpu_device->HasMainSwapChain ())
12751284 return ;
12761285
1277- DEV_LOG (" Display window resized to {}x{}" , width, height);
1286+ DEV_LOG (" Display window resized to {}x{} @ {}x/{}hz " , width, height, scale, refresh_rate );
12781287
12791288 Error error;
1280- if (!g_gpu_device->GetMainSwapChain ()->ResizeBuffers (width, height, scale, &error))
1289+ GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain ();
1290+ if (!swap_chain->ResizeBuffers (width, height, &error))
12811291 {
12821292 // ick, CPU thread read, but this is unlikely to happen in the first place
12831293 ERROR_LOG (" Failed to resize main swap chain: {}" , error.GetDescription ());
12841294 UpdateDisplayWindowOnThread (s_state.requested_fullscreen , true );
12851295 return ;
12861296 }
12871297
1298+ swap_chain->SetScale (scale);
1299+ swap_chain->SetRefreshRate (refresh_rate);
1300+
12881301 DisplayWindowResizedOnThread ();
12891302}
12901303
@@ -1394,14 +1407,8 @@ bool GPUThread::CheckExclusiveFullscreenOnThread()
13941407
13951408void GPUThread::DisplayWindowResizedOnThread ()
13961409{
1397- const GPUSwapChain* swap_chain = g_gpu_device->GetMainSwapChain ();
1398- if (swap_chain)
1399- s_state.render_window_info = swap_chain->GetWindowInfo ();
1400- else
1401- s_state.render_window_info = WindowInfo ();
1402- std::atomic_thread_fence (std::memory_order_release);
1403-
14041410 // surfaceless is usually temporary, so just ignore it
1411+ const GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain ();
14051412 if (!swap_chain)
14061413 return ;
14071414
@@ -1411,25 +1418,18 @@ void GPUThread::DisplayWindowResizedOnThread()
14111418 ImGuiManager::WindowResized (swap_chain->GetFormat (), f_width, f_height);
14121419 InputManager::SetDisplayWindowSize (f_width, f_height);
14131420
1414- if (s_state.gpu_backend )
1421+ // If we're paused, re-present the current frame at the new window size.
1422+ if (s_state.gpu_backend && IsSystemPaused ())
14151423 {
1416- Host::RunOnCoreThread (&System::DisplayWindowResized);
1417-
1418- // If we're paused, re-present the current frame at the new window size.
1419- if (IsSystemPaused ())
1420- {
1421- // Hackity hack, on some systems, presenting a single frame isn't enough to actually get it
1422- // displayed. Two seems to be good enough. Maybe something to do with direct scanout.
1423- Internal::PresentFrameAndRestoreContext ();
1424- Internal::PresentFrameAndRestoreContext ();
1425- }
1424+ // Hackity hack, on some systems, presenting a single frame isn't enough to actually get it
1425+ // displayed. Two seems to be good enough. Maybe something to do with direct scanout.
1426+ Internal::PresentFrameAndRestoreContext ();
1427+ Internal::PresentFrameAndRestoreContext ();
14261428 }
14271429}
14281430
14291431const WindowInfo& GPUThread::GetRenderWindowInfo ()
14301432{
1431- // This is infrequently used, so we can get away with a full barrier.
1432- std::atomic_thread_fence (std::memory_order_acquire);
14331433 return s_state.render_window_info ;
14341434}
14351435
0 commit comments