Open-Source Vulkan C++ API

Related tags

Graphics Vulkan-Hpp
Overview

Vulkan-Hpp: C++ Bindings for Vulkan

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.

Platform Build Status
Linux Build Status

Getting Started

Vulkan-Hpp is part of the LunarG Vulkan SDK since version 1.0.24. Just #include <vulkan/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.

Minimum Requirements

Vulkan-Hpp requires a C++11 capable compiler to compile. The following compilers are known to work:

  • Visual Studio >=2015
  • GCC >= 4.8.2 (earlier version might work, but are untested)
  • Clang >= 3.3

Building Vulkan-Hpp, Samples, and Tests

To build the local samples and tests you'll have to clone this repository and run CMake to generate the required build files

  1. Install dependencies.
    • Ensure that you have CMake and git installed and accessible from a shell.
    • Ensure that you have installed the Vulkan SDK.
    • Optionally install clang-format >= 11.0 to get a nicely formatted Vulkan-Hpp header.
  2. Open a shell which provides git and clone the repository with: git clone --recurse-submodules https://github.com/KhronosGroup/Vulkan-Hpp.git
  3. Change the current directory to the newly created Vulkan-Hpp directory.
  4. Create a build environment with CMake cmake -D DSAMPLES_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DSAMPLES_BUILD=ON -DTESTS_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DTESTS_BUILD=ON -B build You might have to specify a generator via -G, for a full list of generators execute cmake -G.
    • To rebuild vulkan.hpp from the vk.xml XML registry file, add the -DVULKAN_HPP_RUN_GENERATOR=ON option to the CMake command line.
  5. Either open the generated project with an IDE, e.g. Visual Studio or launch the build process with cmake --build ..

Optional: To update the Vulkan-Hpp and its submodules execute git pull --recurse-submodules.

Optional Features

Formatting

If the program clang-format is found by CMake, the define CLANG_FORMAT_EXECUTABLE is set accordingly. In that case, the generated vulkan.hpp is formatted using the .clang-format file located in the root directory of this project. Otherwise it's formatted as hard-coded in the generator.

Usage

namespace vk

To avoid name collisions with the Vulkan C API the C++ bindings reside in the vk namespace. The following rules apply to the new naming

  • All functions, enums, handles, and structs have the Vk prefix removed. In addition to this the first letter of functions is lower case.
    • vkCreateInstance can be accessed as vk::createInstance
    • 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.

Handles

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, ...).

namespace vk::raii

There is an additional header named vulkan_raii.hpp generated. That header holds raii-compliant wrapper classes for the handle types. That is, for e.g. the handle type VkInstance, there's a raii-compliant wrapper vk::raii::Instance. Please have a look at the samples using those classes in the directory RAII_Samples.

C/C++ Interop for Handles

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.

Flags

The scoped enum feature adds type safety to the flags, but also prevents using the flag bits as input for bitwise operations like & and |.

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:

vk::ImageUsageFlags iu1; // initialize a bitmask with no bit set
vk::ImageUsageFlags iu2 = {}; // initialize a bitmask with no bit set
vk::ImageUsageFlags iu3 = vk::ImageUsageFlagBits::eColorAttachment; // initialize with a single value
vk::ImageUsageFlags iu4 = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage; // or two bits to get a bitmask
PipelineShaderStageCreateInfo ci( {} /* pass a flag without any bits set */, ...);

CreateInfo structs

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:

VkImageCreateInfo ci;
ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
ci.pNext = nullptr;
ci.flags = ...some flags...;
ci.imageType = VK_IMAGE_TYPE_2D;
ci.format = VK_FORMAT_R8G8B8A8_UNORM;
ci.extent = VkExtent3D { width, height, 1 };
ci.mipLevels = 1;
ci.arrayLayers = 1;
ci.samples = VK_SAMPLE_COUNT_1_BIT;
ci.tiling = VK_IMAGE_TILING_OPTIMAL;
ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
ci.queueFamilyIndexCount = 0;
ci.pQueueFamilyIndices = 0;
ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkCreateImage(device, &ci, allocator, &image));

There are two typical issues Vulkan developers encounter when filling out a CreateInfo struct field by field

  • One or more fields are left uninitialized.
  • sType is incorrect.

Especially the first one is hard to detect.

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:

vk::ImageCreateInfo ci({}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
                       { width, height, 1 },
                       1, 1, vk::SampleCountFlagBits::e1,
                       vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eColorAttachment,
                       vk::SharingMode::eExclusive, 0, nullptr, vk::ImageLayout::eUndefined);
vk::Image image = device.createImage(ci);

With constructors for CreateInfo structures one can also pass temporaries to Vulkan functions like this:

vk::Image image = device.createImage({{}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
                                     { width, height, 1 },
                                     1, 1, vk::SampleCountFlagBits::e1,
                                     vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eColorAttachment,
                                     vk::SharingMode::eExclusive, 0, nullptr, vk::ImageLayout::eUndefined});

Designated Initializers

Beginning with C++20, C++ supports designated initializers. As that feature requires to not have any user-declared or inherited constructors, you have to #define VULKAN_HPP_NO_CONSTRUCTORS, which removes all the structure and union constructors from vulkan.hpp. Instead you can then use aggregate initialization. The first few vk-lines in your source might then look like

// initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo{ .pApplicationName   = AppName,
                                     .applicationVersion = 1,
                                     .pEngineName        = EngineName,
                                     .engineVersion      = 1,
                                     .apiVersion         = VK_API_VERSION_1_1 };
        
// initialize the vk::InstanceCreateInfo
vk::InstanceCreateInfo instanceCreateInfo{ .pApplicationInfo = & applicationInfo };

instead of

// initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
        
// initialize the vk::InstanceCreateInfo
vk::InstanceCreateInfo instanceCreateInfo( {}, &applicationInfo );

Note, that the designator order needs to match the declaration order. Note as well, that now you can explicitly set the sType member of vk-structures. This is neither neccessary (as they are correctly initialized by default) nor recommended.

Passing Arrays to Functions using ArrayProxy

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.

Here are some code samples on how to use the ArrayProxy:

vk::CommandBuffer c;

// pass an empty array
c.setScissor(0, nullptr);

// pass a single value. Value is passed as reference
vk::Rect2D scissorRect = { {0, 0}, {640, 480} };
c.setScissor(0, scissorRect);

// pass a temporary value.
c.setScissor(0, { { 0, 0 },{ 640, 480 } });

// generate a std::initializer_list using two rectangles from the stack. This might generate a copy of the rectangles.
vk::Rect2D scissorRect1 = { { 0, 0 },{ 320, 240 } };
vk::Rect2D scissorRect2 = { { 320, 240 },{ 320, 240 } };
c.setScissor(0, { scissorRect, scissorRect2 });

// construct a std::initializer_list using two temporary rectangles.
c.setScissor(0, { { {   0,   0 },{ 320, 240 } },
                { { 320, 240 },{ 320, 240 } }
}
);

// pass a std::array
std::array<vk::Rect2D, 2> arr{ scissorRect1, scissorRect2 };
c.setScissor(0, arr);

