Vulkan TutorialのRust版をやってみた 〜準備編〜
Vulkanの入門をRustでやっていきます。目次はこちら。今回までの実装をしたGitHubはこちら。
Vulkanの概要
Vulkanではアプリケーション毎にInstance
を作り、各物理デバイスに対応したLoader
がLayer
を読み込み、そのLayer
を通して各ドライバーを扱います。
(画像はhttps://vulkan.lunarg.com/doc/sdk/1.2.131.2/linux/tutorial/html/01-init_instance.htmlから引用)
また描画する際は、描画命令用のQueue
や各OS固有のウィンドウと描画先のSurface
を作り、レンダーパスを作り、パイプラインを構築し、Queue
にコマンドを送ることで描画できるようになります。
Vulkanで描画するまでの準備
今回は準備編として、デバイス(GPU)を取得するまでを書きます。
開発環境の準備
- Vulkanのライブラリその他をインストール
- 適当なディレクトリで
cargo new [プロジェクト名]
をしてRustのプロジェクトを作る - VulkanのRustラッパであるVulkanoを
Cargo.toml
に追加
Validation layersの追加
現状では関係ないですが、Validation layersは不正な値がGPU側に渡らないように監視すること等ができるため、この段階からデバッグ時のみ有効にしておきます。
Layer
の列挙
レイヤーを有効にするにはInstance
の作成時に引数にレイヤー名を渡す必要があるので、その前にレイヤーを列挙して名前を確認してみます。
vulkano::instance::layers_list().unwrap().for_each(|layer| ...);
列挙された名前から、今回はVK_LAYER_LUNARG_standard_validation
とVK_LAYER_KHRONOS_validation
を読み込んでみます。
Layer
が対応しているかの確認
上では先にLayer
を列挙してからLayer
を読み込むと書きましたが、実行環境によっては読み込みたいLayer
に対応していない可能性があるため、対応しているLayer
だけ抽出します。
let validation_layers = [
"VK_LAYER_LUNARG_standard_validation",
"VK_LAYER_KHRONOS_validation",
];
let supported_validation_layers: Vec<_> = layers_list()
.unwrap()
.filter(|layer| validation_layers.contains(&layer.name()))
.collect();
VK_EXT_debug_utils
の有効化
デバッグ情報等を取得することができるようになるので、VK_EXT_debug_utils
を有効にします。Vulkanoでは、これらextensionsはInstance
の作成時に引数で渡すので、とりあえず何を有効にするのかという設定をしておきます。
let extensions = InstanceExtensions {
ext_debug_utils: true,
..InstanceExtensions::supported_by_core().unwrap()
};
ext_debug_utils: true
とすることでVK_EXT_debug_utils
が有効化されます。
Instance
の作成
アプリケーション毎に用意する必要のある、vulkano::instance::Instance
を作ります。
let instance = Instance::new(
Some(&app_info_from_cargo_toml!()),
&extensions,
supported_validation_layers.iter().map(|layer| layer.name()),
)
.expect("Could not build a Vulkan instance");
ここではそのまま書いていますが、Validation layersをデバッグ時のみ有効にするためにcfg!(debug_assertions)
等で分岐させてください。
DebugCallback
の設定
デフォルトでValidation layersは標準出力に情報を書いていくのですが、どのレベルの情報を書くか等細かい設定をするためにはコールバックを作成する必要があります。
DebugCallback::new(&instance, severity, ty, |message| ...).ok();
注意点として、ext_debug_utils: true
としておかないとDebugCallback::new
がErr
を返します。
物理デバイスの取得
物理デバイスの列挙
物理デバイスはvulkano::instance::PhysicalDevice
で表されており、PhysicalDevice::enumerate
で列挙できます。
PhysicalDevice::enumerate(&instance).for_each(|device| ...);
GPUの取得
列挙された物理デバイスのうちグラフィック用のQueue
を持っているデバイスが必要になるので、ここでは最初に見つかったグラフィック用のQueue
を持っているデバイスを取得します。参考元のサイト及びそのRust版だとちょっと面倒な感じですが、以下のように書けば同じように動作するはずです。
let device = PhysicalDevice::enumerate(&instance)
.filter(|device| {
device
.queue_families()
.any(|queue_family| queue_family.supports_graphics())
})
.next()
.expect("Could not find any GPU");
論理デバイスの取得
上で取得したGPUから対応する論理デバイスを取得します。
let (_device, _queues) = PhysicalDevice::enumerate(&instance)
.filter_map(|device| {
device
.queue_families()
.filter(|queue_family| queue_family.supports_graphics())
.map(|queue_family| (device, queue_family))
.next()
})
.filter_map(|(device, queue_family)| {
Device::new(
device,
&Features::none(),
&DeviceExtensions::supported_by_device(device),
vec![(queue_family, 1.0)],
)
.ok()
})
.next()
.expect("Could not find any GPU");
ここまできてようやく準備が出来た形です。
まとめと感想
この段階だとまだQueue
等よくわからないところも多いですが、最低限Vulkanが動いていることの確認は出来ました。また、Vulkanoのおかげで元のVulkanより大分記述が楽な気がします。ありがとうRust。ありがとうVulkano。
Author And Source
この問題について(Vulkan TutorialのRust版をやってみた 〜準備編〜), 我々は、より多くの情報をここで見つけました https://qiita.com/kbone/items/4ee5cddb7ce9f4bda150著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .