Learning Vulkan

Sawan SunarSawan Sunar
5 min read

TLDR: This is my experience learning Vulkan and trying to create a single triangle with it. This article is quite basic and doesn't include all the technical details. I plan to write a more detailed and precise piece once I have a deeper understanding of how everything works and how Vulkan manages different tasks.

Vulkan is a low-level graphics API designed to be a more flexible and powerful replacement for OpenGL. It was developed by the Khronos Group.

The main advantage of OpenGL and its successor, Vulkan, is that they are cross-platform graphics APIs, making them widely used in the low-level graphics field.

I've been fairly good at working on projects with OpenGL, but it's becoming outdated. Modern games are moving away from OpenGL because Vulkan offers more control over your graphics card's features. This control can lead to better performance if used correctly.

I wanted to learn Vulkan because it's a big challenge, but a rewarding one. I hoped to deepen my basic understanding of the graphics API by the end. While you can still use OpenGL on any system, Vulkan is the best choice for top performance. However, you might not need Vulkan at all, as OpenGL could be enough. I just wanted to take on Vulkan myself.

Learning Vulkan is a whole different challenge. If DirectX 11 and OpenGL are rated around 5 or 6 in terms of difficulty, then DirectX 12 would be an 8, while Vulkan would be a 9 or 10. It requires precise attention and a thorough understanding of the entire pipeline. I can easily write a basic rendering system with OpenGL from memory without help, but Vulkan is so vast and complex that it requires more in-depth study. However, I must say that the API is quite consistent. The criticism of OpenGL was that it was straightforward, so you couldn't really enhance certain aspects of your program, even with additional context, because the API itself is quite basic. To get more features, you would need to add extensions, which might not work for everyone. In Vulkan, you need to set up everything from the beginning. Drawing a triangle, which takes just a few lines of code in OpenGL, involves writing at least 2000 lines of code in Vulkan, including handling concurrency with semaphores and fences.

The beginner tutorial on the Khronos site was helpful in clarifying all the essential knowledge needed to understand what I was writing and why. It helped me grasp Vulkan's design choices better and provided detailed information about the pipeline.

More details about the structure itself: The code includes a function to initialize everything related to Vulkan and a cleanup function. These cover all the systems you need to set up one by one to have a working rendering system. Then, there's the main loop, followed by cleanup when you're finished with your program. It's very similar to the constructor and destructor concept in OOP.

A common pattern in initializing various systems is what I call the Info Pattern. This isn't an official name; it's just something I came up with because the word "info" is used frequently. You start by creating an info variable. There are several info classes (which are like configurations) that you fill with the settings you want (for example, the instance system has options like application name and version). Then, you perform a quick error check to ensure everything works, and finally, you create the actual object using the info, marking the completion of the system's creation. The code is very modular, making it easier to understand. Systems like the Vulkan instance, swapchain, and framebuffer are organized into clear procedures, which you can reference through persistent variables without much trouble. Although it's quite tedious because you're essentially doing the same thing for all the systems with slight variations, those differences require precision. The program won't work unless every system is correctly set up before you start drawing the triangle.

Also, one difference in Vulkan is that you can't use text files or string shaders directly. You still use GLSL as the shader language, but you need to compile it into an intermediate binary format called SPIR-V (Standard Portable Intermediate Representation) before running it in your program. This differs from OpenGL, which lets you provide GLSL strings at runtime and compile them on the fly.

One important thing that confused me was rendering the triangle itself. After spending a long day trying to make it work, I finally got the renderer to draw the triangle, but I couldn't really see the actual coordinates. Coming from an OpenGL background, I assumed there was only one way to do it, so I wasn't understanding what was actually happening. After some more investigation, I realized that the triangle data was stored inside the shaders themselves. This isn't unique to Vulkan; you can do it in OpenGL too. However, it made it hard to understand how the actual draw call function was working. I'm mentioning this because relying on a certain pattern in OpenGL limited my perspective to just one approach.

This is why I learn different technologies in a field. By exploring various ways to solve a problem, I understand when to use each one. It also deepens my understanding of the problem and helps me make better design decisions.

I think Vulkan is quite interesting as I learn it. I might not enjoy it as much if I start doing more with it in the future, but for now, it's pretty good.

0
Subscribe to my newsletter

Read articles from Sawan Sunar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sawan Sunar
Sawan Sunar