Git Product home page Git Product logo

vulkan-tutorial-rs's Introduction

Vulkan tutorial

Vulkan tutorials written in Rust using Ash. The extended branch contains a few more chapters that I won't merge on that branch since I want it to stay close to the original tutorial. Please check it out :). If you wan't to run it on android see the android branch.

The end result

Introduction

This repository will follow the structure of the original tutorial. Each commit will correspond to one page or on section of the page for long chapters.

Sometimes an 'extra' commit will be added with some refactoring, commenting or feature.

All chapters of the original tutorial are now covered. The code compiles on windows, linux and macos and runs on windows, and linux. It should also run on macos but I haven't been able to test yet. I'll update this statement when I (or someone else) can try.

Requirements

You need to have a Vulkan SDK installed and glslangValidator executable in your PATH. This should be the case when installing the Vulkan SDK.

If for some reason you want to skip the shader compilation when buiding the project you can set the SKIP_SHADER_COMPILATION environment variable to true. Though you will need to provide the compiled shaders for the program to run.

Commits

This section contains the summary of the project commits. Follow ๐Ÿ‡ to go to the related tutorial page.

1.1.1: Base code ๐Ÿ‡

Application setup. We don't setup the window system now as it's done in the original tutorial.

1.1.2: Instance ๐Ÿ‡

Create and destroy the Vulkan instance with required surface extensions.

1.1.3: Validation layers ๐Ÿ‡

Add VK_LAYER_LUNARG_standard_validation at instance creation and creates a debug report callback function after checking that it is available. Since we are using the log crate, we log the message with the proper log level. The callback is detroyed at application termination.

1.1.4: Physical devices and queue families ๐Ÿ‡

Find a physical device with at least a queue family supporting graphics.

1.1.5: Logical device and queues ๐Ÿ‡

Create the logical device interfacing with the physical device. Then create the graphics queue from the device.

1.1.extra: Refactoring and comments

  • Update the readme with explanations on the structure of the repository.
  • Move validation layers related code to its own module.
  • Disabled validation layers on release build.

1.2.1: Window surface ๐Ÿ‡

Create the window, the window surface and the presentation queue. Update the physical device creation to get a device with presentation support. At that point, the code will only work on Windows.

1.2.2: Swapchain ๐Ÿ‡

Checks for swapchain support and enable device extension for swapchain. Then query the swapchain details and choose the right settings. Then create the swapchain and retrieve the swapchain images.

1.2.3: Image views ๐Ÿ‡

Create the image views to the swapchain images.

1.2.extra: Refactoring swapchain creation

Add SwapchainProperties to hold the format, present mode and extent of our swapchain. Add a method to build the best properties to SwapchainSupportDetails. Move these two struct into the swapchain module.

1.3.2: Shader module ๐Ÿ‡

Create the vertex and fragment shaders GLSL source and add a compile.bat script to compile it into SPIR-V bytecode using glslangValidator. Load the compiled SPIR-V and create a ShaderModule from it.

In this section I forgot to create the shader stage create info structures. It's ok they will be created in 1.3.5: Graphics pipeline.

1.3.3: Fixed functions ๐Ÿ‡

This one is huge so it will be split across several commits.

  • 1.3.3.1: Vertex input and input assembly

Create the vertex input and input assembly info for the pipeline.

  • 1.3.3.2: Viewports and scissors

Create the viewport and scissor info for the pipeline.

  • 1.3.3.3: Rasterizer

Create the rasterizer info for the pipeline.

  • 1.3.3.4: Multisampling

Create the multisampling info for the pipeline.

  • 1.3.3.5: Color blending

Create color blend attachment and color blend info for the pipeline.

  • 1.3.3.6: Pipeline layout

Create the pipeline layout info.

1.3.4: Render passes ๐Ÿ‡

Create the render pass.

1.3.5: Graphics pipeline ๐Ÿ‡

Create the PipelineShaderStageCreateInfo that we forgot in 1.3.2: Shader module.

Create the grahics pipeline.

