Vulkan
- Publish Date
This post serves as my notes for my journey on Vulkan development. Several years ago, I followed the guide on vulkan-tutorial.com and built a rendering engine. While it yielded success, I didn't learn from it about the architecture of Vulkan since I had a hard time keeping up with the pace of it. Last Monday, I stumbled upon vkguide.dev, which provides me with a warm welcome to Vulkan and a means of getting my hands wet. The thing about this tutorial is that it is a revised version of the original vulkan-tutorial, as its predecessor was written when developers first learned about using it. I hope that I can fully tap into the immense knowledge provided in this guide.
Specifications
- Vulkan Version: 1.3.x
- Discrete GPU: 4070 Ti
- CPU: AMD Ryzen 9 5950x
Resources
Concepts
Physical vs Logical Devices
In Vulkan, many objects are handles pointing (yes, pointers) to something that already exists.
These handles specifically used to point to physical components on your computer are called
physical devices. Now, when we want to interact with the components, we need a logical device,
instantiated by feeding vkCreateDevice
with our physical device (think about it as a description)
and other information.
Sync Structures
Modern computer graphics is usually married with parallel computing. For instance, GPUs are the physical representation of parallel computing/processing, since they can simultaneously process data on different cores (see SIMD on Wikipedia); meanwhile, CPUs can also have multiple threads running on multiple physical cores.
As beneficial as parallel computing seems, it raises some looming problems caused by desynchronization --
our commands (on the GPU after being submitted to VkQueue
) need to wait for the swapchain to
yield an image so that it can compute/render it. How do we know if it's ready? Enter VkSemaphore
,
which is a way to make sure GPU commands can be sync-ed with each other. A semaphore is split into
two types: wait semaphores and signal semaphores. There can only be one signal semaphores, while there's
no uppper limit for the number of wait semaphores. Semaphores in Vulkan are used exclusively for
GPU-to-GPU operations, so the developers at Khronos Group come up with VkFence
for GPU-to-CPU operations,
which works identically1.
Command Execution Process
The way Vulkan handles commands sent to a GPU is by using VkQueue
structs. A sequence of command is represented by VkCommandBuffer
,
the allocation of which is done by allocators of VkCommandPool
. A VkQueue
is a handle pointing to an existing structure of your system,
similar to VkPhysicalDevice
. Remember there can be conflicts between different queues (such as graphics queue versus compute queue), so
sync structures come in handy.
The above image is sourced from vkguide.dev. Note that renderpass is not commonly
used in newer versions of Vulkan. Instead, we use vkBeginCommandBuffer
.
Images
Images in Vulkan are represented as VkImage
. These opaque handles are best accessed via image views. By default, images sent to/from GPUs
(swapchain images) aren't readable by us, since they are in the optimal format for GPU access. To write to our images, we need to change
their format, using our function vkutil::transition_image
. Nonetheless, it isn't a good idea to write to swapchain images directly since
we have to create a new image should any properties of them change on the fly; instead, we should write to another independent image, and
blit (BITBLT) it to our swapchain images, hence the need of vkutil::copy_image_to_image
.
Descriptor Sets
A descriptor is a handle/pointer that accesses specific Vulkan structures. Take a buffer descriptor as an example. We can use it to access
command buffers. To allocate descriptors, we have to initialize them in batch. The cluster of them is called a descriptor set which can be
instantiated with VkDescriptorPool
following the instructions of VkDescriptorSetLayout
. For shaders to read data, we must bind descriptors
to our rendering pipelines.
Libraries
WIP... (◉ 3 ◉)
Edit Logs
- 1.28.2024: First log
- 1.29.2024: changed links
- 1.30.2024: add link ref; commandbuf;
- 2.1.2024: added image source;
- 4.24.2024: added trad chinese translation
Footnotes
-
I might have to research about this later. ↩