The goal of the Vulkan-Hpp is to provide header only C++ bindings for the Vulkan C API to improve the developers Vulkan experience without introducing CPU runtime cost. It adds features like type safety for enums and bitfields, STL container support, exceptions and simple enumerations.
# Getting Started
Vulkan-Hpp is part of the LunarG Vulkan SDK since version 1.0.24. Just include ```<vulkan.hpp>``` and you're ready to use the C++ bindings. If you're using a Vulkan version not yet supported by the Vulkan SDK you can find the latest version of the header [here](https://github.com/KhronosGroup/Vulkan-Hpp/blob/master/vulkan/vulkan.hpp).
# Minimum Requirements
Vulkan-Hpp requires a C++11 capable compiler to compile. The following compilers are known to work:
* ```VkImageTiling``` can be accessed as ```vk::ImageTiling```
* ```VkImageCreateInfo``` can be accessed as ```vk::ImageCreateInfo```
* Enums are mapped to scoped enums to provide compile time type safety. The names have been changed to 'e' + CamelCase with the VK_ prefix and type infix removed. In case the enum type is an extension the extension suffix has been removed from the enum values.
In all other cases the extension suffix has not been removed.
* ```VK_IMAGETYPE_2D``` is now ```vk::ImageType::e2D```.
* ```VK_COLOR_SPACE_SRGB_NONLINEAR_KHR``` is now ```vk::ColorSpaceKHR::eSrgbNonlinear```.
* ```VK_STRUCTURE_TYPE_PRESENT_INFO_KHR``` is now ```vk::StructureType::ePresentInfoKHR```.
* Flag bits are handled like scoped enums with the addition that the _BIT suffix has also been removed.
In some cases it might be necessary to move Vulkan-Hpp to a custom namespace. This can be achieved by defining VULKAN_HPP_NAMESPACE before including Vulkan-Hpp.
Vulkan-Hpp declares a class for all handles to ensure full type safety and to add support for member functions on handles. A member function has been added to a handle class for each
function which accepts the corresponding handle as first parameter. Instead of ```vkBindBufferMemory(device, ...)``` one can write ```device.bindBufferMemory(...)``` or ```vk::bindBufferMemory(device, ...)```.
On 64-bit platforms Vulkan-Hpp supports implicit conversions between C++ Vulkan handles and C Vulkan handles. On 32-bit platforms all non-dispatchable handles are defined as ```uint64_t```,
thus preventing type-conversion checks at compile time which would catch assignments between incompatible handle types..
Due to that Vulkan-Hpp does not enable implicit conversion for 32-bit platforms by default and it is recommended to use a static_cast for the conversion like this: ```VkDevice = static_cast<VkDevice>(cppDevice)```
to prevent converting some arbitrary int to a handle or vice versa by accident. If you're developing your code on a 64-bit platform, but want compile your code for a 32-bit platform without adding the explicit casts
you can define ```VULKAN_HPP_TYPESAFE_CONVERSION``` to 1 in your build system or before including ```vulkan.hpp```. On 64-bit platforms this define is set to 1 by default and can be set to 0 to disable implicit conversions.
As solution Vulkan-Hpp provides a template class ```vk::Flags``` which brings the standard operations like &=, |=, & and | to our scoped enums. Except for the initialization with 0 this class behaves exactly like a normal bitmask
with the improvement that it is impossible to set bits not specified by the corresponding enum by accident. Here are a few examples for the bitmask handling:
When constructing a handle in Vulkan one usually has to create some ```CreateInfo``` struct which describes the new handle. This can result in quite lengthy code as can be seen in the following Vulkan C example:
Vulkan-Hpp provides constructors for all CreateInfo objects which accept one parameter for each member variable. This way the compiler throws a compiler error if a value has been forgotten. In addition to this sType is automatically
filled with the correct value and pNext set to a nullptr by default. Here's how the same code looks with a constructor:
The Vulkan API has several places where which require (count,pointer) as two function arguments and C++ has a few containers which map perfectly to this pair. To simplify development the Vulkan-Hpp bindings have replaced those argument pairs
with the ArrayProxy template class which accepts empty arrays and a single value as well as STL containers std::initializer_list, std::array and std::vector as argument for construction. This way a single generated Vulkan version can accept
a variety of inputs without having the combinatoric explosion which would occur when creating a function for each container type.
Vulkan-Hpp generates references for pointers to structs. This conversion allows passing temporary structs to functions which can result in shorter code. In case the input is optional and thus accepting a null pointer the parameter type will be
a ```vk::Optional<T> const&``` type. This type accepts either a reference to ```T``` or nullptr as input and thus allows optional temporary structs.
Vulkan allows chaining of structures through the pNext pointer. Vulkan-Hpp has a variadic template class which allows constructing of such structure chains with minimal efforts.
In addition to this it checks at compile time if the spec allows the construction of such a pNext chain.
Sometimes the user has to pass a preallocated structure chain to query information. In those cases the corresponding query functions are variadic templates and do accept a structure chain to construct the return value:
```
// Query vk::MemoryRequirements2KHR and vk::MemoryDedicatedRequirementsKHR when calling Device::getBufferMemoryRequirements2KHR:
auto result = device.getBufferMemoryRequirements2KHR<vk::MemoryRequirements2KHR,vk::MemoryDedicatedRequirementsKHR>({});
By default Vulkan-Hpp has exceptions enabled. This means that Vulkan-Hpp checks the return code of each function call which returns a Vk::Result. If Vk::Result is a failure a std::runtime_error will be thrown.
Since there is no need to return the error code anymore the C++ bindings can now return the actual desired return value, i.e. a vulkan handle. In those cases ResultValue <SomeType>::type is defined as the returned type.
If exception handling is disabled by defining ```VULKAN_HPP_NO_EXCEPTIONS``` the type of ```ResultValue<SomeType>::type``` is a struct holding a ```vk::Result``` and a ```SomeType```.
This struct supports unpacking the return values by using ```std::tie```.
In case you don’t want to use the ```vk::ArrayProxy``` and return value transformation you can still call the plain C-style function. Below are three examples showing the 3 ways to use the API:
The second snippet shows how to use the API using return value transformation, but without exceptions. It’s already a little bit shorter than the original code:
For the return value transformation, there's one special class of return values which require special handling: Enumerations. For enumerations you usually have to write code like this:
Vulkan-Hpp provides a ```vk::UniqueHandle<Type,Deleter>``` interface. For each Vulkan handle type ```vk::Type``` there is a unqiue handle ```vk::UniqueType``` which will delete the underlying Vulkan resource upon destruction, e.g.
```vk::UniqueBuffer ``` is the unique handle for ```vk::Buffer```.
For each function which constructs a Vulkan handle of type ```vk::Type``` Vulkan-Hpp provides a second version which returns a ```vk::UnqiueType```. E.g. for ```vk::Device::createBuffer``` there is ```vk::Device::createBufferUnique``` and for ```vk::allocateCommandBuffers```
Note that using ```vk::UniqueHandle``` comes at a cost since most deleters have to store the ```vk::AllocationCallbacks``` and parent handle used for construction because they are required for automatic destruction. The use of ```vk::UniqueHandle``` also requires that exceptions are enabled.
Sometimes it is required to use ```std::vector``` with custom allocators. Vulkan-Hpp supports vectors with custom allocators as input for ```vk::ArrayProx``` and for functions which do return a vector. For the latter case, add your favorite custom allocator as template argument to the function call like this: