Rust Vulkano Tutorial(1) Window Creation(1)
Rust Vulkano のチュートリアルです。
今回は初期化したウィンドウ(Window)の作成について記述しています。
Vulkanoガイド(https://vulkano.rs/guide/introduction)とVulkano Triangle Example
(https://github.com/vulkano-rs/vulkano)を参考にしています。
1 Vulkanオブジェクトの初期化
Vulkanでは直接GPUを扱います。GPUにアクセスできるように、Vulkanデバイス
(Device)を作成します。
Vulkanデバイスの作成には、決まった手続きがあります。次のようにして
作成します。
(1)インスタンス(Instance)の作成
(2)サーフェイス(Surface)の作成
(3)物理デバイス(Physical_device)の取得
(4)キュー・ファミリー(Queue_family)の取得
(5)Vulkanデバイス(Device)とキュー(Queue)の作成
(1)インスタンスの作成
let instance = { let extensions = vulkano_win::required_extensions(); Instance::new(None, &extensions, None).expect("failed to create Vulkan instance") };
(2)サーフェイスの作成
キュー・ファミリーの取得時に必要となるので、ここでサーフェイスを
作成します。同時にウィンドウも作成されます。
let mut events_loop = EventsLoop::new(); let surface = WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
サーフェイスの作成時にイベント・ループ(EventsLoop)が必要となるので、
先にイベント・ループを作成します。
(3)物理デバイスの取得
使用する物理デバイスを取得します。
let physical = PhysicalDevice::enumerate(&instance).next().unwrap();
使用可能な物理デバイスを列挙(enumerate)し、最初のデバイスを取得
(next)します。
(4)キュー・ファミリーの取得
Vulkanデバイスの作成時に必要となるので、ここで物理デバイスからキュー・
ファミリーを取得します。
条件「q.supports_graphics() && surface.is_supported(q)」を満たすキュー・
ファミリー(グラフィックス用でサーフェイスに描画できる
キュー・ファミリー)を取り出します。
let queue_family = physical.queue_families().find(|&q| { q.supports_graphics() && surface.is_supported(q).unwrap_or(false) }).unwrap();
(5)Vulkanデバイスとキューの作成
Vulkanデバイスとキューを作成します。
let (device, mut queues) = { let device_ext = vulkano::device::DeviceExtensions { khr_swapchain: true, .. vulkano::device::DeviceExtensions::none() }; Device::new(physical, physical.supported_features(), &device_ext, [(queue_family, 0.5)].iter().cloned()).expect("failed to create device") }; let queue = queues.next().unwrap();
最後の行で、作成したqueues(キューのイテレータ)から、最初の要素
(next)を使用するキューとして取り出します。
ここまでの段階では、作成されたウィンドウは瞬時に閉じてしまいます。
そこで、events_loopを使ってウィンドウの表示を行います。
let mut done = false; loop { events_loop.poll_events(|event| { match event { winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true, _ => () } }); if done { return; } }
ウィンドウの終了フラッグ(done)を用いて、ウィンドウのクローズボタンが
押されたときにウィンドウを閉じるようにします。
これで、黒い画面(初期化されていない)のウィンドウが表示されます。
全体のプログラムは、次のようになります。
extern crate vulkano_win; extern crate winit; extern crate vulkano; use vulkano_win::VkSurfaceBuild; use winit::EventsLoop; use winit::WindowBuilder; use vulkano::instance::{Instance, PhysicalDevice}; use vulkano::device::Device; fn main() { // Instance let instance = { let extensions = vulkano_win::required_extensions(); Instance::new(None, &extensions, None).expect("failed to create Vulkan instance") }; // Surface and Window let mut events_loop = EventsLoop::new(); let surface = WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap(); // Physical Device let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); // QueueFamily let queue_family = physical.queue_families().find(|&q| { q.supports_graphics() && surface.is_supported(q).unwrap_or(false) }).unwrap(); // Device and Queues let (device, mut queues) = { let device_ext = vulkano::device::DeviceExtensions { khr_swapchain: true, .. vulkano::device::DeviceExtensions::none() }; Device::new(physical, physical.supported_features(), &device_ext, [(queue_family, 0.5)].iter().cloned()).expect("failed to create device") }; let queue = queues.next().unwrap(); let mut done = false; loop { // EventsLoop events_loop.poll_events(|event| { match event { winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true, _ => () } }); if done { return; } } }