DirectX11 を使ってマルチディスプレイをフルスクリーンモードで使いたい場合に、Windows10 では問題があるということを前回記載しました。結論としては、仮想的なフルスクリーンを実装する(=全画面を覆うウィンドウを作成&最前面)でしたが、これを今回はテストしてみたいと思います。
仮想フルスクリーンの実装
仮想フルスクリーンの実装について説明します。といっても全画面を覆うウィンドウを作成するだけですので、難しいことはありません。
コードの抜粋ですが、以下のような感じで用意します。
ComPtradapter; IDXGIOutput* output = nullptr; for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND && i < MonitorCount; ++i) { DXGI_OUTPUT_DESC desc{}; output->GetDesc(&desc); UINT num = 0; hr = output->GetDisplayModeList(format, 0, &num, nullptr); std::vector modes; modes.resize(num); output->GetDisplayModeList(format, 0, &num, modes.data()); MONITORINFO monInfo; ZeroMemory(&monInfo,sizeof(monInfo)); monInfo.cbSize = sizeof(monInfo); GetMonitorInfo(desc.Monitor, &monInfo); int width = monInfo.rcMonitor.right - monInfo.rcMonitor.left; int height = monInfo.rcMonitor.bottom - monInfo.rcMonitor.top; // ウィンドウを作成 hwnds[i] = InitInstance( hInstance, monInfo.rcMonitor.left, monInfo.rcMonitor.top, width, height); } HWND InitInstance11(HINSTANCE hInstance, int x, int y, int Width, int Height ) { DWORD dwStyle = WS_POPUP; DWORD dwExStyle = WS_EX_TOPMOST; HWND hWnd = CreateWindowExW( dwExStyle, szWindowClass, szTitle, dwStyle, x, y, Width, Height, nullptr, nullptr, hInstance, nullptr); ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); return hWnd; }
あとは作成したウィンドウごとにスワップチェインを CreateSwapChainForHwnd 関数を用いて作成します。
実験
スワップチェインのフラグに、従来のモードとフリップタイプのモードを設定してみてどのような差が出るかを確認してみたいと思います。
環境
今回環境としては以下のような2機種で試してみました。いずれも Windows10 CU (1703) x64 の環境です。
- NVIDIA Geforce 650 Ti
- Intel HD Graphics 5300
どちらの環境でもモニタの接続については、プライマリを 1920×1200, セカンダリを 1280×1024 という環境となっています。
テスト
バッファ使用数は DXGI_SWAP_CHAIN_DESC1.BufferCount = 3 で実験を開始しました。いわゆるトリプルバッファリングです。DXGI_SWAP_EFFECT_DISCARD や DXGI_SWAP_EFFECT_FLIP_DISCARD を設定して Vsync 同期しないで全力で描画を実行してみました。表に記載の描画にかかっている時間は、直近 300 フレームの平均値となっています。
ベンダー | DXGI_SWAP_EFFECT_DISCARD | DXGI_SWAP_EFFECT_FLIP_DISCARD |
---|---|---|
NVIDIA | 0 ms | 8 ms |
Intel | 3 ms | 8 ms |
この結果を見ると、 DXGI_SWAP_EFFECT_DISCARD のほうが全力で描画処理を回せているように見えます。一方で、 DXGI_SWAP_EFFECT_FLIP_DISCARD は両者で同じような値になったことから、何か待ちが発生していると考えられます。
参考までに各フレームでの描画の時間をグラフ描画してみたところ、以下のようになり、描画時間が一定では無いことが確認できました。定期的に一定時間を待っているような感じです。(グラフは描画にかかった時間を縦軸、画面下をゼロとしています)
続いてバッファの使用数を DXGI_SWAP_CHAIN_DESC1.BufferCount = 12 で実験を行いました。同じように SWAP_EFFECT を変更しつつ確認してみます。
ベンダー | DXGI_SWAP_EFFECT_DISCARD | DXGI_SWAP_EFFECT_FLIP_DISCARD |
---|---|---|
NVIDIA | 0 ms | 0.9 ms |
Intel | 3 ms | 2.5 ms |