Skip to content

Commit 71f46cf

Browse files
committed
GPUThread: Update core thread window size on core thread
Avoid the barrier when reading it.
1 parent abed81d commit 71f46cf

20 files changed

+66
-59
lines changed

src/core/gpu_thread.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ static bool SleepGPUThread(bool allow_sleep);
7474

7575
static bool CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool preserve_fsui_state, Error* error);
7676
static 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);
7878
static void UpdateDisplayWindowOnThread(bool fullscreen, bool allow_exclusive_fullscreen);
7979
static void DisplayWindowResizedOnThread();
8080
static bool CheckExclusiveFullscreenOnThread();
@@ -411,7 +411,6 @@ bool GPUThread::SleepGPUThread(bool allow_sleep)
411411
void 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

13951408
void 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

14291431
const 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

src/core/gpu_thread.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void SetFullscreen(bool fullscreen);
6666
void SetFullscreenWithCompletionHandler(bool fullscreen, AsyncCallType completion_handler);
6767

6868
/// Called when the window is resized.
69-
void ResizeDisplayWindow(s32 width, s32 height, float scale);
69+
void ResizeDisplayWindow(s32 width, s32 height, float scale, float refresh_rate);
7070

7171
/// Access to main window size from CPU thread.
7272
const WindowInfo& GetRenderWindowInfo();

src/duckstation-mini/mini_host.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ struct SDLHostState
113113

114114
SDL_Window* sdl_window = nullptr;
115115
float sdl_window_scale = 0.0f;
116+
float sdl_window_refresh_rate = 0.0f;
116117
WindowInfo::PreRotation force_prerotation = WindowInfo::PreRotation::Identity;
117118

118119
Threading::Thread core_thread;
@@ -496,6 +497,11 @@ std::optional<WindowInfo> MiniHost::TranslateSDLWindowInfo(SDL_Window* win, Erro
496497
{
497498
INFO_LOG("Display mode refresh rate: {} hz", dispmode->refresh_rate);
498499
wi.surface_refresh_rate = dispmode->refresh_rate;
500+
s_state.sdl_window_refresh_rate = dispmode->refresh_rate;
501+
}
502+
else
503+
{
504+
s_state.sdl_window_refresh_rate = 0.0f;
499505
}
500506

501507
// SDL's opengl window flag tends to make a mess of pixel formats...
@@ -748,10 +754,11 @@ void MiniHost::ProcessSDLEvent(const SDL_Event* ev)
748754
{
749755
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
750756
{
751-
Host::RunOnCoreThread(
752-
[window_width = ev->window.data1, window_height = ev->window.data2, window_scale = s_state.sdl_window_scale]() {
753-
GPUThread::ResizeDisplayWindow(window_width, window_height, window_scale);
754-
});
757+
Host::RunOnCoreThread([window_width = ev->window.data1, window_height = ev->window.data2,
758+
window_scale = s_state.sdl_window_scale,
759+
window_refresh_rate = s_state.sdl_window_refresh_rate]() {
760+
GPUThread::ResizeDisplayWindow(window_width, window_height, window_scale, window_refresh_rate);
761+
});
755762
}
756763
break;
757764

@@ -765,8 +772,9 @@ void MiniHost::ProcessSDLEvent(const SDL_Event* ev)
765772

766773
int window_width = 1, window_height = 1;
767774
SDL_GetWindowSizeInPixels(s_state.sdl_window, &window_width, &window_height);
768-
Host::RunOnCoreThread([window_width, window_height, window_scale = s_state.sdl_window_scale]() {
769-
GPUThread::ResizeDisplayWindow(window_width, window_height, window_scale);
775+
Host::RunOnCoreThread([window_width, window_height, window_scale = s_state.sdl_window_scale,
776+
window_refresh_rate = s_state.sdl_window_refresh_rate]() {
777+
GPUThread::ResizeDisplayWindow(window_width, window_height, window_scale, window_refresh_rate);
770778
});
771779
}
772780
}

src/duckstation-qt/displaywidget.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ void DisplayWidget::checkForSizeChange()
7171
if (!m_window_info.has_value())
7272
return;
7373

74+
// TODO: Handle refresh rate changes
7475
// avoid spamming resize events for paint events (sent on move on windows)
7576
const u16 prev_width = m_window_info->surface_width;
7677
const u16 prev_height = m_window_info->surface_height;
@@ -81,7 +82,8 @@ void DisplayWidget::checkForSizeChange()
8182
{
8283
DEV_LOG("Display widget resized to {}x{} (Qt {}x{}) DPR={}", m_window_info->surface_width,
8384
m_window_info->surface_height, width(), height(), m_window_info->surface_scale);
84-
emit windowResizedEvent(m_window_info->surface_width, m_window_info->surface_height, m_window_info->surface_scale);
85+
emit windowResizedEvent(m_window_info->surface_width, m_window_info->surface_height, m_window_info->surface_scale,
86+
m_window_info->surface_refresh_rate);
8587
}
8688

8789
updateCenterPos();

src/duckstation-qt/displaywidget.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class DisplayWidget final : public QWidget
4242
void destroy();
4343

4444
Q_SIGNALS:
45-
void windowResizedEvent(int width, int height, float scale);
45+
void windowResizedEvent(int width, int height, float scale, float refresh_rate);
4646
void windowRestoredEvent();
4747
void windowKeyEvent(int key_code, bool pressed);
4848
void windowTextEntered(const QString& text);

src/duckstation-qt/qthost.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,9 +963,9 @@ void CoreThread::onDisplayWindowMouseWheelEvent(float dx, float dy)
963963
InputManager::UpdatePointerRelativeDelta(0, InputPointerAxis::WheelY, dy);
964964
}
965965

966-
void CoreThread::onDisplayWindowResized(int width, int height, float scale)
966+
void CoreThread::onDisplayWindowResized(int width, int height, float scale, float refresh_rate)
967967
{
968-
GPUThread::ResizeDisplayWindow(width, height, scale);
968+
GPUThread::ResizeDisplayWindow(width, height, scale, refresh_rate);
969969
}
970970

971971
void CoreThread::redrawDisplayWindow()

src/duckstation-qt/qthost.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class CoreThread : public QThread
192192
void stopInThread();
193193
void onDisplayWindowMouseButtonEvent(int button, bool pressed);
194194
void onDisplayWindowMouseWheelEvent(float dx, float dy);
195-
void onDisplayWindowResized(int width, int height, float scale);
195+
void onDisplayWindowResized(int width, int height, float scale, float refresh_rate);
196196
void onDisplayWindowKeyEvent(int key, bool pressed);
197197
void onDisplayWindowTextEntered(const QString& text);
198198
void doBackgroundControllerPoll();

src/util/d3d11_device.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,8 @@ bool D3D11SwapChain::CreateRTV(Error* error)
413413
return true;
414414
}
415415

