Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: Deploy
name: deploy
on:
push:
branches:
- main
- production
- staging
jobs:
deploy:
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
# Learn Vulkan

[![Build status](https://github.com/cpp-gamedev/learn-vulkan/actions/workflows/ci.yml/badge.svg)](https://github.com/cpp-gamedev/learn-vulkan/actions/workflows/ci.yml)

This repository hosts the [learn-vulkan](https://cpp-gamedev.github.io/learn-vulkan/) guide's C++ source code. It also hosts the sources of the [guide](./guide) itself.

## Building

### Requirements

- CMake 3.24+
- C++23 compiler and standard library
- [Linux] [GLFW dependencies](https://www.glfw.org/docs/latest/compile_guide.html#compile_deps_wayland) for X11 and Wayland

### Steps

Standard CMake workflow. Using presets is recommended, in-source builds are not recommended. See the [CI script](.github/workflows/ci.yml) for building on the command line.

## Branches

1. `main`^: latest, stable code (builds and runs), stable history (never rewritten)
1. `production`^: guide deployment (live), stable code and history
1. `section/*`^: reflection of source at the end of corresponding section in the guide, stable code
1. `feature/*`: potential upcoming feature, shared contributions, stable history
1. others: unstable

_^ rejects direct pushes (PR required)_

[Original Repository](https://github.com/cpp-gamedev/learn-vulkan)
5 changes: 3 additions & 2 deletions guide/src/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Introduction

Vulkan is known for being explicit and verbose. But the _required_ verbosity has steadily reduced with each successive version, its new features, and previous extensions being absorbed into the core API. Similarly, RAII has been a pillar of C++ since its inception, yet most Vulkan guides do not utilize it, instead choosing to "extend" the explicitness by manually cleaning up resources.
Vulkan is known for being explicit and verbose. But the _required_ verbosity has steadily reduced with each successive version, its new features, and previous extensions being absorbed into the core API. Similarly, RAII has been a pillar of C++ since its inception, yet most existing Vulkan tutorials do not utilize it, instead choosing to "extend" the explicitness by manually cleaning up resources.

To fill that gap, this guide has the following goals:

Expand All @@ -10,6 +10,8 @@ To fill that gap, this guide has the following goals:

To reiterate, the focus is _not on performance_, it is on a quick introduction to the current standard multi-platform graphics API while utilizing the modern paradigms and tools (at the time of writing). Even disregarding potential performance gains, Vulkan has a better and more modern design and ecosystem than OpenGL, eg: there is no global state machine, parameters are passed by filling structs with meaningful member variable names, multi-threading is largely trivial (yes, it is actually easier to do on Vulkan than OpenGL), there are a comprehensive set of validation layers to catch misuse which can be enabled without _any_ changes to application code, etc.

For an in-depth Vulkan guide, the [official tutorial](https://docs.vulkan.org/tutorial/latest/00_Introduction.html) is recommended. [vkguide](https://vkguide.dev/) and the original [Vulkan Tutorial](https://vulkan-tutorial.com/) are also very popular and intensely detailed.

## Target Audience

The guide is for you if you:
Expand All @@ -30,4 +32,3 @@ Some examples of what this guide _does not_ focus on:
## Source

The source code for the project (as well as this guide) is located in [this repository](https://github.com/cpp-gamedev/learn-vulkan). A `section/*` branch intends to reflect the state of the code at the end of a particular section of the guide. Bugfixes / changes are generally backported, but there may be some divergence from the current state of the code (ie, in `main`). The source of the guide itself is only up-to-date on `main`, changes are not backported.

2 changes: 1 addition & 1 deletion guide/src/initialization/device.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Vulkan Device

A [Vulkan Device](https://registry.khronos.org/vulkan/specs/latest/man/html/VkDevice.html) is a logical instance of a Physical Device, and will the primary interface for everything Vulkan now onwards. [Vulkan Queues](https://registry.khronos.org/vulkan/specs/latest/man/html/VkQueue.html) are owned by the Device, we will need one from the queue family stored in the `Gpu` to submit recorded command buffers. We also need to explicitly declare all features we want to use, eg [Dynamic Rendering](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_dynamic_rendering.html) and [Synchronization2](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_synchronization2.html).
A [Vulkan Device](https://docs.vulkan.org/spec/latest/chapters/devsandqueues.html#devsandqueues-devices) is a logical instance of a Physical Device, and will the primary interface for everything Vulkan now onwards. [Vulkan Queues](https://docs.vulkan.org/spec/latest/chapters/devsandqueues.html#devsandqueues-queues) are owned by the Device, we will need one from the queue family stored in the `Gpu` to submit recorded command buffers. We also need to explicitly declare all features we want to use, eg [Dynamic Rendering](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_dynamic_rendering.html) and [Synchronization2](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_synchronization2.html).

Setup a `vk::QueueCreateInfo` object:

Expand Down
2 changes: 1 addition & 1 deletion guide/src/initialization/gpu.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Vulkan Physical Device

A [Physical Device](https://registry.khronos.org/vulkan/specs/latest/man/html/VkPhysicalDevice.html) represents a single complete implementation of Vulkan, for our intents and purposes a single GPU. (It could also be eg a software renderer like Mesa/lavapipe.) Some machines may have multiple Physical Devices available, like laptops with dual-GPUs. We need to select the one we want to use, given our constraints:
A [Physical Device](https://docs.vulkan.org/spec/latest/chapters/devsandqueues.html#devsandqueues-physical-device-enumeration) represents a single complete implementation of Vulkan, for our intents and purposes a single GPU. (It could also be eg a software renderer like Mesa/lavapipe.) Some machines may have multiple Physical Devices available, like laptops with dual-GPUs. We need to select the one we want to use, given our constraints:

1. Vulkan 1.3 must be supported
1. Vulkan Swapchains must be supported
Expand Down
2 changes: 1 addition & 1 deletion guide/src/initialization/instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Instead of linking to Vulkan (via the SDK) at build-time, we will load Vulkan at
1. In `app.cpp` this line is added to the global scope: `VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE`
1. Before and during initialization `VULKAN_HPP_DEFAULT_DISPATCHER.init()` is called

The first thing to do in Vulkan is to create an [Instance](https://registry.khronos.org/vulkan/specs/latest/man/html/VkInstance.html), which will enable enumeration of physical devices (GPUs) and creation of a logical device.
The first thing to do in Vulkan is to create an [Instance](https://docs.vulkan.org/spec/latest/chapters/initialization.html#initialization-instances), which will enable enumeration of physical devices (GPUs) and creation of a logical device.

Since we require Vulkan 1.3, store that in a constant to be easily referenced:

Expand Down
2 changes: 1 addition & 1 deletion guide/src/initialization/surface.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Vulkan Surface

Being platform agnostic, Vulkan interfaces with the WSI via the [`VK_KHR_surface` extension](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_surface.html). A [Surface](https://registry.khronos.org/vulkan/specs/latest/man/html/VkSurfaceKHR.html) enables displaying images on the window through the presentation engine.
Being platform agnostic, Vulkan interfaces with the WSI via the [`VK_KHR_surface` extension](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_surface.html). A [Surface](https://docs.vulkan.org/guide/latest/wsi.html#_surface) enables displaying images on the window through the presentation engine.

Add another helper function in `window.hpp/cpp`:

Expand Down
2 changes: 1 addition & 1 deletion guide/src/initialization/swapchain.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Swapchain

A [Vulkan Swapchain](https://registry.khronos.org/vulkan/specs/latest/man/html/VkSwapchainKHR.html) is an array of presentable images associated with a Surface, which acts as a bridge between the application and the platform's presentation engine (compositor / display engine). The Swapchain will be continually used in the main loop to acquire and present images. Since failing to create a Swapchain is a fatal error, its creation is part of the initialization section.
A [Vulkan Swapchain](https://docs.vulkan.org/guide/latest/wsi.html#_swapchain) is an array of presentable images associated with a Surface, which acts as a bridge between the application and the platform's presentation engine (compositor / display engine). The Swapchain will be continually used in the main loop to acquire and present images. Since failing to create a Swapchain is a fatal error, its creation is part of the initialization section.

We shall wrap the Vulkan Swapchain into our own `class Swapchain`. It will also store the a copy of the Images owned by the Vulkan Swapchain, and create (and own) Image Views for each Image. The Vulkan Swapchain may need to be recreated in the main loop, eg when the framebuffer size changes, or an acquire/present operation returns `vk::ErrorOutOfDateKHR`. This will be encapsulated in a `recreate()` function which can simply be called during initialization as well.

Expand Down
2 changes: 1 addition & 1 deletion guide/src/rendering/swapchain_loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Additionally, the number of swapchain images can vary, whereas the engine should

## Virtual Frames

All the dynamic resources used during the rendering of a frame comprise a virtual frame. The application has a fixed number of virtual frames which it cycles through on each render pass. For synchronization, each frame will be associated with a [`vk::Fence`](https://registry.khronos.org/vulkan/specs/latest/man/html/VkFence.html) which will be waited on before rendering to it again. It will also have a pair of [`vk::Semaphore`](https://registry.khronos.org/vulkan/specs/latest/man/html/VkSemaphore.html)s to synchronize the acquire, render, and present calls on the GPU (we don't need to wait for them on the CPU side / in C++). For recording commands, there will be a [`vk::CommandBuffer`](https://docs.vulkan.org/spec/latest/chapters/cmdbuffers.html) per virtual frame, where all rendering commands for that frame (including layout transitions) will be recorded.
All the dynamic resources used during the rendering of a frame comprise a virtual frame. The application has a fixed number of virtual frames which it cycles through on each render pass. For synchronization, each frame will be associated with a [`vk::Fence`](https://docs.vulkan.org/spec/latest/chapters/synchronization.html#synchronization-fences) which will be waited on before rendering to it again. It will also have a pair of [`vk::Semaphore`](https://docs.vulkan.org/spec/latest/chapters/synchronization.html#synchronization-semaphores)s to synchronize the acquire, render, and present calls on the GPU (we don't need to wait for them on the CPU side / in C++). For recording commands, there will be a [`vk::CommandBuffer`](https://docs.vulkan.org/spec/latest/chapters/cmdbuffers.html) per virtual frame, where all rendering commands for that frame (including layout transitions) will be recorded.

## Image Layouts

Expand Down