// pass a std::vector of dynamic size
std::vector<vk::Rect2D> vec;
vec.push_back(scissorRect1);
vec.push_back(scissorRect2);
c.setScissor(0, vec);

Passing Structs to Functions

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.

// C
VkImageSubresource subResource;
subResource.aspectMask = 0;
subResource.mipLevel = 0;
subResource.arrayLayer = 0;
VkSubresourceLayout layout;
vkGetImageSubresourceLayout(device, image, &subresource, &layout);

// C++
auto layout = device.getImageSubresourceLayout(image, { {} /* flags*/, 0 /* miplevel */, 0 /* arrayLayer */ });

Structure Pointer Chains

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.

// This will compile successfully.
vk::StructureChain<vk::MemoryAllocateInfo, vk::ImportMemoryFdInfoKHR> c;
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();

// This will fail compilation since it's not valid according to the spec.
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedRequirementsKHR> c;
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();

Vulkan-Hpp provides a constructor for these chains similar to the CreateInfo objects which accepts a list of all structures part of the chain. The pNext field is automatically set to the correct value:

vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> c = {
  vk::MemoryAllocateInfo(size, type),
  vk::MemoryDedicatedAllocateInfo(image)
};

If one of the structures of a StructureChain is to be removed, maybe due to some optional settings, you can use the function vk::StructureChain::unlink<ClassType>(). It modifies the StructureChain such that the specified structure isn't part of the pNext-chain any more. Note, that the actual memory layout of the StructureChain is not modified by that function. In case that very same structure has to be re-added to the StructureChain again, use vk::StructureChain::relink<ClassType>().

Sometimes the user has to pass a preallocated structure chain to query information. For those cases there are two corresponding getter functions. One with a variadic template generating a structure chain of at least two elements to construct the return value:

// Query vk::MemoryRequirements2HR and vk::MemoryDedicatedRequirementsKHR when calling Device::getBufferMemoryRequirements2KHR:
auto result = device.getBufferMemoryRequirements2KHR<vk::MemoryRequirements2KHR, vk::MemoryDedicatedRequirementsKHR>({});
vk::MemoryRequirements2KHR &memReqs = result.get<vk::MemoryRequirements2KHR>();
vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedRequirementsKHR>();

To get just the base structure, without chaining, the other getter function provided does not need a template argument for the structure to get:

// Query just vk::MemoryRequirements2KHR
vk::MemoryRequirements2KHR memoryRequirements = device.getBufferMemoryRequirements2KHR({});

Return values, Error Codes & Exceptions

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 ::type is defined as the returned type.

To create a device you can now just write:

vk::Device device = physicalDevice.createDevice(createInfo);

Some functions allow more than just vk::Result::eSuccess to be considered as a success code. For those functions, we always return a ResultValue<SomeType>. An example is acquireNextImage2KHR, that can be used like this:

vk::ResultValue<uint32_t> result = device->acquireNextImage2KHR(acquireNextImageInfo);
switch (result.result)
{
	case vk::Result::eSuccess:
		currentBuffer = result.value;
		break;
	case vk::Result::eTimeout:
	case vk::Result::eNotReady:
	case vk::Result::eSuboptimalKHR:
		// do something meaningful
		break;
	default:
		// should not happen, as other return codes are considered to be an error and throw an exception
		break;
}

As time passes, some vulkan functions might change, such that they start to support more result codes than vk::Result::eSuccess as a success code. That logical change would not be visible in the C-API, but in the C++-API, as such a function would now return a vk::ResultValue<SomeType> instead of just SomeType. In such (rare) cases, you would have to adjust your cpp-sources to reflect that API change.

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 first snippet shows how to use the API without exceptions and the return value transformation:

// No exceptions, no return value transformation
ShaderModuleCreateInfo createInfo(...);
ShaderModule shader1;
Result result = device.createShaderModule(&createInfo, allocator, &shader1);
if (result.result != VK_SUCCESS)
{
    handle error code;
    cleanup?
    return?
}

ShaderModule shader2;
Result result = device.createShaderModule(&createInfo, allocator, &shader2);
if (result != VK_SUCCESS)
{
    handle error code;
    cleanup?
    return?
}

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:

ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */);
if (shaderResult1.result != VK_SUCCESS)
{
  handle error code;
  cleanup?
  return?
}

// std::tie support.
vk::Result result;
vk::ShaderModule shaderModule2;
std::tie(result, shaderModule2)  = device.createShaderModule({...} /* createInfo temporary */);
if (shaderResult2.result != VK_SUCCESS)
{
  handle error code;
  cleanup?
  return?
}

A nicer way to unpack the result is provided by the structured bindings of C++17. They will allow us to get the result with a single line of code:

auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo temporary */);

Finally, the last code example is using exceptions and return value transformation. This is the default mode of the API.

 ShaderModule shader1;
 ShaderModule shader2;
 try {
   shader1 = device.createShaderModule({...});
   shader2 = device.createShaderModule({...});
 } catch(std::exception const &e) {
   // handle error and free resources
 }

Keep in mind that Vulkan-Hpp does not support RAII style handles and that you have to cleanup your resources in the error handler!

C++17: [[nodiscard]]

With C++17 and above, some functions are attributed with [[nodiscard]], resulting in a warning if you don't use the return value in any way. You can switch those warnings off by defining VULKAN_HPP_NO_NODISCARD_WARNINGS.

Enumerations

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:

std::vector<LayerProperties,Allocator> properties;
uint32_t propertyCount;
Result result;
do
{
  // determine number of elements to query
  result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, nullptr ) );
  if ( ( result == Result::eSuccess ) && propertyCount )
  {
    // allocate memory & query again
    properties.resize( propertyCount );
    result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, reinterpret_cast
     <VkLayerProperties*>( properties.data() ) ) );
  }
} while ( result == Result::eIncomplete );
// it's possible that the count has changed, start again if properties was not big enough
properties.resize(propertyCount);

Since writing this loop over and over again is tedious and error prone the C++ binding takes care of the enumeration so that you can just write:

std::vector<LayerProperties> properties = physicalDevice.enumerateDeviceLayerProperties();

UniqueHandle for automatic resource management

Vulkan-Hpp provides a vk::UniqueHandle<Type, Deleter> interface. For each Vulkan handle type vk::Type there is a unique 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::UniqueType. E.g. for vk::Device::createBuffer there is vk::Device::createBufferUnique and for vk::allocateCommandBuffers there is vk::allocateCommandBuffersUnique.

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.

Custom allocators

Sometimes it is required to use std::vector with custom allocators. Vulkan-Hpp supports vectors with custom allocators as input for vk::ArrayProxy 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:

std::vector<LayerProperties, MyCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties<MyCustomAllocator>();

You can as well use a stateful custom allocator by providing it as an argument to those functions. Unfortunately, to make the compilers happy, you also need to explicitly set the Dispatch argument. To get the default there, a simple ´´´{}´´´ would suffice:

MyStatefulCustomAllocator allocator;
std::vector<LayerProperties, MyStatefulCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties( allocator, {} );

