Siv3D / OpenSiv3D

C++20 framework for creative coding 🎮🎨🎹 / Cross-platform support (Windows, macOS, Linux, and the Web)
https://siv3d.github.io/
MIT License
1k stars 138 forks source link

一部Windows環境にてVSync無効時にフレームレートが制限される現象を修正 #1179

Closed m4saka closed 8 months ago

m4saka commented 8 months ago

起きていた現象

一部Windows環境にて、VSyncを無効にした場合でもフレームレートが120fpsに制限されている。 ウィンドウモード、フルスクリーンモードの両方で発生する。 ※垂直同期有効時は60fpsとなっている。

発生を確認している環境:

下記のQiita記事に「注意点」として記載している現象と同一のものです。 OpenSiv3Dでフレームレートを60fps以外に固定する方法(FrameRateLimitアドオン)

現象の原因

DirectXのSwapChainのPresent時に、VSync無効時に可変フレームレートにするために必要となるティアリング許可フラグが立っていないため。

修正内容

SwapChainの初期化時に、サポートされている場合はDXGI_SWAP_CHAIN_FLAG_ALLOW_TEARINGフラグを立てるように。 また、VSync無効かつサポートされている場合はPresent時にDXGI_PRESENT_ALLOW_TEARINGフラグを立てるように。

サポートされているかどうかを調べるCheckTearingSupport関数の実装にあたっては、Microsoft公式が出している下記サンプルコードを参考にしました。 https://github.com/microsoft/DirectX-Graphics-Samples/blob/b5f92e2251ee83db4d4c795b3cba5d470c52eaf8/Samples/UWP/D3D12HDR/src/DXSample.cpp#L160

補足

DXGI_PRESENT_ALLOW_TEARINGについて、Microsoft公式には下記のように「ウィンドウ モードでのみ使用できます」という一見紛らわしい記載がありますが、OpenSiv3Dでは「IDXGIFactory::MakeWindowAssociation を使用して Alt + Enter の全画面表示の自動切り替えを無効」にしている(該当箇所)ので、フルスクリーンモードでも使用できています。

実際に、修正前はフルスクリーンモードでも現象が発生しており、修正後はフルスクリーンモードでも現象が発生しなくなったことを確認しました。

https://learn.microsoft.com/ja-jp/windows/win32/direct3ddxgi/dxgi-present

DXGI_PRESENT_ALLOW_TEARING フラグは、現在全画面表示排他モードのアプリケーションでは使用できません ( SetFullscreenState(TRUE)を呼び出して設定)。 ウィンドウ モードでのみ使用できます。 全画面表示の Win32 アプリでこのフラグを使用するには、アプリケーションを全画面表示の境界線のないウィンドウに表示し、 IDXGIFactory::MakeWindowAssociation を使用して Alt + Enter の全画面表示の自動切り替えを無効にする必要があります。 を呼び出 Windows::UI::ViewManagement::ApplicationView::TryEnterFullscreen() して全画面表示モードに入る UWP アプリは、全画面表示の境界線のないウィンドウであり、 フラグを使用できます。

m4saka commented 8 months ago

同一現象とみられるIssueを見つけたので記載: Graphics::SetVSyncEnabled(false); が効かないことがある #655

Reputeless commented 8 months ago

Merged. Thank you!