26
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RustでDirectX12を使う

Last updated at Posted at 2016-06-17

安全性、速度、並行性の3つのゴールにフォーカスしたシステムプログラミング言語Rust1でDirectX陣営のLow-overhead APIとして新たに(けっこう前に)策定されたDirectX12を動かします。(とりあえずメモ的な)
Rustはまだまだ初心者なので間違ってたりもっとよくできたりする点があるかもしれませんが暖かい目で見てやってください。

環境

rustcはバージョン1.9.0を使用します。あと、たぶんWindows SDKが入ってるなら入ってると思いますがDebugging Tools for Windows(windbg)も入れておきましょう。D言語を一緒に入れてる人はパスの関係でコマンドラインでwindbgを起動するとD言語付属のやつが起動してしまうかもしれないのでファイル名を変えておくといいと思います。
追記: rustcはMSVC ABIのほうを使用すると安心かと思います。GNU ABI(MinGW環境)でももしかしたら動いてくれるかもしれませんが、そもそもMinGWにはd3d12.libが同梱されていないのでちょっと準備が大変かと思います。

Crates

今回使用するクレートは以下の通りです。

Cargo.toml
[dependencies]
winapi = "0.2.7"
kernel32-sys = "0.2.2"
user32-sys = "0.2.0"
d3d12-sys = "0.2.0"
dxgi-sys = "0.2.0"
dxguid-sys = "0.2.0"
d3dcompiler-sys = "0.2.0"
widestring = "0.2.0"

D3DCompilerがワイド文字列を要求してくるのでwidestringがないとめちゃくちゃつらいです(たしか標準ライブラリだけでもできなくはないはずですけど)

引っかかり点

コード本体はほとんどC++と同じように書けるのですが、いくつか引っかかり点があるので書いておきます。

D3D12_GRAPHICS_PIPELINE_DESC::RTVFormats

最初はRTVFormats: [DXGI_FORMAT_R8G8B8A8_UNORM; 8]で一括して初期化していたのですが、どうやら使われないRTVFormatsの要素(インデックス番号>=NumRenderTargetsとなるような要素)は絶対にDXGI_FORMAT_UNKNOWNを指定しないとダメらしいです。地道に初期化しましょう。

頂点入力レイアウトの要素のSemanticNameについて(というか、すべての文字列指定についての注意)

明示的にstatic領域に置くようにしないとダメですID3D12Device::CreateGraphicsPipelineStateから制御が返るまでに文字列オブジェクトが生存している必要があるので、べた書きじゃなくて一回ローカル変数を経由するようにする必要があります。普通に

D3D12_INPUT_ELEMENT_DESC { SemanticName: CString::new("POSITION").unwrap().as_ptr(), .. (省略) }

でいいんじゃないかと思いますが、CString::new("POSITION").unwrap()が一時オブジェクトなのでこの式が終了すると文字列含めオブジェクトが解放されるみたいでメモリ領域が破壊されます(運が良ければ生きています。たぶん)。正しくはこう

let sn_pos = CString::new("POSITION").unwrap();
...
D3D12_INPUT_ELEMENT_DESC { SemanticName: sn_pos.as_ptr(), .. (省略) }

あるいはコメントで教えていただきましたが、as_ptrの代わりにinto_rawを使うと直接書けます(メモリリークの心配がありますが、アプリケーション終了時にOSか言語処理系が使用済みメモリを回収してくれるはず(たぶん)なのでここではそこまで神経質になる必要もないかなと思います)。

D3D12_INPUT_ELEMENT_DESC { SemanticName: CString::new("POSITION").unwrap().into_raw(), .. (省略) }

C/C++/DだとCString::newの引数は(この書き方だと)そのままstatic領域に格納されたはずなので引っかかりやすい点だと思います。

  1. https://doc.rust-lang.org/book/README.html

26
24
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?