Custom assertions

All over vulkan.hpp, there are a couple of calls to an assert function. By defining VULKAN_HPP_ASSERT, you can specifiy your own custom assert function to be called instead.

By default, VULKAN_HPP_ASSERT_ON_RESULT will be used for checking results when VULKAN_HPP_NO_EXCEPTIONS is defined. If you want to handle errors by yourself, you can disable/customize it just like VULKAN_HPP_ASSERT.

There are a couple of static assertions for each handle class and each struct. By defining VULKAN_HPP_STATIC_ASSERT, you can specify your own custom static assertion to be used for those cases. That is, by defining it to be a NOP, you can reduce your compilation time a little.

Extensions / Per Device function pointers

The Vulkan loader exposes only the Vulkan core functions and a limited number of extensions. To use Vulkan-Hpp with extensions it's required to have either a library which provides stubs to all used Vulkan functions or to tell Vulkan-Hpp to dispatch those functions pointers. Vulkan-Hpp provides a per-function dispatch mechanism by accepting a dispatch class as last parameter in each function call. The dispatch class must provide a callable type for each used Vulkan function. Vulkan-Hpp provides one implementation, DispatchLoaderDynamic, which fetches all function pointers known to the library.

// Providing a function pointer resolving vkGetInstanceProcAddr, just the few functions not depending an an instance or a device are fetched
vk::DispatchLoaderDynamic dld( getInstanceProcAddr );

// Providing an already created VkInstance and a function pointer resolving vkGetInstanceProcAddr, all functions are fetched
vk::DispatchLoaderDynamic dldi( instance, getInstanceProcAddr );

// Providing also an already created VkDevice and optionally a function pointer resolving vkGetDeviceProcAddr, all functions are fetched as well, but now device-specific functions are fetched via vkDeviceGetProcAddr.
vk::DispatchLoaderDynamic dldid( instance, getInstanceProcAddr, device );

// Pass dispatch class to function call as last parameter
device.getQueue(graphics_queue_family_index, 0, &graphics_queue, dldid);

