掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
VSYNC待ちをするには?? (ID:61769)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
過去のソースをサルベージしたら、とあるプロジェクトで V待ちを行っていて、それは概略こんな感じになってました。 ・時間を QueryPerformanceCounter で計測しながらVを3回待つ。 ・VとVの間隔のうち、短いほうをV周期として採用。 (短いほうが正しいV周期と思われるので) ・描画ループの中で、時間を QueryPerformanceCounter で計測して、 V周期の間待ち、所定の時間に達したら描画する、というのを 繰り返す。 描画ループ中のV待ちを単純に時間計測で行っているので、 長い間には誤差が蓄積してしまうでしょうが、このプロジェクトでの 描画は 2秒くらいで一区切りつくような構成になっていたので 問題ありませんでした。 また、描画ループ中、CPU使用率が100%になったままになりますが、 スムーズな描画のためと、割り切りました。 なお、最初に時間計測するときのV待ちには IDirectDraw::WaitForVerticalBlank ではなく IDirectDraw::GetVerticalBlankStatus を使っていました。 どうも, IDirectDraw::WaitForVerticalBlank は モニターパワーセーブに入ると帰ってこなくなってしまう、 という問題があって使うのをやめたようです。 IDirectDraw::GetVerticalBlankStatus によるV待ちは 次のようにしていました。 ・まず現在時刻を計測。 ・ループの中で時刻を計測して、設定したタイムアウトに 達していないか確認。(タイムアウトは200msを設定していました) ・IDirectDraw::GetVerticalBlankStatus で現在垂直帰線期間内か 確認すると同時に、その状態を保存。 ・現在垂直帰線期間内で、前回は垂直帰線期間内ではなかったなら、 新たに垂直帰線期間に入ったということなので、ループを抜ける。 ところで、このプロジェクトのもっと後のバージョンでは、 別の方法でのV待ちを行っていました。 どうも、上記の方法でもまれに抜けが発生していたようで、 もっと確実にV待ちを行うため、ライン番号を監視することに したようです。 具体的には IDirentDraw::GetScanLine を使って、 次のようにしていました。 ・まず現在時刻を計測。 ・ループの中で時刻を計測して、設定したタイムアウトに 達していないか確認。 (ここまでは GetVerticalBlankStatus による方法と同じ) ・IDirentDraw::GetScanLine で現在のライン番号を取得。 同時にこれを保存。 なお, DDERR_VERTICALBLANKINPROGRESS が返ってきたなら ライン番号は 0 とする。 ・前回のライン番号より今回のライン番号のほうが少なければ 帰線したということなのでループを抜ける。 IDirentDraw::GetScanLine によるV待ちでは抜けがほとんど なかったので、描画ループの中でダイレクトに GetScanLine による V待ち処理を呼び出してしました。 ただし, IDirentDraw::GetScanLine は環境によっては 正常な値を返さない(1画面スキャンする間に何度も増減を繰り返す) ことがありました。 よって、最初に GetScanLine で2回V待ちを行ってその間隔を計測し、 想定する最小間隔(600分の1秒という値を想定していました)より 小さかったら GetScanLine は採用せず, GetVerticalBlankStatus による待ちを行うようにしていました。
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.