1.3.extra: Shader compilation refactoring

Until now we compiled the shaders with a compile.bat script that we have to run manually before running the application. In this section, we will compite them when building the application using Cargo's build scripts.

The build script scan the content of the shaders directory and generates a compiled SPIR-V shader for each file it founds. The files are generated in a the same directory as the GLSL shaders and with the same name appended with .spv.

1.4.1: Framebuffers ๐Ÿ‡

Create one framebuffer for each image of the swapchain.

1.4.2: Command buffers ๐Ÿ‡

Create a command pool and allocate one command buffer per swapchain image. Then we register all the commands required to render.

1.4.3: Rendering and presentation ๐Ÿ‡

This section is also split across multiple commits.

  • 1.4.3.1: Main loop

Setup the main loop.

  • 1.4.3.2: Semaphores

Create a semphore to signal that an image has been acquired and another one to signal that the rendering to the image is finished.

  • 1.4.3.3: Rendering the triangle!

Acquire the next image from the swapchain, submit the command buffer and present the rendered image.

The first triangle!

  • 1.4.3.4: Frames in flight

Limit the number of frames that can be renderer simultaneously using fences.

1.4.extra: Refactoring

  • Add QueueFamilyIndices structure and return it at physical device creation to avoid having to recreate it multiple times.
  • Add SyncObjects containing the semaphores and fence for one frame.
  • Add InFlightFrames containing all SyncObjects and the current frame index.
  • Implement Iterator for InFlightFrames so we just need to call next() to get next frame sync objects.

1.5: Swapchain recreation ๐Ÿ‡

Handle swapchain recreation when resizing the window or when the swapchain is suboptimal or out of date.

2.1: Vertex input description ๐Ÿ‡

Remove hard coded vertices from the vertex shader source and create vertices on the cpu. Update the pipeline with the vertex binding and attributes description.

2.2: Vertex buffer creation ๐Ÿ‡

Create and fill the vertex buffer and bind it before rendering.

2.3: Staging buffer ๐Ÿ‡

Create a staging buffer for the vertex data and copy the vertex data from this buffer's memory to the memory of the device local buffer.

The tutorial also suggests that we allocate command buffers used for memory copy from a command pool dedicated to short-lived command buffers, so we did that too.

2.4: Index buffer ๐Ÿ‡

Use index buffer to reuse vertice when drawing a rectangle.

In the original tutorial the create_index_buffer is the same as create_vertex_buffer but with the vertex data replaced with the index data. To limit duplication we've added a method that creates and fill a buffer and fill it with the passed data. This method is called from create_vertex_buffer and create_index_buffer.

Then a quad.

3.1: Descriptor layout and buffer ๐Ÿ‡

Create a UniformBufferObject structure containing transformation matrices and create the descriptor layout and buffers used to make it accessible from the vertex shader.

Also add a math module containing a perspective function that creates a prespective matrix that is working with Vulkan's NDC.

3.2: Descriptor pool and sets ๐Ÿ‡

Create a descriptor pool and allocate a descriptor set for each descriptor buffer.

With MVP matrices.

4.1: Images ๐Ÿ‡

This section is split too.

  • 4.1.1: Loading an image

Load an image from a file.

  • 4.1.2: Creating the image

Create an host visible staging buffer for image data and create a device local image. At this point the image is empty, we will copy the buffer data in a later section.

  • 4.1.3: Copying buffer data into the image

Copy the image data store in the host visible buffer to the device local image.

4.2: Image view and sampler ๐Ÿ‡

Create the image view and sampler. Also enable the sampler anisotropy feature.

4.3: Combined image sampler ๐Ÿ‡

Update the descriptor set, add texture coordinates to Vertex and update the shaders to read texture coordinates and sample the texture.

Textured.

5: Depth buffering ๐Ÿ‡

Update Vertex to make the position 3d. Update the vertex shader to take the new dimension into account. Add a new quad to render. And setup depth buffer so the new quad is renderer correctly relatively to the other. Recreate the depth buffer resources when the swapchain is recreated.

With a friend!