To use the DispatchLoaderDynamic as the default dispatcher (means: you don't need to explicitly add it to every function call), you need to #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1, and have the macro VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE exactly once in your source code to provide storage for that default dispatcher. Then you can use it by the macro VULKAN_HPP_DEFAULT_DISPATCHER, as is shown in the code snippets below. To ease creating such a DispatchLoaderDynamic, there is a little helper class DynamicLoader. Creating a full featured DispatchLoaderDynamic is a two- to three-step process:

  1. initialize it with a function pointer of type PFN_vkGetInstanceProcAddr, to get the instance independent function pointers:
    vk::DynamicLoader dl;
    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
    VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
  1. initialize it with a vk::Instance to get all the other function pointers:
    vk::Instance instance = vk::createInstance({}, nullptr);
    VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
  1. optionally initialize it with a vk::Device to get device-specific function pointers
    std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
    assert(!physicalDevices.empty());
    vk::Device device = physicalDevices[0].createDevice({}, nullptr);
    VULKAN_HPP_DEFAULT_DISPATCHER.init(device);

After the second step above, the dispatcher is fully functional. Adding the third step can potentially result in more efficient code.

In some cases the storage for the DispatchLoaderDynamic should be embedded in a DLL. For those cases you need to define VULKAN_HPP_STORAGE_SHARED to tell Vulkan-Hpp that the storage resides in a DLL. When compiling the DLL with the storage it is also required to define VULKAN_HPP_STORAGE_SHARED_EXPORT to export the required symbols.

For all functions, that VULKAN_HPP_DEFAULT_DISPATCHER is the default for the last argument to that function. In case you want to explicitly provide the dispatcher for each and every function call (when you have multiple dispatchers for different devices, for example) and you want to make sure, that you don't accidentally miss any function call, you can define VULKAN_HPP_NO_DEFAULT_DISPATCHER before you include vulkan.hpp to remove that default argument.

Type traits

vulkan.hpp provides a couple of type traits, easing template programming:

  • template <typename EnumType, EnumType value> struct CppType Maps IndexType values (IndexType::eUint16, IndexType::eUint32, ...) to the corresponding type (uint16_t, uint32_t, ...) by the member type Type; Maps ObjectType values (ObjectType::eInstance, ObjectType::eDevice, ...) to the corresponding type (vk::Instance, vk::Device, ...) by the member type Type; Maps DebugReportObjectType values (DebugReportObjectTypeEXT::eInstance, DebugReportObjectTypeEXT::eDevice, ...) to the corresponding type (vk::Instance, vk::Device, ...) by the member type Type;
  • template <typename T> struct IndexTypeValue Maps scalar types (uint16_t, uint32_t, ...) to the corresponding IndexType value (IndexType::eUint16, IndexType::eUint32, ...).
  • template <typename T> struct isVulkanHandleType Maps a type to true if and only if it's a handle class (vk::Instance, vk::Device, ...) by the static member value.
  • HandleClass::CType Maps a handle class (vk::Instance, vk::Device, ...) to the corresponding C-type (VkInstance, VkDevice, ...) by the member type CType.
  • HandleClass::objectType Maps a handle class (vk::Instance, vk::Device, ...) to the corresponding ObjectType value (ObjectType::eInstance, ObjectType::eDevice, ...) by the static member objectType.
  • HandleClass::debugReportObjectType Maps a handle class (vk::Instance, vk::Device, ...) to the corresponding DebugReportObjectTypeEXT value (DebugReportObjectTypeEXT::eInstance, DebugReportObjectTypeEXT::eDevice, ...) by the static member debugReportObjectType.

vk::Format trait functions

vulkan.hpp provides a couple of trait functions on vk::Format. With C++14 and above, all those functions are marked as constexpr, that is with appropriate arguments, they are resolved by the compiler.

  • uin8_t blockSize( vk::Format format ); Gets the texel block size of this format in bytes.
  • uint8_t texelsPerBlock( vk::Format format ); Gets the number of texels in a texel block.
  • std::array<uint8_t, 3> blockExtent( vk::Format format ); Gets the three-dimensional extent of texel blocks.
  • char const * compressionScheme( vk::Format format ); Gets a textual description of the compression scheme of this format, or an empty text if it is not compressed.
  • bool isCompressed( vk::Format format ); True, if format is a compressed format, otherwise false.
  • uint8_t packed( vk::Format format ); Gets the number of bits into which the format is packed. A single image element in this format can be stored in the same space as a scalar type of this bit width.
  • uint8_t componentCount( vk::Format format ); Gets the number of components of this format.
  • bool componentsAreCompressed( vk::Format format ); True, if the components of this format are compressed, otherwise False.
  • uint8_t componentBits( vk::Format format, uint8_t component ); Gets the number of bits in this component, if not compressed, otherwise 0.
  • uint8_t componentPlaneIndex( vk::Format format, uint8_t component ); Gets the plane index, this component lies in.
  • uint8_t planeCount( vk::Format format ); Gets the number of image planes of this format.
  • vk::Format planeCompatibleFormat( vk::Format format, uint8_t plane ); Gets a single-plane format compatible with this plane.
  • uint8_t planeHeightDivisor( vk::Format format, uint8_t plane ); Gets the relative height of this plane. A value of k means that this plane is 1/k the height of the overall format.
  • Cuint8_t planeWidthDivisor( vk::Format format, uint8_t plane );` Gets the relative width of this plane. A value of k means that this plane is 1/k the width of the overall format.

Hashing Vulkan types

With the additional header vulkan_hash.hpp, you get specializations of std::hash for the handle wrapper classes and, with C++14, for the structure wrappers. With VULKAN_HPP_HASH_COMBINE, you can define your own hash combining algorithm for the structure elements.

Samples and Tests

When you configure your project using CMake, you can enable SAMPLES_BUILD to add some sample projects to your solution. Most of them are ports from the LunarG samples, but there are some more, like CreateDebugUtilsMessenger, InstanceVersion, PhysicalDeviceDisplayProperties, PhysicalDeviceExtensions, PhysicalDeviceFeatures, PhysicalDeviceGroups, PhysicalDeviceMemoryProperties, PhysicalDeviceProperties, PhysicalDeviceQueueFamilyProperties, and RayTracing. All those samples should just compile and run. When you configure your project using CMake, you can enable TESTS_BUILD to add some test projects to your solution. Those tests are just compilation tests and are not required to run.

Configuration Options

There are a couple of defines you can use to control the feature set and behaviour of vulkan.hpp:

VULKAN_HPP_ASSERT

At various places in vulkan.hpp an assertion statement is used. By default, the standard assert funtions from <cassert> is called. By defining VULKAN_HPP_ASSERT before including vulkan.hpp, you can change that to any function with the very same interface.

VULKAN_HPP_ASSERT_ON_RESULT

If there are no exceptions enabled (see VULKAN_HPP_NO_EXCEPTIONS), an assertion statement checks for a valid success code returned from every vulkan call. By default, this is the very same assert function as defined by VULKAN_HPP_ASSERT, but by defining VULKAN_HPP_ASSERT_ON_RESULT you can replace just those assertions with your own function, using the very same interface.

VULKAN_HPP_DEFAULT_DISPATCHER

Every vk-function gets a Dispatcher as its very last argument, which defaults to VULKAN_HPP_DEFAULT_DISPATCHER. If VULKAN_HPP_DISPATCH_LOADER_DYNAMIC is defined to be 1, it is defaultDispatchLoaderDynamic. This in turn is the dispatcher instance, which is defined by VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE, which has to be used exactly once in your sources. If, on the other hand, VULKAN_HPP_DISPATCH_LOADER_DYNAMIC is defined to something different from 1, VULKAN_HPP_DEFAULT_DISPATCHER is set to be DispatchLoaderStatic(). You can use your own default dispatcher by setting VULKAN_HPP_DEFAULT_DISPATCHER to an object that provides the same API. If you explicitly set VULKAN_HPP_DEFAULT_DISPATCHER, you need to set VULKAN_HPP_DEFAULT_DISPATCHER_TYPE accordingly as well.

VULKAN_HPP_DEFAULT_DISPATCHER_TYPE

This names the default dispatcher type, as specified by VULKAN_HPP_DEFAULT_DISPATCHER. Per default, it is DispatchLoaderDynamic or DispatchLoaderStatic, depending on VULKAN_HPP_DISPATCH_LOADER_DYNAMIC being 1 or not 1, respectively. If you explicitly set VULKAN_HPP_DEFAULT_DISPATCHER, you need to set VULKAN_HPP_DEFAULT_DISPATCHER_TYPE accordingly as well.

VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE

If you have not defined your own VULKAN_HPP_DEFAULT_DISPATCHER, and have VULKAN_HPP_DISPATCH_LOADER_DYNAMIC defined to be 1 (the default), you need to have the macro VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE exactly once in any of your source files to provide storage for that default dispatcher. VULKAN_HPP_STORAGE_API then controls the import/export status of that default dispatcher.

VULKAN_HPP_DISABLE_ENHANCED_MODE

When this is defined before including vulkan.hpp, you essentially disable all enhanced functionality. All you then get is

  • improved compile time error detection, via scoped enums;
  • usage of the helper class vk::Flags for bitmasks;
  • wrapper structs for all vulkan structs providing default initialization;
  • the helper class vk::StructureChain for compile-time construction of structure chains.

If this is not defined, you additionally get

  • enhanced versions of the commands (consuming vk::ArrayProxy<>, simplifying handling of array data; returning requested data; throwing exceptions on errors (as long as VULKAN_HPP_NO_EXCEPTIONS is not defined);
  • enhanced structure constructors (as long as VULKAN_HPP_NO_STRUCT_CONSTRUCTORS is not defined) (consuming vk::ArrayProxyNoTemporaries<>);
  • enhanced setter functions on some members of structs (consuming vk::ArrayProxyNoTemporaries<>);
  • the helper classes vk::ArrayProxy<> and vk::ArrayProxyNoTemporaries<>
  • all the RAII-stuff in vulkan_raii.hpp

VULKAN_HPP_DISPATCH_LOADER_DYNAMIC

This either selects the dynamic (when it's 1) or the static (when it's not 1) DispatchLoader as the default one, as long as it's not explicitly specified by VULKAN_HPP_DEFAULT_DISPATCHER. By default, this is defined to be 1 if VK_NO_PROTOTYPES is defined, otherwise 0.

VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL

By default, a little helper class DynamicLoader is used to dynamically load the vulkan library. If you set it to something different than 1 before including vulkan.hpp, this helper is not available, and you need to explicitly provide your own loader type for the function DispatchLoaderDynamic::init().

VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC

By default, the member m_mask of the Flags template class is private. This is to prevent accidentally setting a Flags with some inappropriate value. But it also prevents using a Flags, or a structure holding a Flags, to be used as a non-type template parameter. If you really need that functionality, and accept the reduced security, you can use this define to change the access specifier for m_mask from private to public, which allows using a Flags as a non-type template parameter.

VULKAN_HPP_HASH_COMBINE

This define can be used to specify your own hash combiner function. In order to determine the hash of a vk-structure, the hashes of the members of that struct are to be combined. This is done by this define, which by default is identical to what the function boost::hash_combine() does. It gets the type of the to-be-combined value, the seed, which is the combined value up to that point, and finally the to-be-combined value. This hash calculation determines a "shallow" hash, as it takes the hashes of any pointer in a structure, and not the hash of a pointed-to value.

VULKAN_HPP_INLINE

This is set to be the compiler-dependent attribute used to mark functions as inline. If your compiler happens to need some different attribute, you can set this define accordingly before including vulkan.hpp.

VULKAN_HPP_NAMESPACE

By default, the namespace used with vulkan.hpp is vk. By defining VULKAN_HPP_NAMESPACE before including vulkan.hpp, you can adjust this.

VULKAN_HPP_NO_CONSTRUCTORS

With C++20, designated initializers are available. Their use requires the absence of any user-defined constructors. Define VULKAN_HPP_NO_CONSTRUCTORS to remove constructors from structs and unions.

VULKAN_HPP_NO_EXCEPTIONS

When a vulkan function returns an error code that is not specified to be a success code, an exception is thrown unless VULKAN_HPP_NO_EXCEPTIONS is defined before including vulkan.hpp.

VULKAN_HPP_NO_NODISCARD_WARNINGS

With C++17, all vk-functions returning something are declared with the attribute [[nodiscard]]. This can be removed by defining VULKAN_HPP_NO_NODISCARD_WARNINGS before including vulkan.hpp.

VULKAN_HPP_NO_SETTERS

By defining VULKAN_HPP_NO_SETTERSbefore including vulkan.hpp, setter member functions will not be available within structs and unions. Modifying their data members will then only be possible via direct assignment.

VULKAN_HPP_NO_SMART_HANDLE

By defining VULKAN_HPP_NO_SMART_HANDLE before including vulkan.hpp, the helper class UniqueHandle and all the unique handle types are not available.

VULKAN_HPP_NO_SPACESHIP_OPERATOR

With C++20, the so-called spaceship-operator <=> is introduced. If that operator is supported, all the structs and classes in vulkan.hpp use the default implementation of it. As currently some implementations of this operator are very slow, and others seem to be incomplete, by defining VULKAN_HPP_NO_SPACESHIP_OPERATOR before including vulkan.hpp you can remove that operator from those structs and classes.

VULKAN_HPP_STORAGE_API

With this define you can specify whether the DispatchLoaderDynamic is imported or exported (see VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE). If VULKAN_HPP_STORAGE_API is not defined externally, and VULKAN_HPP_STORAGE_SHARED is defined, depending on the VULKAN_HPP_STORAGE_SHARED_EXPORT being defined, VULKAN_HPP_STORAGE_API is either set to __declspec( dllexport ) (for MSVC) / __attribute__( ( visibility( "default" ) ) ) (for gcc or clang) or __declspec( dllimport ) (for MSVC), respectively. For other compilers, you might specify the corresponding storage by defining VULKAN_HPP_STORAGE_API on your own.

VULKAN_HPP_TYPESAFE_CONVERSION

32-bit vulkan is not typesafe for handles, so we don't allow copy constructors on this platform by default. To enable this feature on 32-bit platforms define VULKAN_HPP_TYPESAFE_CONVERSION.

Deprecated elements

There are a couple of elements in vulkan.hpp that are marked as deprecated (with C++14 and above):

The implicit cast operators on vk::ResultValue are potentially wrong under certain circumstances. You should access the value explicitly as the member of the vk::ResultValue instead

The type traits cpp_type<ObjectType::eObjectTypeID> are replaced by the more general type traits CppType<Type, Type::eTypeID>.

Some functions (listed below) provide an interface that does not fit to the general approach in vulkan.hpp, where values you get from a function are supposed to be returned. Use the corresponding functions with the same name, that actually return those values, instead. The affected functions are

	Device::getAccelerationStructureHandleNV
	Device::getCalibratedTimestampsEXT
	Device::getQueryPoolResults
	Device::getRayTracingCaptureReplayShaderGroupHandlesKHR
	Device::getRayTracingShaderGroupHandlesKHR
	Device::getRayTracingShaderGroupHandlesNV
	Device::writeAccelerationStructuresPropertiesKHR

All those elements will be removed around November 2021.

See Also

Feel free to submit a PR to add to this list.

License

Copyright 2015-2020 The Khronos Group Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • Add UniqueHandle non-const accessors, ensure all by reference.

    Add UniqueHandle non-const accessors, ensure all by reference.

    • Add Type * operator->()
    • Fix Type get() const to const Type & get() const
    • Add Type & get()

    Fixes https://github.com/KhronosGroup/Vulkan-Hpp/issues/122#issuecomment-327198391

    opened by ioquatix 21
  • Ugly set methods for arrays -> Add std::cref support for arrays in *createInfo setters

    Ugly set methods for arrays -> Add std::cref support for arrays in *createInfo setters

    The set methods for arrays is a bit ugly and cumbersome.

    return vk::PipelineVertexInputStateCreateInfo()
    	.setVertexBindingDescriptionCount(binding_descriptions.size())
    	.setPVertexBindingDescriptions(binding_descriptions.data())
    	.setVertexAttributeDescriptionCount(attribute_descriptions.size())
    	.setPVertexAttributeDescriptions(attribute_descriptions.data());
    

    Would be nicer to write something like:

    return vk::PipelineVertexInputStateCreateInfo()
    	.setVertexBindingDescriptions(binding_descriptions)
    	.setVertexAttributeDescriptions(attribute_descriptions));
    

    Or perhaps:

    return vk::PipelineVertexInputStateCreateInfo()
    	.setVertexBindingDescriptions(binding_descriptions.begin(), binding_descriptions.end())
    	.setVertexAttributeDescriptions(attribute_descriptions.begin(), attribute_descriptions.end());
    

    Or both?

    opened by ioquatix 20
  • Pointer `len` not accepted in structs

    Pointer `len` not accepted in structs

    In a WIP MR, a struct is added where a count + an array of things are returned (similar to vkEnumeratePhysicalDevices). However, VulkanHppGenerator does not accept the idiomatic optional="false,true" set on the count, and len="pFooCount" on the pointer. It fails with the following message:

    member attribute <len> references a member of unexpected type <uint32_t *>
    
    opened by ShabbyX 19
  • Vulkan.hpp pollutes namespace by windows.h

    Vulkan.hpp pollutes namespace by windows.h

    Hi all,

    after upgrading Vulkan SDK, I cannot compile some projects. It turned out that vulkan.hpp now pollutes c++ namespace by huge number of macros, such as min, max, near, far, and tons of others. I was scared when I find out that it now pulls windows.h in by default. Recently, it was included only when VK_USE_PLATFORM_WIN32_KHR was defined. And I made sure to define it in very specific cpp files only and never in headers to minimize its impact.

    Now, with DynamicLoader,... yes, there are workarounds (VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL set to 0). But in my opinion, such horrible thing as windows.h should not be included by default. It not only makes compilation much longer but also pollutes the namespace by so many macros and garbage. And you have to fight through, especially in big projects... Endless renaming of variables, functions, etc. to make them not clash with windows.h garbage.

    I made some investigation. The whole problem is just because of HMODULE type and three functions - LoadLibrary, FreeLibrary and GetProcAddress. It seems to me that these might be handled without including windows.h. Would you be open to discuss such solution? Including windows.h is evil in my eyes unless completely necessary.

    John

    opened by pc-john 18
  • Optionally support (designated) aggregate initialization for structs.

    Optionally support (designated) aggregate initialization for structs.

    It would be really great if structs could be initialized with designated initializers (C++20), e.g:

    auto createInfo = vk::PipelineTessellationStateCreateInfo {
       .patchControlPoints = 4
    };
    

    Currently, this is prevented by:

    • The fact that structs define custom constructors.
    • The fact that most structs have a private StructureType member.
    • Default initialization is performed in the constructor instead of using default member initializers.

    A possible solution for all these issues might be the following construction: EDIT: note that this original suggestion was not a good idea, since the resulting struct will not be guaranteed to have the correct memory layout.

    template<StructureType s>
    struct StructureBase {
    private:
      StructureType sType = s;
    };
    
    struct PipelineInputAssemblyStateCreateInfo
    : StructureBase<StructureType::ePipelineInputAssemblyStateCreateInfo>
      {
        // no constructors
        ... // setters, operators as before
        // no private sType member
        // all fields use default member initializers
        const void* pNext = nullptr;
        PipelineInputAssemblyStateCreateFlags flags = PipelineInputAssemblyStateCreateFlags();
        PrimitiveTopology topology = PrimitiveTopology::ePointList;
        Bool32 primitiveRestartEnable = 0;
      };
    

    To achieve backwards compatibility constructors could still be defined, unless disabled by an explicit #define. An alternative to inheriting from a StructureBase template type would be another #define that changes the sType members from private to public.

    Any thoughts?

    opened by ekpyron 17
  • Better unique handles to simplify updating existing code.

    Better unique handles to simplify updating existing code.

    The current system for unique handles is useful but cumbersome especially when migrating existing code which doesn't use them. I'm not sure how useful these ideas are but I think it would be good to have a discussion about it.

    It would be good to discuss the following improvements:

    • Prefer std::unique_ptr as base implementation.
    • Type dependent allocation/initialization. Rather than vk::DeviceDeleter, expose vk::Device::Deleter.
    • Use a template for the majority of deleter implementations. You know you can pass function pointers as template parameters.
    • Use the type dependent lookup to automatically create the deleter appropriately rather than having to manually invoke specific methods.

    Ideally, it would be possible just to change the type signature, and have everything continue to work. In order to do that, you'd need a base wrapper which could be automatically converted to a unique pointer.

    vk::Device device;
    vk::Unique<vk::Device> unique_device;
    
    device = _physical_device.createDevice(device_info, alloc());
    unique_device = device; // take ownership
    

    or probably more reasonably:

    vk::Unique<vk::Device> device = _physical_device.createDevice(device_info, alloc());
    

    Otherwise, a lot of changes to the codebase are required to change createX to createXUnique.

    opened by ioquatix 17
  • Compiler error on gcc <= 6.5

    Compiler error on gcc <= 6.5

    Updating KhronosGroup/Vulkan-Tools to the latest Vulkan-Hpp on gcc version 6.5 and below produces several errors that look like this:

    In file included from /home/lunarg/.jenkins/w4/64-bit/Release/Vulkan-Tools/cube/cube.cpp:41:0:
    /home/lunarg/.jenkins/w4/64-bit/Release/Vulkan-Tools/external/Vulkan-Headers/build/install/include/vulkan/vulkan.hpp:824:13: error: specialization of 'template<class _Tp> struct std::hash' in different namespace [-fpermissive]
     struct std::hash<VULKAN_HPP_NAMESPACE::Flags<BitType>>
                 ^
    In file included from /usr/include/c++/5/bits/basic_string.h:5471:0,
                     from /usr/include/c++/5/string:52,
                     from /usr/include/c++/5/bits/locale_classes.h:40,
                     from /usr/include/c++/5/bits/ios_base.h:41,
                     from /usr/include/c++/5/ios:42,
                     from /usr/include/c++/5/ostream:38,
                     from /usr/include/c++/5/iostream:39,
                     from /home/lunarg/.jenkins/w4/64-bit/Release/Vulkan-Tools/cube/cube.cpp:35:
    /usr/include/c++/5/bits/functional_hash.h:58:12: error:   from definition of 'template<class _Tp> struct std::hash' [-fpermissive]
         struct hash;
                ^
    
    

    We are also seeing a related errors on the GitHub macOS CI runners:

    In file included from /Users/runner/work/Vulkan-Tools/Vulkan-Tools/cube/macOS/cubepp/DemoViewController.mm:24:
    In file included from /Users/runner/work/Vulkan-Tools/Vulkan-Tools/cube/cube.cpp:41:
    In file included from /Users/runner/work/Vulkan-Tools/Vulkan-Tools/external/Vulkan-Headers/build/install/include/vulkan/vulkan.hpp:6528:
    /Users/runner/work/Vulkan-Tools/Vulkan-Tools/external/Vulkan-Headers/build/install/include/vulkan/vulkan_structs.hpp:1196:5: error: implicit instantiation of undefined template 'std::__1::hash<vk::StructureType>'
        VULKAN_HPP_HASH_COMBINE( VULKAN_HPP_NAMESPACE::StructureType, seed, accelerationStructureBuildSizesInfoKHR.sType );
        ^
    /Users/runner/work/Vulkan-Tools/Vulkan-Tools/external/Vulkan-Headers/build/install/include/vulkan/vulkan.hpp:239:13: note: expanded from macro 'VULKAN_HPP_HASH_COMBINE'
        seed ^= std::hash<std::remove_const<valueType>::type>{}( value ) + 0x9e3779b9 + ( seed << 6 ) + ( seed >> 2 )
                ^
    /Applications/Xcode_12.4.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/type_traits:428:50: note: template is declared here
    template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash;
                                                     ^
    

    Newer versions of gcc and clang appear to work fine, however the latest Apple Clang compiler still shows the second error.

    opened by mikes-lunarg 16
  • Building using MinGW x64 and Ninja

    Building using MinGW x64 and Ninja

    Building the project for Windows using MSYS2 CMake (mingw-w64-x86_64-cmake) and Ninja (mingw-w64-x86_64-ninja), gives me this error: ninja: error: 'glslang/OGLCompilersDLL/libOGLCompiler.a', needed by 'samples/utils/libutils.a', missing and no known rule to make it

    Complete log: $ cmake -G Ninja -D DSAMPLES_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DSAMPLES_BUILD=ON -DTESTS_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DTESTS_BUILD=ON -DVULKAN_HPP_RUN_GENERATOR=0N -B build -- The C compiler identification is GNU 11.2.0 -- The CXX compiler identification is GNU 11.2.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: C:/msys64/mingw64/bin/cc.exe - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: C:/msys64/mingw64/bin/c++.exe - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done CMake Warning at CMakeLists.txt:56 (message): Could not find clang-format. Generated vulkan.hpp and vulkan_raii.hpp will not be nicely formatted.

    CMAKE_CXX_STANDARD = <11> -- Looking for pthread.h -- Looking for pthread.h - found -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success -- Found Threads: TRUE -- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE) -- Looking for dinput.h -- Looking for dinput.h - found -- Looking for xinput.h -- Looking for xinput.h - found -- Performing Test _GLFW_HAS_DEP -- Performing Test _GLFW_HAS_DEP - Success -- Performing Test _GLFW_HAS_ASLR -- Performing Test _GLFW_HAS_ASLR - Success -- Performing Test _GLFW_HAS_64ASLR -- Performing Test _GLFW_HAS_64ASLR - Success -- Using Win32 for window creation -- No build type selected, default to Debug -- Found PythonInterp: C:/msys64/mingw64/bin/python3.exe (found suitable version "3.9.7", minimum required is "3") -- Google Mock was not found - tests based on that will not build -- spirv-tools not linked - illegal SPIRV may be generated for HLSL -- Found Vulkan: C:/VulkanSDK/1.2.198.1/Lib/vulkan-1.lib -- Configuring done -- Generating done CMake Warning: Manually-specified variables were not used by the project:

    DSAMPLES_BUILD_WITH_LOCAL_VULKAN_HPP
    

    -- Build files have been written to: C:/Users/Henrique/Documents/Vulkan-Hpp/build

    $ ninja ninja: error: 'glslang/OGLCompilersDLL/libOGLCompiler.a', needed by 'samples/utils/libutils.a', missing and no known rule to make it

    opened by hott-henrique 14
  • vk::SurfaceKHR get pointer and m_surface cleanup in destructor?

    vk::SurfaceKHR get pointer and m_surface cleanup in destructor?

    I was looking though the header and saw that you can assign a VkSurfaceKHR to a vk::SurfaceKHR which stores it internally, but it doesn't clean up the m_surface with vkDestroySurfaceKHR() in a destructor. Is this something worth doing?

    Also I was trying to pass the vk::SurfaceKHR surface to glfwCreateWindowSurface() which takes a pointer to a c VkSurfaceKHR so was wondering if there was a way we could make that possible with vulkanhpp (a function that returns a pointer?).

    opened by dokipen3d 14
  • Allow for Vulkan functions to use the results of clients call to vkGetDeviceProcAddr

    Allow for Vulkan functions to use the results of clients call to vkGetDeviceProcAddr

    I'm referencing this stack-overflow question (look at the accepted answers where it talks about Vulkan.hpp)

    https://stackoverflow.com/questions/45868990/should-i-use-the-vulkan-loader/45871076?noredirect=1#comment78702774_45871076

    which talks about using vkGetDeviceProcAddr in order to avoid using the loader trampoline/terminator for efficiency reasons as described in this link

    https://vulkan.lunarg.com/doc/view/1.0.57.0/windows/LoaderAndLayerInterface.html#user-content-best-application-performance-setup

    Currently, I don't see a way to accomplish this using Vulkan.hpp

    opened by ghost 13
  • Vulkan HPP Compilation with Clang on Windows and Visual Studio 2019

    Vulkan HPP Compilation with Clang on Windows and Visual Studio 2019

    Vulkan HPP does not compile when using clang on Windows since clang interprets Windows defined constructs such as LPCSTR as distinctly different than char const *:

    extern "C" __declspec( dllimport ) void * __stdcall LoadLibraryA( char const * lpLibFileName );
    extern "C" __declspec( dllimport ) int __stdcall FreeLibrary( void * hLibModule );
    extern "C" __declspec( dllimport ) void * __stdcall GetProcAddress( void * hModule, char const * lpProcName );
    

    Ergo, clang believes the library loading functions do not share the same signatures as those defined in the Window's header libloaderapi.h. Hence, the fix to permit the Vulkan HPP to compile on Windows with clang is to simply change the signature and use reinterpret cast whenever these functions are called.:

    extern "C" __declspec( dllimport ) HMODULE __stdcall LoadLibraryA( LPCSTR lpLibFileName );
    extern "C" __declspec( dllimport ) BOOL __stdcall FreeLibrary( HMODULE hLibModule );
    extern "C" __declspec( dllimport ) FARPROC __stdcall GetProcAddress( HMODULE hModule, LPCSTR lpProcName );
    

    I have a patch for this, but I'm not certain if this is the repo to upload it to since it seems that the hpp file is also found in the Vulkan-Headers repo.

    opened by Fierykev 12
  • 1.3.229 SDK makes non-backward-compatible change to SwapchainKHR::getImages()

    1.3.229 SDK makes non-backward-compatible change to SwapchainKHR::getImages()

    The 1.3.224 and older SDK returns a std::vector<VkImage>.

    6fe966c6d985bab4d97bdaa55e1e97ea9dd4aec9 changes this to return a std::vector<vk::Image>. While vk::Image is directly convertible to VkImage, vector<vk::Image> and vector<VkImage> are not directly convertible.

    As a result, existing code which assigns the value of getImages() to a variable of type vector<VkImage> will no longer compile with the .229 SDK, and changing the type will make it require .229 and not compile with .224 or older. This doesn't seem like the kind of API change that should have been made in a minor version.

    I'm not sure what the best course of action is now that there's been an official SDK release containing this change, but I wanted to get it out there.

    opened by azonenberg 0
  • headers are too large

    headers are too large

    I really like using vulkan-hpp. But I think the generated headers are way too large for most users.

    This has significant productivity implications:

    • slows down compile time significantly, especially if not using precompiled headers.
    • IDE features such as auto complete tend not to work properly.

    Another issue I encountered is that when I tried putting vulkan_raii.hpp as an include file in my precompiled headers, I got the weirdest compile errors about incompatible precompiled headers (this is probably an MSVC issue, but still - it took a long time to figure out that vulkan_raii.hpp is the issue).

    I think there should be an option to generate "lighter" headers:

    • separating the "implementation" header needs to be included just once by a single .cpp file.
    • opting out of certain library features - for example the UniqueHandle api is probably unnecessary if one uses the raii API.
    • opting out of certain features. And I mean not even generating the code for them (just to be deactivated under a preprocessor command). Examples: VULKAN_HPP_NO_STRUCT_SETTERS, VULKAN_HPP_NO_STRUCT_CONSTRUCTORS VULKAN_HPP_HAS_SPACESHIP_OPERATOR etc.
    opened by eladmaimoni 13
  • Clarify which symbols are part of public API and which are implementation details

    Clarify which symbols are part of public API and which are implementation details

    The README explains in general how to use Vulkan-HPP, but it doesn’t really go into details. So, to figure out e.g. individual function signatures, I’ve taken to just browsing the header file. Unfortunately, the header file has very few comments, so I’m not sure which things I discover I’m really allowed to use—which are parts of Vulkan-HPP’s public API, and which are implementation details which are only in the header file for technical reasons (i.e. because Vulkan-HPP is a header-only library so everything is in header files)?

    For example, if I have a Result lying around, am I allowed to call throwResultException myself, or is that an implementation detail which might get renamed or deleted in a future version of Vulkan without warning?

    It would be good if implementation details were either commented as such, or perhaps put into an impl namespace or something like that.

    enhancement 
    opened by Hawk777 0
  • Handling

    Handling "vulkan owned" objects (DescriptorSet and CommandBuffer) in vk::raii

    When using the vk::raii interface it is currently impossible to handle descriptorsSets allocated from a descriptorPool created without vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet set.

    Regardless of the order these objects get destroyed it violates the vulkan specification:

    • Destroy pool first: The pool gets destroyed and destroys all its sets. The sets then get destroyed. This is invalid for two reasons: First the descriptorPool handle that gets passed to vkFreeDescriptorSets is no longer valid and second the descriptorSet already got destroyed.

    • Destroy sets first: This is invalid in itself without vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSetset for the pool.

    Something similar applies to commandBuffers and commandPools. While they can be destroyed manually it is also valid to just destroy the commandPool they belong to and all its commandBuffers will get destroyed automatically.

    Destroying a pool object implicitly frees all objects allocated from that pool. Specifically, destroying VkCommandPool frees all VkCommandBuffer objects that were allocated from it, and destroying VkDescriptorPool frees all VkDescriptorSet objects that were allocated from it.

    From here (almost at the end): https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#fundamentals-objectmodel-lifetime

    While just using the plain vulkan.hpp handles in this case is possible, I think it is not a good solution to the problem.

    I think the easiest and cleanest solution to this would be to add non owning versions of these objects to vk::raii. Then the user can decide to use the approriate one. A disadvantage would be, that it is possible to try and use a vk::raii object which is no longer valid, which rarely if ever happens in the rest of vk::raii. However validation layers should catch this. Another solution could be to add a function that releases the underlying handle to just those two objects. This would have the advantage that the user can decide at runtime wether the vulkan object still needs to be destroyed. However I don't like this solution, because it would be less clear from an interface perspective and also much less transparent in code.

    Edit: For the solution of adding special non owning versions of these objects you could also add explicit conversion constructors between the owning and non-owning version, so the user still has the freedom to choose the actually needed type at runtime.

    opened by Kasys 9
  • Is there some proper documentation somewhere?

    Is there some proper documentation somewhere?

    So far I've only been able to find the repo readme and the examples, but I feel like the examples are poorly documented... for example, what's a vk::raii::Context for? What's the vk::raii::su namespace and what does su even stand for? Why is it nested into raii? What's the different between the raii namespace stuff and UniqueHandles (aren't they supposed to clean up using RAII)? etc etc (and this is pretty much just the unanswered questions from the first raii example). Is there a doxygen page somewhere or something? I went into file RAII_Samples/utils/utils.hpp to check if it's commented there somewhere, but that file was pretty much devoid of comments (especially in regards to the questions above).

    opened by Falkgaard 9
Releases(v1.3.237)
Owner
The Khronos Group
Connecting Software to Silicon
The Khronos Group
A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input

GLFW Introduction GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan application development. It provides a simple, platf

GLFW 10k Jan 1, 2023
Low Level Graphics Library (LLGL) is a thin abstraction layer for the modern graphics APIs OpenGL, Direct3D, Vulkan, and Metal

Low Level Graphics Library (LLGL) Documentation NOTE: This repository receives bug fixes only, but no major updates. Pull requests may still be accept

Lukas Hermanns 1.5k Jan 8, 2023
基于 Vulkan 实现的 GPUImage

Vulkan-GPUImage 基于 Vulkan 渲染的 GPUImage 版本,实现渲染链机制,复刻 GPUImage 上的多个效果(逐渐增加中)。 更多技术实现,详见源码~~ Vulkan 学习文章 进击的 Vulkan 移动开发(一)之今生前世 进击的 Vulkan 移动开发之 Instan

glumes 143 Nov 15, 2022
Minimal pathtracer using Vulkan RayTracing

Single File Vulkan Pathtracing Minimal pathtracer using Vulkan RayTracing Environment Vulkan SDK 1.2.162.0 GPU / Driver that support Vulkan Ray Tracin

Yuki Nishidate 29 Dec 21, 2022
OBS Linux Vulkan/OpenGL game capture

OBS Linux Vulkan/OpenGL game capture OBS plugin for Vulkan/OpenGL game capture on Linux. Requires OBS with EGL support (currently unreleased, you need

David Rosca 290 Jan 1, 2023
Vulkan physically based raytracer including denoising

VulkanPBRT Vulkan physically based raytracer including denoising. The GPU raytracer is based on Vulkan only, as well as for the denoising only the Vul

null 18 Nov 25, 2022
Axel Gneiting 1.5k Dec 31, 2022
A toy renderer written in C using Vulkan to perform real-time ray tracing research.

This is a toy renderer written in C using Vulkan. It is intentionally minimalist. It has been developed and used for the papers "BRDF Importance Sampl

Christoph Peters 290 Dec 19, 2022
This repository accompanies Ray Tracing Gems II: Next Generation Rendering with DXR, Vulkan, and OptiX

Apress Source Code This repository accompanies Ray Tracing Gems II: Next Generation Rendering with DXR, Vulkan, and OptiX by Adam Marrs, Peter Shirley

Apress 684 Dec 29, 2022
Vulkan Minimal Hybrid Rendering

Vulkan Minimal Hybrid Rendering A minimal hybrid rendering sample using ray query Features Rasterization Raytraced shadow Environment Vulkan SDK 1.2.1

Yuki Nishidate 11 Aug 31, 2022
vkfetch is a fetch-program that displays basic information about your vulkan-compatible graphic card(s)!

vkfetch vkfetch is a fetch-program that displays basic information about your vulkan-compatible graphic card(s)! vkfetch will also display some vendor

Wunk 19 Oct 27, 2022
simple fdtd using vulkan, omp or single thread

fdtd simple fdtd using vulkan, omp or single thread example how to build first clone the repo with: git clone https://github.com/nikisalli/fdtd.git up

Nik 5 Nov 12, 2022
This repo will sort of document my story of learning vulkan with VulkanSDK and cl (msvc) on windows.

Learning Vulkan This repo is a means of documenting my journey with learning Vulkan's basics on windows. Because of the binaries in the LunarG VulkanS

null 2 Dec 8, 2021
A realtime Vulkan voxel path tracer.

brickmap-vulkan A realtime Vulkan voxel path tracer. This is a work in progress! This system is a Vulkan/SPIRV implementation of the BrickMap by stijn

brandon reinhart 0 Nov 3, 2022
Implementation of Peter Shirley's Ray Tracing In One Weekend book using Vulkan and NVIDIA's RTX extension.

Ray Tracing In Vulkan My implementation of Peter Shirley's Ray Tracing in One Weekend books using Vulkan and NVIDIA's RTX extension (formerly VK_NV_ra

Tanguy Fautre 862 Dec 31, 2022
C++/openGL/Vulkan 3D engine

DeusEx Machina engine C++/GL/Vulkan 3D graphic engine First commit, hello world! :D Reddit post about why I started with skeletal animation system and

Brais 41 May 19, 2022
Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform AAA Open 3D Engine

Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform 3D engine that enables developers and content creators to build AAA games, cinema-quality 3D worlds, and high-fidelity simulations without any fees or commercial obligations.

O3DE 5.8k Jan 7, 2023
An Open-Source subdivision surface library.

OpenSubdiv OpenSubdiv is a set of open source libraries that implement high performance subdivision surface (subdiv) evaluation on massively parallel

Pixar Animation Studios 2.7k Jan 2, 2023
An open-source implementation of Autodesk's FBX

SmallFBX An open-source implementation of Autodesk's FBX that is capable of import & export mesh, blend shape, skin, and animations. Mainly intended t

Seiya Ishibashi 43 Dec 21, 2022