Rust version of
https://github.com/Overv/VulkanTutorial
using
.
Goal: Rust port with code structure as similar as possible to the original C++, so the original tutorial can easily be followed (similar to
).
Current State: The chapters Drawing a triangle and Vertex buffers are complete.
———
Physical devices and queue families
Introduction
This tutorial consists of the the ported code and notes about the differences between the original C++ and the Rust code. The
generally apply equally, although the Rust version is often shorter due to the use of
, a safe wrapper around the Vulkan API with some convenience functionality (the final triangle example is about 600 lines, compared to 950 lines in C++).
If you prefer a lower-level API closer to the Vulkan C API, have a look at
and
.
Overview
https://vulkan-tutorial.com/Overview
(nothing to note here)
Development Environment
https://vulkan-tutorial.com/Development_environment
Download the Vulkan SDK as described, but ignore everything about library and project setup. Instead, create a new Cargo project:
$ cargo new vulkan-tutorial-rs Then add this to your Cargo.toml:
[dependencies] vulkano = "0.11.1" On macOS, copy
, adapt the VULKAN_SDK path if necessary and source the file in your terminal. See also
vulkano-rs/vulkano#macos-and-ios-specific-setup
.
Drawing a triangle
Setup
Base code
https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Base_code
General structureexterncrate vulkano;structHelloTriangleApplication{}implHelloTriangleApplication{pubfninitialize() -> Self{Self{}}fnmain_loop(&mutself){}}fnmain(){letmut app = HelloTriangleApplication::initialize(); app.main_loop();}Resource managementVulkano handles calling vkDestroyXXX/vkFreeXXX in the Drop implementation of all wrapper objects, so we will skip all cleanup code.
Integrating GLFW winitInstead of GLFW we'll be using
, an alternative window managment library written in pure Rust.
Add this to your Cargo.toml:
winit = "0.18.0" And extend your main.rs:
externcrate winit;use winit::{EventsLoop,WindowBuilder, dpi::LogicalSize};constWIDTH:u32 = 800;constHEIGHT:u32 = 600;structHelloTriangleApplication{events_loop:EventsLoop,}pubfninitialize() -> Self{let events_loop = Self::init_window();Self{ events_loop,}}fninit_window() -> EventsLoop{let events_loop = EventsLoop::new();let _window = WindowBuilder::new().with_title("Vulkan").with_dimensions(LogicalSize::new(f64::from(WIDTH), f64::from(HEIGHT))).build(&events_loop); events_loop }fnmain_loop(&mutself){loop{letmut done = false;self.events_loop.poll_events(|ev| {ifletEvent::WindowEvent{event:WindowEvent::CloseRequested, .. } = ev { done = true}});if done {return;}}}
Instance
https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
Cargo.toml:
vulkano-win = "0.11.1" main.rs:
externcrate vulkano_win;use std::sync::Arc;use vulkano::instance::{Instance,InstanceExtensions,ApplicationInfo,Version,};structHelloTriangleApplication{instance:Option<Arc<Instance>>,events_loop:EventsLoop,}pubfninitialize() -> Self{let instance = Self::create_instance();let events_loop = Self::init_window();Self{ instance, events_loop,}}fncreate_instance() -> Arc<Instance>{let supported_extensions = InstanceExtensions::supported_by_core().expect("failed to retrieve supported extensions");println!("Supported extensions: {:?}", supported_extensions);let app_info = ApplicationInfo{application_name:Some("Hello Triangle".into()),application_version:Some(Version{major:1,minor:0,patch:0}),engine_name:Some("No Engine".into()),engine_version:Some(Version{major:1,minor:0,patch:0}),};let required_extensions = vulkano_win::required_extensions();Instance::new(Some(&app_info),&required_extensions,None).expect("failed to create Vulkan instance")}
/
Validation layers
https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers
From here on we'll just link to the code instead of putting everything in the README:
/
Physical devices and queue families
https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Physical_devices_and_queue_families
/
Logical device and queues
https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Logical_device_and_queues
/
Presentation
Window surface
https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Window_surface
/
Swap chain
https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain
/
Image views
https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Image_views
We're skipping this section because image views are handled by Vulkano and can be accessed via the SwapchainImages created in the last section.
Graphics pipeline basics
Introduction
https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics
/
Shader Modules
https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Shader_modules
Instead of compiling the shaders to SPIR-V manually and loading them at runtime, we'll use
to do the same at compile-time. Loading them at runtime is also possible, but a bit more invovled - see the
example of Vulkano.
/
/
/
Fixed functions
https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Fixed_functions
/
Render passes
https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Render_passes
/
Conclusion
https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Conclusion
/
Drawing
Framebuffers
https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Framebuffers
/
Command buffers
https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Command_buffers
We're skipping the first part because Vulkano maintains a
.
/
Rendering and presentation
https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Rendering_and_presentation
/
Swapchain recreation
https://vulkan-tutorial.com/Drawing_a_triangle/Swap_chain_recreation
/
Vertex buffers
Vertex input description
https://vulkan-tutorial.com/Vertex_buffers/Vertex_input_description
/
(Rust code combined with next section, since this alone won't compile)
Vertex buffer creation
https://vulkan-tutorial.com/Vertex_buffers/Vertex_buffer_creation
/
Staging buffer
https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer
We're just replacing CpuAccessibleBuffer with ImmutableBuffer, which uses a staging buffer internally. See
for an overview of Vulkano's buffer types.
/
Index buffer
https://vulkan-tutorial.com/Vertex_buffers/Index_buffer
/
Uniform buffers
Uniform Buffer Object
https://vulkan-tutorial.com/Uniform_buffers
In this section we change the vertex shader to take a uniform buffer object consisting of a model, view, and projection matrix. The shader now outputs the final position as the result of multiplying these three matrices with the original vertex position.
We add a new type of buffer, the CpuAccessibleBuffer, which allows us to update its contents without needing to rebuild the entire buffer. In order to actually be able to write to this buffer we need to specify its usage as a uniform buffer and also the destination of a memory transfer.
Note that unlike the original tutorial we did not need to create any layout binding. This is handled internally by vulkano when creating a descriptor set, as we'll see in the next section.
At this point our program will compile and run but immediately panic because we specify a binding in our shader but do not include a matching descriptor set.
/
/
Texture mapping (TODO)
Depth buffering (TODO)
Loading models (TODO)
Generating Mipmaps (TODO)
Multisampling (TODO)