Chiharu の日記

絵描き C/C++ プログラマーの日記です。

Parallel force - パラレル・フォース 〜表画面への転送 (2)

先の日記の日付を 2 度にわたって間違える始末。眠いとミスも増えますね。気をつけよう。
さて、バックバッファの扱いをちょっと再考しています。
昨日の日記のとおり、現在、描画処理に『裏画面の合成』と『表画面への転送』という 2 つのステージを設けて、それぞれを非同期処理しています。前者は描画タスクを受け取ってバックバッファに裏画面の合成結果を出力します。後者はバックバッファを受け取って表画面へ転送します。
前者の出力を後者が受け取る形になっているのですが、非同期処理のためには、バックバッファを何とかして双方の処理で同時にアクセスできるようにする必要がありました。バックバッファをロックしてしまっては非同期処理にならないので、バックバッファの多重化は避けられないとして、できればメモリ コピーのオーバーヘッドのないフリップで対応したいところでした。
しかし、下記のとおり、それぞれのステージで更新領域(ダーティ エリア)の管理方法を統一することができず、フリップ処理が採用できませんでした。

  • 裏画面の合成: 並列処理用に画面分割の上、分割領域ごとに更新領域矩形を管理。
  • 表画面への転送: ティアリング回避のため 1 回の StretchBlt で描画するため、転送領域は 1 つの矩形として管理。

フリップ不可の説明は図解抜きでは面倒なんで、ざっくり言うと、フリップすると裏画面の合成処理で 2 フレーム目と 3 フレーム目の差分を 1 フレーム目に描くことになり、3 フレーム目を表画面へ転送する際、1 フレーム目と 3 フレーム目が混じったアレゲな絵になって出力される、という事態になります。裏画面と表画面で更新領域の取り扱いが統一できれば、差分だけを表画面へ転送できることになるので、このような挙動でも問題ありません。しかし、『表画面への転送』の転送領域に 1 つの矩形しか採用できないということは、裏画面の更新領域の外接矩形で転送することになり、差分以外の領域も転送されることになります。ですので、2 フレーム目と 3 フレーム目の差分は必ず 2 フレーム目に描く必要があることになります。
昨日の日記でバックバッファを 2 枚用意したと書きましたが、上記から、『表画面への転送』側にコピーを保持するようにしています。コピーは無駄が多いので避けたいと考えています。ふーむ。何か浮かびそうなんで、ちょっと考えます。