はかせのラボ

私の頭の中を書いていく雑記ブログです

DirectX12 DirectX12を触ってみる

あいさつ

どうも、はかせです。
札幌でCEDECが開催されますね。
もちろん私は行きますよ。

そこでセッション内容を見てたら
結構DirectX12系のセッションが多そう。

これはCEDECに参加する前に
基本ぐらいは抑えておく必要がありそう。

ということでDirectX12やってみます。
(なんかちょっと前に日本語の資料出たらしいですし)

サンプルコード

今回はこちらのサイトのコードを
落として勉強していきます。
(先人の遺産にがっつり頼っていくスタイル)

解説記事
qiita.com
コード
github.com

DirectX12の描画フロー

基本はDirectX11と同じで
頂点作って
バッファ作って
シェーダー作って
パイプラインに流して描画
って感じっぽいです。

ただDirectX11と大きく違うのが二点あって
それは描画の仕方とパイプラインの構築です。

描画の仕方

DirectX11ではDeviceContextを通して
ドローコールを行うことで自動的に描画までしてくれました。

DirectX12ではCommandList, CommandAllocator, CommandQueueという
三つのオブジェクトを使って描画命令の発行・登録・実行を行います。

CommandListはドローコールを発行するものです。
こいつのDraw関数を呼ぶことで描画命令の発行ができます。

CommandAllocatorは発行された
描画命令を登録しておくバッファみたいな感じです。
基本的にList→Allocatorは一対一で対応させるらしいです。
(多対一でもできるらしいですがあまり価値は無いそう)

CommandQueueは登録された描画命令を実行させるものです。
厳密に言えば発行され登録されている
描画命令をGPUに転送するものらしいですが、
まぁ実行させるものって認識で大きくは外さないでしょう。きっと。

この流れを図にするとこんな感じ
f:id:hakase0274:20190926220658p:plain

ただこの時気をつけなきゃいけない点があって
DirectX11と違って描画後の待ちの処理が必要です。

というのもListはコマンドの発行するだけ、
Queueは登録されているコマンドをGPUに転送するだけなんで
待たなくてもいいんですが、
コマンドが登録されているAllocatorに関しては
全部流しきるまで更新されちゃ困ります。

なのでコマンドが全て消化されるまで処理を待つ必要があるわけですね。

パイプラインの構築

DirectX11では描画フローのたびに
都度プリミティブの解釈やラスタライズの方法など
パイプラインの設定項目を設定し直していました。

DirectX12では予めそういったものをまとめて設定し
あとはそれをパイプラインにあてがうことで
この毎回やっていた設定を無くすことに成功しています。

都度再設定しなくていいのは楽ですね。

ただ設定が全部ひとまとめになっているので
どこか違う場合(例えばシェーダー)
また別に設定を作ってそれをパイプラインあてがう必要があるみたいです。

あとがき

今回はDirectX12始めたよって記事でした。
最近はC#の深いところにどっぷりつかっていたので
そんな離れてないはずなのに大分C++が懐かしく感じました。

世間ではDirectX12は激ムズだっていう話でしたが、
そこまで超絶難易度の黒魔術って感じはしませんでしたね。
(むしろILのが難しいまである)

なんやかんやいって4年前ぐらいに出てきたもので
英語記事はそこそこありますし、
ついこないだ日本語資料が出てきた影響で
日本語記事もめっちゃ増えてますし、
全く手も足も出ないって感じはないと思います。

結局基本はDirectX11とそんな変わんないですしね。

とりあえずCEDECまでにマスターは無理でも
ある程度読み書きできるレベルまでには持ってきたいところですね。
それでは今回はこの辺でノシ