5.extra: Refactoring

Add Texture struct which will hold the resources required by mutable image, (image, memory, view and optionnally a sampler).

Add VkContext that will hold the instance, debug callback, physical and logical devices, and surface.

Overall refactoring of the code with some Rust specific code smell fixes.

6: Loading models ๐Ÿ‡

Load a 3D model from an wavefront obj file and render it. We skip the deduplication step because the crate we use to load obj files already does it.

6.extra: Orbital camera

Since 3.1: Descriptor layout and buffer, our rendered geometry has been spinning infinitely around its local z axis. In this chapter we change this behaviour and implement an orbital camera controlled with the mouse.

You can scroll the mouse wheel to get closer or further away from the global origin. And you can left click and move the mouse to move around the global origin.

7: Generating mpimaps ๐Ÿ‡

Generate mipmaps for the model texture and update the sampler to make use of them.

8: Multisampling ๐Ÿ‡

Add multisampling anti-aliasing.

The end result

Run it

With validation layers:

RUST_LOG=vulkan_tutorial_ash=debug cargo run

The RUST_LOG level will affect the log level of the validation layers too.

or without:

cargo run --release

Links

Vulkan tutotial

Ash

Rust docs

Cargo docs

Vulkan SDK

Vulkan specs

The image statue

The 3D model

Credits

Thanks to Alexander Overvoorde for this amazing tutorials.

vulkan-tutorial-rs's People

Contributors

adrien-ben avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

vulkan-tutorial-rs's Issues

Strange resize behavior in chapter 1.5: Swapchain recreation

First and foremost, thank you for the great tutorial. I'm currently following it and I've got to the chapter 1.5. When implemented, the code does not enable window resizing (only maximizing and switching back to the original size works). At first I was thinking that it all comes to my own modifications (I'm using the latest version of the libraries, most notably the latest version of winit), but after spending some time I failed to grasp the problem and checked out your repository at the corresponding commit - the behavior is the same, only maximized and original sizes are reachable.

Could you please tell me if it's by design?

Missing VK_KHR_portability_subset device extension

I am currently learning Rust and Vulkan and following the tutorial with your repository. Since I am on macOS and using MoltenVK I got a validation error enforcing VK_KHR_portability_subset when the device supports it. After some trial and error I was finally able to fix the validation error: https://github.com/ChristianIvicevic/blight/commit/a32f3a40d14829e76aab71fe8dbb565588fbf4e2

Are you open for a PR to add this check to your repository as well?

vkCmdCopyBuffer error

Hello. Sorry to bother you again, but in the chapter that describes the staging buffer implementation (this commit), there's an error emitted to the log (everything works though):

vulkan_tutorial_ash::debug] BUFFER - " [ VUID-vkCmdCopyBuffer-size-00115 ] Object: 0x51b3510000000014 (Type = 9) | vkCmdCopyBuffer(): pRegions[0].size (256) is greater than the source buffer size (60) minus pRegions[0].srcOffset (0). The Vulkan spec states: The size member of each element of pRegions must be less than or equal to the size of srcBuffer minus srcOffset (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkCmdCopyBuffer-size-00115)"

It looks like mem_requirements.size is 256, while the size is 3 * 20 = 60. Although everything works, I cannot wrap my mind around this error and why it is emitted.

I've tried changing the code like this:

 Self::copy_buffer(
            physical_device,
            command_pool,
            transfer_queue,
            staging_buffer,
            buffer,
            /*staging_mem_size*/ size,
        );

and the error is gone.

Could you please provide some guidance on this one?
As far as I understand, the source buffer is 60 bytes but requires 256, so it looks like [information in 0- 59 | 60 - 255 filled with any values], and the destination buffer is also 60 bytes long with 256 bytes needed and has the very same structure. So the validation layer is upset when we copy more than 60 bytes, but it works because bytes from 60 to 255 do not matter anyway. Do I understand this correctly?

How to run on android

Hello. Would you be able to describe how to run it on android. Me and my colleague are in trouble. Thanks in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.