描画を別スレッドにする
スワップチェインは周期的に全画面を書き換えるようなアプリ、つまりゲームには向いているが、元の画像から部分的に書き換えるようなというか、部分的な書き換えがランダムな間隔で発生するようなUI描画には向いていない。やはり描画を保持するビットマップサーフェースを用意して、それをスワップチェインに転送するほうが簡単だろう。しかしDXGI1.2からはスワップ部分書き換えに対応し、DXGI1.3からは画面がフリップしたかを検出できるようになった。この2つを組み合わせればなんとかならないかと休日中ゴロゴロしながら考えていた。
いろいろ考えた結果、描画のみを別スレッドで行うことにした。描画メッセージはすぐに行わず、キューに溜める。描画スレッドはキューから取り出して描画し、Present1()するのである。Present()が完了するとシグナルするイベントオブジェクトをスワップチェインから得ることができる。Present()したらイベントオブジェクトがシグナルされるまで待つ。シグナルされると、キューに溜まっている描画命令を実行し、できればDirtyRectsをうまく使うようにする。これを繰り返すのである。
スレッドの実装は非同期エージェントライブラリを使用し、キューはunbound_bufferを使えば良いだろう。私はこの非同期エージェントライブラリを含む同時実行ランタイムが結構好きだ。MSのライブラリの中でもかなり出来がいいのではないかと思っている。ネイティブC++との親和性が良いし、さらにC++/CXを使ったWindows Store Appの非同期処理部分が簡潔に書ける。then()とかね。非同期エージェントライブラリはいわゆるスレッドを抽象化したライブラリである。これを使用すれば64ビットであれば自動的にUMSを使うようだし、今これを使って実装してみているところである。
今のところ描画を別スレッドにできてはいるが、いまいち反応が良くない。イベントオブジェクトではなく単にDIDXGIOutput::WaitForVBlank()で待ったほうがいいかもしれない。