From 5893e95032971df09ca9b2f5d13cec77ed48d3d0 Mon Sep 17 00:00:00 2001 From: Karn Kaul Date: Wed, 2 Apr 2025 19:43:17 -0700 Subject: [PATCH 1/3] Only deploy from `staging` and `production` --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a42b725..c08ba18 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,8 +1,8 @@ -name: Deploy +name: deploy on: push: branches: - - main + - production - staging jobs: deploy: From 0a827e0af29f69026e474f1c5137164dc88643c8 Mon Sep 17 00:00:00 2001 From: Karn Kaul Date: Wed, 2 Apr 2025 19:54:56 -0700 Subject: [PATCH 2/3] Replace 'registry.khronos' links with 'docs.vulkan' ones --- guide/src/initialization/device.md | 2 +- guide/src/initialization/gpu.md | 2 +- guide/src/initialization/instance.md | 2 +- guide/src/initialization/surface.md | 2 +- guide/src/initialization/swapchain.md | 2 +- guide/src/rendering/swapchain_loop.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/guide/src/initialization/device.md b/guide/src/initialization/device.md index 5dfbdde..5cb2530 100644 --- a/guide/src/initialization/device.md +++ b/guide/src/initialization/device.md @@ -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: diff --git a/guide/src/initialization/gpu.md b/guide/src/initialization/gpu.md index a06bf14..e3a5ac6 100644 --- a/guide/src/initialization/gpu.md +++ b/guide/src/initialization/gpu.md @@ -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 diff --git a/guide/src/initialization/instance.md b/guide/src/initialization/instance.md index a2fa674..da6cef2 100644 --- a/guide/src/initialization/instance.md +++ b/guide/src/initialization/instance.md @@ -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: diff --git a/guide/src/initialization/surface.md b/guide/src/initialization/surface.md index fd51a5a..629c55c 100644 --- a/guide/src/initialization/surface.md +++ b/guide/src/initialization/surface.md @@ -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`: diff --git a/guide/src/initialization/swapchain.md b/guide/src/initialization/swapchain.md index c5565b0..9fdeccc 100644 --- a/guide/src/initialization/swapchain.md +++ b/guide/src/initialization/swapchain.md @@ -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. diff --git a/guide/src/rendering/swapchain_loop.md b/guide/src/rendering/swapchain_loop.md index 747c271..64f7043 100644 --- a/guide/src/rendering/swapchain_loop.md +++ b/guide/src/rendering/swapchain_loop.md @@ -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 From 79563f7cfe2d8709fc36d524e3f19fc52987fb18 Mon Sep 17 00:00:00 2001 From: Karn Kaul Date: Wed, 2 Apr 2025 21:12:19 -0700 Subject: [PATCH 3/3] Expand README --- README.md | 26 ++++++++++++++++++++++++++ guide/src/README.md | 5 +++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 60ee915..f9d0252 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/guide/src/README.md b/guide/src/README.md index 4e1059e..903bbb9 100644 --- a/guide/src/README.md +++ b/guide/src/README.md @@ -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: @@ -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: @@ -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. -