【Direct2D】規定値でパラメータを初期化したら垂直同期に合わせられて困った話
はじめに
OpenCVで画像処理をした結果をDirect2Dで描画しようとプログラムを作ってみたら予想以上にフレームレートが落ちていたので,それについて記事にしてみました.
実装と計測
HWNDを対象とするレンダーターゲットであるID2D1HwndRenderTargetインターフェースに関しては,以下の通りに生成しました.
D2D1_SIZE_U PixelSize = { rect.Width(), rect.Height() }; D2D1_RENDER_TARGET_PROPERTIES RenderTargetProperties = D2D1::RenderTargetProperties(); D2D1_HWND_RENDER_TARGET_PROPERTIES HwndRenderTargetProperties = D2D1::HwndRenderTargetProperties(m_hWindow, PixelSize); HRESULT hr= m_pD2d1Factory->CreateHwndRenderTarget( RenderTargetProperties, HwndRenderTargetProperties, &m_pRenderTarget);
また,今回は処理が無事に実行されることを確認するだけだったので,ウィンドウの背景をクリアするのみとなっています.
/* 開始 */ m_pRenderTarget->BeginDraw(); /* 背景のクリア */ m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Blue)); /* 終了 */ m_pRenderTarget->EndDraw();
処理自体は非常にシンプルであり,レンダリングの開始・背景のクリア・終了しかしていません.
しかし,このコードで処理を実行した結果,約60fpsしか出ませんでした...
フレームレートが重くなった原因
ID2D1HwndRenderTarget インターフェイスのインスタンスを生成する上で,CreateHwndRenderTarget() 関数を使っていました.
このメソッドの第1・第2パラメータには,それぞれ適切に初期化されたD2D1_RENDER_TARGET_PROPERTIES 構造体,D2D1_HWND_RENDER_TARGET_PROPERTIES 構造体が必要となります.
しかし,先のプログラムでは初期化を簡単にするため,以下の関数を使用していました.
RenderTargetProperties( D2D1_RENDER_TARGET_TYPE type = D2D1_RENDER_TARGET_TYPE_DEFAULT, _In_ CONST D2D1_PIXEL_FORMAT &pixelFormat = D2D1::PixelFormat(), FLOAT dpiX = 0.0, FLOAT dpiY = 0.0, D2D1_RENDER_TARGET_USAGE usage = D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL minLevel = D2D1_FEATURE_LEVEL_DEFAULT )
HwndRenderTargetProperties( _In_ HWND hwnd, _In_ D2D1_SIZE_U pixelSize = D2D1::Size(static_cast<UINT32>(0), static_cast<UINT32>(0)), _In_ D2D1_PRESENT_OPTIONS presentOptions = D2D1_PRESENT_OPTIONS_NONE )
このうち,HwndRenderTargetProperties() 関数の第3パラメータに指定するD2D1_PRESENT_OPTIONSがフレームレートを下げていた原因でした.このパラメータは規定値だと,レンダリングをディスプレイのリフレッシュレートに合わせる(垂直同期)ようです.
...うん,綺麗に60fpsなんて数字になったのでなんかおかしいとは思ったんですけど,パラメータの指定をさぼった自分のミスでしたね(-_-;)
このパラメータをD2D1_PRESENT_OPTIONS_IMMEDIATELY メンバに設定すれば垂直同期をしなくなるようなので,処理の実行速度なんかを計測したい場合はこのパラメータを設定するといいでしょう.