mirror of
https://github.com/KhronosGroup/Vulkan-Hpp.git
synced 2024-10-14 16:32:17 +00:00
Fix typo in README.md (#179)
This commit is contained in:
parent
75cb7d14f1
commit
bae68b49aa
722
README.md
722
README.md
@ -1,364 +1,364 @@
|
|||||||
# Vulkan-Hpp: C++ Bindings for Vulkan
|
# 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.
|
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 |
|
| Platform | Build Status |
|
||||||
|:--------:|:------------:|
|
|:--------:|:------------:|
|
||||||
| Linux | [![Build Status](https://travis-ci.org/KhronosGroup/Vulkan-Hpp.svg?branch=master)](https://travis-ci.org/KhronosGroup/Vulkan-Hpp) |
|
| Linux | [![Build Status](https://travis-ci.org/KhronosGroup/Vulkan-Hpp.svg?branch=master)](https://travis-ci.org/KhronosGroup/Vulkan-Hpp) |
|
||||||
|
|
||||||
## Getting Started
|
## 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](https://github.com/KhronosGroup/Vulkan-Hpp/blob/master/vulkan/vulkan.hpp).
|
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](https://github.com/KhronosGroup/Vulkan-Hpp/blob/master/vulkan/vulkan.hpp).
|
||||||
|
|
||||||
### Minimum Requirements
|
### Minimum Requirements
|
||||||
|
|
||||||
Vulkan-Hpp requires a C++11 capable compiler to compile. The following compilers are known to work:
|
Vulkan-Hpp requires a C++11 capable compiler to compile. The following compilers are known to work:
|
||||||
* Visual Studio >=2015
|
* Visual Studio >=2015
|
||||||
* GCC >= 4.8.2 (earlier version might work, but are untested)
|
* GCC >= 4.8.2 (earlier version might work, but are untested)
|
||||||
* Clang >= 3.3
|
* Clang >= 3.3
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### namespace vk
|
### 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
|
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 leter of functions is lower case.
|
* All functions, enums, handles, and structs have the Vk prefix removed. In addition to this the first leter of functions is lower case.
|
||||||
* `vkCreateImage` can be accessed as `vk::createImage`
|
* `vkCreateImage` can be accessed as `vk::createImage`
|
||||||
* `VkImageTiling` can be accessed as `vk::ImageTiling`
|
* `VkImageTiling` can be accessed as `vk::ImageTiling`
|
||||||
* `VkImageCreateInfo` can be accessed as `vk::ImageCreateInfo`
|
* `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.
|
* 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.
|
In all other cases the extension suffix has not been removed.
|
||||||
* `VK_IMAGETYPE_2D` is now `vk::ImageType::e2D`.
|
* `VK_IMAGETYPE_2D` is now `vk::ImageType::e2D`.
|
||||||
* `VK_COLOR_SPACE_SRGB_NONLINEAR_KHR` is now `vk::ColorSpaceKHR::eSrgbNonlinear`.
|
* `VK_COLOR_SPACE_SRGB_NONLINEAR_KHR` is now `vk::ColorSpaceKHR::eSrgbNonlinear`.
|
||||||
* `VK_STRUCTURE_TYPE_PRESENT_INFO_KHR` is now `vk::StructureType::ePresentInfoKHR`.
|
* `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.
|
* 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.
|
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
|
### 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, ...)`.
|
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, ...)`.
|
||||||
|
|
||||||
### C/C++ Interop for Handles
|
### 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.
|
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
|
### 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 |.
|
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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
vk::ImageUsage iu1; // initialize a bitmask with no bit set
|
vk::ImageUsage iu1; // initialize a bitmask with no bit set
|
||||||
vk::ImageUsage iu2 = {}; // initialize a bitmask with no bit set
|
vk::ImageUsage iu2 = {}; // initialize a bitmask with no bit set
|
||||||
vk::ImageUsage iu3 = vk::ImageUsage::eColorAttachment; // initialize with a single value
|
vk::ImageUsage iu3 = vk::ImageUsage::eColorAttachment; // initialize with a single value
|
||||||
vk::ImageUsage iu4 = vk::ImageUsage::eColorAttachment | vk::ImageUsage::eStorage; // or two bits to get a bitmask
|
vk::ImageUsage iu4 = vk::ImageUsage::eColorAttachment | vk::ImageUsage::eStorage; // or two bits to get a bitmask
|
||||||
PipelineShaderStageCreateInfo ci( {} /* pass a flag without any bits set */, ...);
|
PipelineShaderStageCreateInfo ci( {} /* pass a flag without any bits set */, ...);
|
||||||
```
|
```
|
||||||
|
|
||||||
### CreateInfo structs
|
### 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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
VkImageCreateInfo ci;
|
VkImageCreateInfo ci;
|
||||||
ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
ci.pNext = nullptr;
|
ci.pNext = nullptr;
|
||||||
ci.flags = ...some flags...;
|
ci.flags = ...some flags...;
|
||||||
ci.imageType = VK_IMAGE_TYPE_2D;
|
ci.imageType = VK_IMAGE_TYPE_2D;
|
||||||
ci.format = VK_FORMAT_R8G8B8A8_UNORM;
|
ci.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
ci.extent = VkExtent3D { width, height, 1 };
|
ci.extent = VkExtent3D { width, height, 1 };
|
||||||
ci.mipLevels = 1;
|
ci.mipLevels = 1;
|
||||||
ci.arrayLayers = 1;
|
ci.arrayLayers = 1;
|
||||||
ci.samples = VK_SAMPLE_COUNT_1_BIT;
|
ci.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
ci.tiling = VK_IMAGE_TILING_OPTIMAL;
|
ci.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
ci.queueFamilyIndexCount = 0;
|
ci.queueFamilyIndexCount = 0;
|
||||||
ci.pQueueFamilyIndices = 0;
|
ci.pQueueFamilyIndices = 0;
|
||||||
ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
vkCreateImage(device, &ci, allocator, &image));
|
vkCreateImage(device, &ci, allocator, &image));
|
||||||
```
|
```
|
||||||
|
|
||||||
There are two typical issues Vulkan developers encounter when filling out a CreateInfo struct field by field
|
There are two typical issues Vulkan developers encounter when filling out a CreateInfo struct field by field
|
||||||
* One or more fields are left uninitialized.
|
* One or more fields are left uninitialized.
|
||||||
* `sType` is incorrect.
|
* `sType` is incorrect.
|
||||||
|
|
||||||
Especially the first one is hard to detect.
|
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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
vk::ImageCreateInfo ci({}, vk::ImageType::e2D, vk::format::eR8G8B8A8Unorm,
|
vk::ImageCreateInfo ci({}, vk::ImageType::e2D, vk::format::eR8G8B8A8Unorm,
|
||||||
{ width, height, 1 },
|
{ width, height, 1 },
|
||||||
1, 1, vk::SampleCount::e1,
|
1, 1, vk::SampleCount::e1,
|
||||||
vk::ImageTiling::eOptimal, vk::ImageUsage:eColorAttachment,
|
vk::ImageTiling::eOptimal, vk::ImageUsage:eColorAttachment,
|
||||||
vk::SharingMode::eExclusive, 0, 0, vk::Imagelayout::eUndefined);
|
vk::SharingMode::eExclusive, 0, 0, vk::Imagelayout::eUndefined);
|
||||||
```
|
```
|
||||||
|
|
||||||
With constructors for CreateInfo structures one can also pass temporaries to Vulkan functions like this:
|
With constructors for CreateInfo structures one can also pass temporaries to Vulkan functions like this:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
vk::Image image = device.createImage({{}, vk::ImageType::e2D, vk::format::eR8G8B8A8Unorm,
|
vk::Image image = device.createImage({{}, vk::ImageType::e2D, vk::format::eR8G8B8A8Unorm,
|
||||||
{ width, height, 1 },
|
{ width, height, 1 },
|
||||||
1, 1, vk::SampleCount::e1,
|
1, 1, vk::SampleCount::e1,
|
||||||
vk::ImageTiling::eOptimal, vk::ImageUsage:eColorAttachment,
|
vk::ImageTiling::eOptimal, vk::ImageUsage:eColorAttachment,
|
||||||
vk::SharingMode::eExclusive, 0, 0, vk::Imagelayout::eUndefined});
|
vk::SharingMode::eExclusive, 0, 0, vk::Imagelayout::eUndefined});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Passing Arrays to Functions using ArrayProxy
|
### 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.
|
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:
|
Here are some code samples on how to use the ArrayProxy:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
vk::CommandBuffer c;
|
vk::CommandBuffer c;
|
||||||
|
|
||||||
// pass an empty array
|
// pass an empty array
|
||||||
c.setScissor(0, nullptr);
|
c.setScissor(0, nullptr);
|
||||||
|
|
||||||
// pass a single value. Value is passed as reference
|
// pass a single value. Value is passed as reference
|
||||||
vk::Rect2D scissorRect = { {0, 0}, {640, 480} };
|
vk::Rect2D scissorRect = { {0, 0}, {640, 480} };
|
||||||
c.setScissor(0, scissorRect);
|
c.setScissor(0, scissorRect);
|
||||||
|
|
||||||
// pass a temporary value.
|
// pass a temporary value.
|
||||||
c.setScissor(0, { { 0, 0 },{ 640, 480 } });
|
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.
|
// 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 scissorRect1 = { { 0, 0 },{ 320, 240 } };
|
||||||
vk::Rect2D scissorRect2 = { { 320, 240 },{ 320, 240 } };
|
vk::Rect2D scissorRect2 = { { 320, 240 },{ 320, 240 } };
|
||||||
c.setScissor(0, { scissorRect, scissorRect2 });
|
c.setScissor(0, { scissorRect, scissorRect2 });
|
||||||
|
|
||||||
// construct a std::initializer_list using two temporary rectangles.
|
// construct a std::initializer_list using two temporary rectangles.
|
||||||
c.setScissor(0, { { { 0, 0 },{ 320, 240 } },
|
c.setScissor(0, { { { 0, 0 },{ 320, 240 } },
|
||||||
{ { 320, 240 },{ 320, 240 } }
|
{ { 320, 240 },{ 320, 240 } }
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// pass a std::array
|
// pass a std::array
|
||||||
std::array<vk::Rect2D, 2> arr{ scissorRect1, scissorRect2 };
|
std::array<vk::Rect2D, 2> arr{ scissorRect1, scissorRect2 };
|
||||||
c.setScissor(0, arr);
|
c.setScissor(0, arr);
|
||||||
|
|
||||||
// pass a std::vector of dynamic size
|
// pass a std::vector of dynamic size
|
||||||
std::vector<vk::Rect2D> vec;
|
std::vector<vk::Rect2D> vec;
|
||||||
vec.push_back(scissorRect1);
|
vec.push_back(scissorRect1);
|
||||||
vec.push_back(scissorRect2);
|
vec.push_back(scissorRect2);
|
||||||
c.setScissor(0, vec);
|
c.setScissor(0, vec);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Passing Structs to Functions
|
### 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.
|
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++
|
```c++
|
||||||
// C
|
// C
|
||||||
ImageSubResource subResource;
|
ImageSubResource subResource;
|
||||||
subResource.aspectMask = 0;
|
subResource.aspectMask = 0;
|
||||||
subResource.mipLevel = 0;
|
subResource.mipLevel = 0;
|
||||||
subResource.arrayLayer = 0;
|
subResource.arrayLayer = 0;
|
||||||
vkSubresourceLayout layout = vkGetImageSubResourceLayout(image, subresource);
|
vkSubresourceLayout layout = vkGetImageSubResourceLayout(image, subresource);
|
||||||
|
|
||||||
// C++
|
// C++
|
||||||
auto layout = device.getImageSubResourceLayout(image, { {} /* flags*/, 0 /* miplevel */, 0 /* layout */ });
|
auto layout = device.getImageSubResourceLayout(image, { {} /* flags*/, 0 /* miplevel */, 0 /* layout */ });
|
||||||
```
|
```
|
||||||
|
|
||||||
### Structure Pointer Chains
|
### 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.
|
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.
|
// This will compile successfully.
|
||||||
vk::StructureChain<vk::MemoryAllocateInfo, vk::ImportMemoryFdInfoKHR> c;
|
vk::StructureChain<vk::MemoryAllocateInfo, vk::ImportMemoryFdInfoKHR> c;
|
||||||
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
|
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
|
||||||
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
|
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
|
||||||
|
|
||||||
// This will fail compilation since it's not valid according to the spec.
|
// This will fail compilation since it's not valid according to the spec.
|
||||||
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedRequirementsKHR> c;
|
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedRequirementsKHR> c;
|
||||||
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
|
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
|
||||||
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
|
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
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:
|
// Query vk::MemoryRequirements2KHR and vk::MemoryDedicatedRequirementsKHR when calling Device::getBufferMemoryRequirements2KHR:
|
||||||
auto result = device.getBufferMemoryRequirements2KHR<vk::MemoryRequirements2KHR, vk::MemoryDedicatedRequirementsKHR>({});
|
auto result = device.getBufferMemoryRequirements2KHR<vk::MemoryRequirements2KHR, vk::MemoryDedicatedRequirementsKHR>({});
|
||||||
vk::MemoryRequirements2KHR &memReqs = result.get<vk::MemoryRequirements2KHR>();
|
vk::MemoryRequirements2KHR &memReqs = result.get<vk::MemoryRequirements2KHR>();
|
||||||
vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedRequirementsKHR>();
|
vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedRequirementsKHR>();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Return values, Error Codes & Exceptions
|
### 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 <SomeType>::type is defined as the returned type.
|
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.
|
||||||
|
|
||||||
To create a device you can now just write:
|
To create a device you can now just write:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
vk::Device device = physicalDevice.createDevice(createInfo);
|
vk::Device device = physicalDevice.createDevice(createInfo);
|
||||||
```
|
```
|
||||||
|
|
||||||
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`.
|
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:
|
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:
|
The first snippet shows how to use the API without exceptions and the return value transformation:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
// No exceptions, no return value transformation
|
// No exceptions, no return value transformation
|
||||||
ShaderModuleCreateInfo createInfo(...);
|
ShaderModuleCreateInfo createInfo(...);
|
||||||
ShaderModule shader1;
|
ShaderModule shader1;
|
||||||
Result result = device.createShaderModule(&createInfo, allocator, &shader1);
|
Result result = device.createShaderModule(&createInfo, allocator, &shader1);
|
||||||
if (result.result != VK_SUCCESS)
|
if (result.result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
handle error code;
|
handle error code;
|
||||||
cleanup?
|
cleanup?
|
||||||
return?
|
return?
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModule shader2;
|
ShaderModule shader2;
|
||||||
Result result = device.createShaderModule(&createInfo, allocator, &shader2);
|
Result result = device.createShaderModule(&createInfo, allocator, &shader2);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
handle error code;
|
handle error code;
|
||||||
cleanup?
|
cleanup?
|
||||||
return?
|
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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */);
|
ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */);
|
||||||
if (shaderResult1.result != VK_SUCCESS)
|
if (shaderResult1.result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
handle error code;
|
handle error code;
|
||||||
cleanup?
|
cleanup?
|
||||||
return?
|
return?
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::tie support.
|
// std::tie support.
|
||||||
vk::Result result;
|
vk::Result result;
|
||||||
vk::ShaderModule shaderModule2;
|
vk::ShaderModule shaderModule2;
|
||||||
std::tie(result, shaderModule2) = device.createShaderModule({...} /* createInfo temporary */);
|
std::tie(result, shaderModule2) = device.createShaderModule({...} /* createInfo temporary */);
|
||||||
if (shaderResult2.result != VK_SUCCESS)
|
if (shaderResult2.result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
handle error code;
|
handle error code;
|
||||||
cleanup?
|
cleanup?
|
||||||
return?
|
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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo temporary */);
|
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.
|
Finally, the last code example is using exceptions and return value transformation. This is the default mode of the API.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
ShaderModule shader1;
|
ShaderModule shader1;
|
||||||
ShaderModule shader2;
|
ShaderModule shader2;
|
||||||
try {
|
try {
|
||||||
myHandle = device.createShaderModule({...});
|
myHandle = device.createShaderModule({...});
|
||||||
myHandle2 = device.createShaderModule({...});
|
myHandle2 = device.createShaderModule({...});
|
||||||
} catch(std::exception const &e) {
|
} catch(std::exception const &e) {
|
||||||
// handle error and free resources
|
// 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!
|
Keep in mind that Vulkan-Hpp does not support RAII style handles and that you have to cleanup your resources in the error handler!
|
||||||
|
|
||||||
### Enumerations
|
### 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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
std::vector<LayerProperties,Allocator> properties;
|
std::vector<LayerProperties,Allocator> properties;
|
||||||
uint32_t propertyCount;
|
uint32_t propertyCount;
|
||||||
Result result;
|
Result result;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// determine number of elements to query
|
// determine number of elements to query
|
||||||
result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, nullptr ) );
|
result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, nullptr ) );
|
||||||
if ( ( result == Result::eSuccess ) && propertyCount )
|
if ( ( result == Result::eSuccess ) && propertyCount )
|
||||||
{
|
{
|
||||||
// allocate memory & query again
|
// allocate memory & query again
|
||||||
properties.resize( propertyCount );
|
properties.resize( propertyCount );
|
||||||
result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, reinterpret_cast
|
result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, reinterpret_cast
|
||||||
<VkLayerProperties*>( properties.data() ) ) );
|
<VkLayerProperties*>( properties.data() ) ) );
|
||||||
}
|
}
|
||||||
} while ( result == Result::eIncomplete );
|
} while ( result == Result::eIncomplete );
|
||||||
// it's possible that the count has changed, start again if properties was not big enough
|
// it's possible that the count has changed, start again if properties was not big enough
|
||||||
properties.resize(propertyCount);
|
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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
std::vector<LayerProperties> properties = physicalDevice.enumerateDeviceLayerProperties();
|
std::vector<LayerProperties> properties = physicalDevice.enumerateDeviceLayerProperties();
|
||||||
```
|
```
|
||||||
|
|
||||||
### UniqueHandle for automatic resource management
|
### UniqueHandle for automatic resource management
|
||||||
|
|
||||||
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`.
|
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` there is `vk::allocateCommandBuffersUnique`.
|
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.
|
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
|
### 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:
|
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:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
std::vector<LayerProperties, MyCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties<MyCustomAllocator>();
|
std::vector<LayerProperties, MyCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties<MyCustomAllocator>();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Custom assertions
|
### 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.
|
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.
|
||||||
|
|
||||||
### Extensions / Per Device function pointers
|
### 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
|
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
|
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.
|
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.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
// This dispatch class will fetch all function pointers through the passed instance
|
// This dispatch class will fetch all function pointers through the passed instance
|
||||||
vk::DispatchLoaderDynamic dldi(instance);
|
vk::DispatchLoaderDynamic dldi(instance);
|
||||||
|
|
||||||
// This dispatch class will fetch function pointers for the passed device if possible, else for the passed instance
|
// This dispatch class will fetch function pointers for the passed device if possible, else for the passed instance
|
||||||
vk::DispatchLoaderDynamic dldid(instance, device);
|
vk::DispatchLoaderDynamic dldid(instance, device);
|
||||||
|
|
||||||
// Pass dispatch class to function call as last parameter
|
// Pass dispatch class to function call as last parameter
|
||||||
device.getQueue(graphics_queue_family_index, 0, &graphics_queue, dldid);
|
device.getQueue(graphics_queue_family_index, 0, &graphics_queue, dldid);
|
||||||
```
|
```
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
Feel free to submit a PR to add to this list.
|
Feel free to submit a PR to add to this list.
|
||||||
|
|
||||||
- [Vookoo](https://github.com/andy-thomason/Vookoo/) Stateful helper classes for Vulkan-Hpp, [Introduction Article](https://accu.org/index.php/journals/2380).
|
- [Vookoo](https://github.com/andy-thomason/Vookoo/) Stateful helper classes for Vulkan-Hpp, [Introduction Article](https://accu.org/index.php/journals/2380).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright 2015-2017 The Khronos Group Inc.
|
Copyright 2015-2017 The Khronos Group Inc.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user