416-
bool D3D11SwapChain::ResizeBuffers(u32 new_width, u32 new_height, float new_scale, Error* error)
416+
bool D3D11SwapChain::ResizeBuffers(u32 new_width, u32 new_height, Error* error)
417417
{
418-
m_window_info.surface_scale = new_scale;
419418
if (m_window_info.surface_width == new_width && m_window_info.surface_height == new_height)
420419
return true;
421420

src/util/d3d11_device.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class D3D11SwapChain : public GPUSwapChain
232232
ALWAYS_INLINE ID3D11RenderTargetView* const* GetRTVArray() const { return m_swap_chain_rtv.GetAddressOf(); }
233233
ALWAYS_INLINE bool IsUsingAllowTearing() const { return m_using_allow_tearing; }
234234

235-
bool ResizeBuffers(u32 new_width, u32 new_height, float new_scale, Error* error) override;
235+
bool ResizeBuffers(u32 new_width, u32 new_height, Error* error) override;
236236
bool SetVSyncMode(GPUVSyncMode mode, bool allow_present_throttle, Error* error) override;
237237
bool IsExclusiveFullscreen() const override;
238238

src/util/d3d12_device.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,9 +1077,8 @@ bool D3D12SwapChain::IsExclusiveFullscreen() const
10771077
return m_fullscreen_mode.has_value();
10781078
}
10791079

1080-
bool D3D12SwapChain::ResizeBuffers(u32 new_width, u32 new_height, float new_scale, Error* error)
1080+
bool D3D12SwapChain::ResizeBuffers(u32 new_width, u32 new_height, Error* error)
10811081
{
1082-
m_window_info.surface_scale = new_scale;
10831082
if (m_window_info.surface_width == new_width && m_window_info.surface_height == new_height)
10841083
return true;
10851084

0 commit comments

Comments
 (0)