5
1

More than 3 years have passed since last update.

Vulkan TutorialのRust版をやってみた 〜描画編〜

Posted at

Vulkanの入門をRustでやっていきます。目次はこちら。今回までの実装をしたGitHubはこちら

Vulkanでの描画

ついに今回は三角形を描画します。描画には今までのrender pass等に加えバッファが必要になります。

framebufferの作成

framebufferはswap chainの各image毎に作るもので、render passで設定したとおりに各attachmentにデータを渡す、文字通りバッファとして働くようです。

let _framebuffers: Vec<_> = spwapchain_image
    .iter()
    .map(|image| {
        Arc::new(
            Framebuffer::start(render_pass.clone())
                .add(image.clone())
                .unwrap()
                .build()
                .expect("Could not create a framebuffer"),
        )
    })
    .collect();

command bufferの作成

そのまんま、commandのバッファです。Vulkanoの場合はAutoCommandBufferBuilderでcommand bufferとcommand poolを作成します。また、各framebuffer毎に作るので以下を各framebuffer毎に行います。

AutoCommandBufferBuilder::primary_simultaneous_use(
    device.clone(),
    graphics_queue.family()
).unwrap()
.begin_render_pass(
    framebuffer.clone(),
    false,
    vec![[0.0, 0.0, 0.0, 1.0].into()],
).unwrap()
.draw(
    graphics_pipeline.clone(),
    &DynamicState::none(),
    vertices,
    (),
    (),
).unwrap()
.end_render_pass().unwrap()
.build().unwrap()

ここで怒涛の.unwrap()となっており、本当は独自のResultを定義して.and_then()等をする方が良いのだと思うのですが、簡単のため.unwrap()にしています(ビルダーパターンなんだから本当はVulkano側でなんとかしてほしい。)

描画

ここまでの用意でようやく三角形が描画できます。なお、Vulkanoではacquire_next_imageという関数が用意されているため、semaphoreは不要です。
まず描画するための関数を呼び出す場所ですが、winit = "0.22.0"では

match event {
    Event::MainEventsCleared => {
        surface.window().request_redraw(); // イベント消化後に描画要求
    }
    Event::RedrawRequested(_) => {
        /* ここで描画 */
    }
    _ => {}
}

となっています。この中で描画用のimageを要求し、commandを実行させ、それを画面上に反映するという流れです。

if let Ok((image_index, _, acquire_future)) =
    acquire_next_image(swapchain.clone(), None)
{
    let command_buffer = command_buffers[image_index].clone();
    if let Ok(future) =
        acquire_future.then_execute(graphics_queue.clone(), command_buffer)
    {
        let _ = future
            .then_swapchain_present(
                present_queue.clone(),
                swapchain.clone(),
                image_index,
            )
            .then_signal_fence_and_flush()
            .and_then(|future| future.wait(None));
    }
}

なお今回は描画ループ内なので.unwrap()を避けて書いてみました。

まとめと感想

ついに三角形を描画できました。まだ理解しきれていないところも多く、OpenGLと比較してもやはり難しくなっていると感じました。

5
1
0

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
5
1