The Vulkan-HPP Dilemma

The Vulkan API is C. It’s uncommon to write full applications in only C these days — C++ is far more common. If you are writing C++, it makes sense to use the Vulkan-C++ wrapper which adds type safety, exceptions, and optional automatic RAII style scoped memory management with “Unique” data types. Vulkan is hard enough to use without that syntax sugar sprinkled on top, so if you are using C++ and it is practical, your application should absolutely use the C++ binding types to take advantage of objectively good things like type safety, and having cleanup work properly. (Or not?)

Writing raw Vulkan is a pain. It’s fussy and pedantic, and you have to deal with a wide range of hardware yourself. Therefore, you should try and wrap a bunch of the boilerplate in reusable components so you don’t have to write common functionality like “find a queue” and “make a texture” from scratch every time.

If you are making a library or reusable component with Vulkan that you want to share, not all of your potential users use the C++ wrappers. Some write in C++ but use the Vulkan C API. Others use Vulkan bindings for the C API from other languages like Rust or Go. So your library shouldn’t expose Vulkan-CPP types. As an example, the public interface of the Vulkan Memory Allocator library depends on the raw C vkDevice and vkPhysicalDevice handles, rather than the more type-safe vk::Device and vk::PhysicalDevice types. You can have those classes in your application, but you have to write a bit of extra adapter code to use the C handles when using a library that is probably useful to almost every Vulkan developer who doesn’t enjoy implementing their own GPU malloc from scratch.

The type safety of the C++ API means that it won’t implicitly promote the C types to C++ types. So if libraries are all supposed to expose the primitive C API types, your application should depend on the C API types rather than the C++ binding types. And there’s the dilemma. An application both should and shouldn’t use the C++ bindings. This is one of the frustrations of the flexibility of the Vulkan ecosystem. Tons of brilliant engineering that went into a bunch of individually rational choices, which resulted in an irrational ecosystem.

This isn’t unique to Vulkan in any way, but I still wanted to vent about it. Vulkan just serves as an object lesson a deeper philosophical point that is hard to put clearly into words. You can draw seemingly contradictory conclusions from what seem like rational deductions in many parts of the modern software development stack. Contradictory conclusions are supposed to be impossible with correct logic, unless the basic axioms and premises used as a starting point are incorrect. I think the resulting conclusion here is that the whole of software engineering is provably built upon false premises. But I don’t know that it matters, because people will never exactly agree about what the falsehood is. And even if they did, we still have to deal with it. If somebody tried to invent a brand new completely isolated computing ecosystem from more objectively correct first principles, nobody would use it because it doesn’t have widespread support.

Have I got a point in this rant? I’ll try to sum it up:

Computer programs are applied formal logic. It’s a shame that computer programming is fundamentally so illogical.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s