Vulkan sucks
The worst API I've ever dealt with
Usually my tone is gentle when I write titles. Instead of Vulkan Sucks, usually I would've written titles like Why Vulkan Is Not the Right One for Me or Why Vulkan Falls Behind Other Graphics APIs. But I'm making this post an exception. Vulkan sucks.
A few weeks ago, I found an article on rendering the atmosphere and the universe. Because I have been interested in graphics programming, specifically real-time rendering for games, since high school, I decided to do some graphics projects in the future. As I'm transferring to mathematical physics, I thought it would be nice to visualize physical phenomena such as the bending of light around a black hole, or realistic rendering of the Earth and the universe, using a graphics API.
Since I have already learned the basic concepts of real-time rendering and OpenGL usage through LearnOpenGL, I wanted to go on with a "modern" graphics API for two reasons. First, most OpenGL resources are written with GLSL and binding APIs, and I hate those two. Secondly, even though there are SPIR-V and Direct State Access in OpenGL 4.6, my MacBook doesn't support the latest OpenGL specification, as macOS ceased updating its OpenGL implementation at OpenGL 4.1 and moved to Metal a decade ago.
The first candidate was DirectX 11/12. They have great tooling backed by Microsoft, tons of resources online, and have been battle-proven for more than a decade. But they're Windows-only, and I removed all my Windows installations a few months ago because I hate Windows 11, so I didn't pick DirectX 11/12.
The second candidate was Vulkan. It's cross-platform, a choice of open-source enthusiasts, and supports a niche shader language called Slang. I had such high expectations because it was the successor to OpenGL, but eventually it disappointed me a lot while I was learning it. I wrote a glTF model renderer with multiple backends (OpenGL, Vulkan, Metal coming soon) to compare how these APIs work and choose one for my future projects. In this blog post I will show why I was disappointed by Vulkan.
Before I start criticizing Vulkan, I want to note that the project was heavily written by an LLM, although I had to modify a lot of code (I will discuss this in the bonus section). So if you are an LLM-paranoid person who believes that what I wrote here can't be trusted just because I didn't write the whole code myself (i.e. you can't learn if an LLM wrote some of your code), close this window. Seriously, reading this article will be a waste of time for you. The sole goal of the project was comparing the ergonomics of different graphics APIs, and I used an LLM because not only did I not have much time (I have a bunch of scheduled work right now), but it turned out that Vulkan is painful to write and I would have faced burnout without the LLM's help. When I need to practice a graphics API in the future, either for a job or research, I will rewrite this from scratch.
Tooling issues
I went through so many tooling issues with Vulkan. The Khronos Group is a typical example of a high school or university group project. Everyone wants their project to succeed, but no one wants to put in maximum effort. DirectX and Metal don't have this problem because Microsoft and Apple have full responsibility for managing their APIs.
The first issue is the Vulkan SDK. I encountered a bug in the Slang CMake config shipped by the SDK, where project configuration fails because the Slang CMake config points to the wrong directory. I found a bug report on the issue tracker and the maintainer acknowledged that this is a regression in the latest release. This is good, but the problem is this: the maintainer said the issue will be fixed in the next SDK release. What? There is a misconfigured CMake file that basically makes all projects depending on Slang fail, and the fix will come in the next release, which will arrive in a few months? I was quite surprised that they didn't make a patch release for this regression, so I had to write a hack in my CMakeLists.txt file to work around this issue.
The second issue is the graphics debugger. The de facto debugger for OpenGL and Vulkan is RenderDoc, a piece of software maintained by an individual. I encountered an issue where RenderDoc couldn't capture a frame on Linux, and it turned out that I hadn't built with XWayland (GLFW has a GLFW_PLATFORM_X11 flag for this). Now imagine this: what happens if there is a bug that only occurs on Wayland? How are developers supposed to debug this if they are planning to ship their application as a Wayland application? Finding the root cause would be a nightmare because they cannot use a graphics debugger for Wayland. RenderDoc is used by many graphics programmers, some from big game studios making video games with Vulkan, but surprisingly no one has stepped up to add Wayland support. Remember I said the Khronos Group is a typical group project? This is exactly what I mean: more than a decade has passed since Vulkan was made, but the tooling is still bad because everyone only wants to make the application that can be monetized.
Problems with the API itself
The Vulkan API is too verbose. Sometimes far too much. Things like sType in *CreateInfo structures, memory allocation, device and logical device handling, swapchain, image, and image view management, and so on.
Some of the boilerplate around *CreateInfo structures and object destruction can be reduced by using vulkan.hpp instead of vulkan.h. The RAII version of vulkan.hpp reduces the boilerplate further. Memory allocation can be simplified with VulkanMemoryAllocator, and the startup boilerplate can be reduced with vk-bootstrap; these were what I used for my project.
But the issue is that many of the essential Vulkan libraries aren’t managed directly by the Khronos Group. Both VMA and vk-bootstrap are third-party libraries, but I believe these should be first-party libraries led by the Khronos Group.
I also think this level of verbosity is useless for ordinary users. Yes, there might be some users who need to squeeze maximum performance out of the API, but I think that’s a minority. For ordinary users, things like image transitions (stage mask, access mask, and layout) and memory types (host, GPU, optimal, etc.) are pretty useless. A common excuse I see on the internet from Vulkan proponents is that people can choose OpenGL if they feel Vulkan is too verbose, but don’t say that. We all know OpenGL’s design is archaic, and Vulkan could’ve been a higher-level API similar to Metal.
The Khronos Group was right to judge that many OpenGL drivers were poorly written. Some decisions were good, like moving from GLSL to SPIR-V, because many drivers had different parsing rules. But the idea of letting the graphics programmer do the low-level optimization is bogus. The micro-optimization cases they worried about only apply to a few pieces of software, but by making that mandatory, now all the burden is on the graphics programmer and everyone needs to write the same boilerplate. In most cases this ends up being unnecessary premature optimization that doesn’t bring any visible improvement, and developers waste time and resources. This is critical for indie game studios, where they have limited time and money.
What did the Khronos Group miss?
Vulkan is a common graphics driver interface, not an application programming interface. The designers of Vulkan only focused on reducing the burden of device driver programmers and did not consider application programmers at all. This might be a successful interface for GPU manufacturers, but it’s a total failure for application programmers. There is a reason why Apple was involved in the creation of Vulkan but chose to make their own API in the end. They definitely knew Vulkan was too complicated for the average application programmer, and this was the right move. I thank Apple for creating an alternative, and this is one of the rare occasions where I thank Apple.
People suggest learning graphics programming with OpenGL and then moving to Vulkan, but this is a bad idea. Not only do you need to start with an archaic API that you won’t use in most cases, but the transition from OpenGL to Vulkan is hard because there are too many discrepancies. The pipeline and synchronization concepts should be enough. Device-level optimization should be left to advanced programmers who really need to squeeze out maximum performance (e.g. simulations and AAA video games).
The minimum they should do here is make a simpler version of Vulkan with less boilerplate. They could implement a graphics API library on top of Vulkan, like Zink, and the majority of graphics programmers would spend less time writing boilerplate and more time implementing the actual logic, improving productivity. This is crucial for small indie game studios.
Unfortunately, I don’t think this will happen. The Khronos Group will keep focusing on adding more extensions to Vulkan without considering the true pain point for many programmers. That has been the case over the last decade.
Conclusion
First, to the Vulkan proponents who wonder why more game studios don’t make video games based on Vulkan:
It’s simply because Vulkan sucks. If Vulkan were at least at DirectX’s or Metal’s level, I think the majority of video games would run on Vulkan. Before criticizing the game studios that use DirectX only, ask yourself whether Vulkan is actually superior to, or at least on par with, other modern graphics APIs.
Next, to the Khronos Group:
Stop adding more extensions to the API specification and focus on the actual product. Improve the tools and spend more time testing them (the aforementioned Slang config incident should not happen again). Make an API that does one thing great before moving on. We want a graphics API, not a weird mix of graphics and GPGPU APIs that isn’t good at either.
I’m currently working on the Metal backend of the project and it seems better than Vulkan, so I guess my choice of graphics API for the future will be Metal. I’ll lose the cross-platform advantage for sure, but it’s better than getting headaches from Vulkan’s downsides. Metal has issues too, specifically with the C++ implementation. I will discuss this in a following post.
Bonus: Claude sucks
I noticed this while using Claude Code for this project: Claude (or Claude Code) has become worse in the last couple of weeks. Claude Code seems to find and fetch many resources from the internet but fails to make use of them. One example of this is writing CMakeLists.txt for me. Even when I gave it a link to a reference configuration, and the only thing Claude Code needed to do was copy that and make some small modifications, it spent three minutes thinking and came up with something I didn’t ask for.
It writes many comments in the code, but the actual code is garbage. Even a novice graphics programmer like me can notice it. It seems to optimize the code prematurely, but does not accomplish what I asked for. It even does things like multiplying view and projection matrices on the CPU instead of on the GPU, which is clearly wrong, and I had to manually revamp that part by hand in the end.
At this point Claude Code is degrading my productivity, so I decided not to renew my Claude subscription and to move to ChatGPT and Codex. It probably plagued me more than Vulkan did during this project.
Off-topic: I watched The Odyssey with my friends yesterday and it was pretty good. All six of us gave the movie 10/10 (some 20/10). Definitely a recommended watch. I watched it in normal IMAX, and I think the experience could've been much better if I'd watched the 15/70 version, so if you haven't watched the movie I suggest going for IMAX 70mm.

