mirror of
https://github.com/KhronosGroup/Vulkan-Hpp.git
synced 2024-10-14 16:32:17 +00:00
Minor edits to README (#1832)
* Minor edits to README * Address feedback and perform another edit pass on README
This commit is contained in:
parent
a7ac08b8d2
commit
268fb77fb5
360
README.md
360
README.md
@ -9,12 +9,12 @@ The goal of the Vulkan-Hpp is to provide header only C++ bindings for the Vulkan
|
||||
|
||||
## 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](https://www.lunarg.com/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 headers [here](vulkan).
|
||||
|
||||
### Minimum Requirements
|
||||
|
||||
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)
|
||||
* Clang >= 3.3
|
||||
|
||||
@ -27,16 +27,19 @@ To build the local samples and tests you'll have to clone this repository and ru
|
||||
* Ensure that you have installed the Vulkan SDK.
|
||||
* Optionally install clang-format >= 11.0 to get a nicely formatted Vulkan-Hpp header.
|
||||
1. Open a shell which provides git and clone the repository with:
|
||||
```git clone --recurse-submodules https://github.com/KhronosGroup/Vulkan-Hpp.git```
|
||||
2. Change the current directory to the newly created Vulkan-Hpp directory.
|
||||
3. Create a build environment with CMake
|
||||
```cmake -DVULKAN_HPP_SAMPLES_BUILD=ON -DVULKAN_HPP_SAMPLES_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DVULKAN_HPP_TESTS_BUILD=ON -DVULKAN_HPP_TESTS_BUILD_WITH_LOCAL_VULKAN_HPP=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.
|
||||
4. Either open the generated project with an IDE, e.g. Visual Studio or launch the build process with ```cmake --build build --parallel```.
|
||||
|
||||
Optional: To update the Vulkan-Hpp and its submodules execute ```git pull --recurse-submodules```.
|
||||
`git clone --recurse-submodules https://github.com/KhronosGroup/Vulkan-Hpp.git`
|
||||
2. Change the current directory to the newly created Vulkan-Hpp directory.
|
||||
3. Create a build environment with CMake:
|
||||
|
||||
`cmake -DVULKAN_HPP_SAMPLES_BUILD=ON -DVULKAN_HPP_SAMPLES_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DVULKAN_HPP_TESTS_BUILD=ON -DVULKAN_HPP_TESTS_BUILD_WITH_LOCAL_VULKAN_HPP=ON -B build`
|
||||
|
||||
You might need 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.
|
||||
4. Either open the generated project with an IDE, e.g. Visual Studio or launch the build process with `cmake --build build --parallel`.
|
||||
|
||||
Optional: To update the Vulkan-Hpp and its submodules execute `git pull --recurse-submodules`.
|
||||
|
||||
### Installing vulkan-hpp using vcpkg
|
||||
|
||||
@ -56,31 +59,31 @@ The vulkan-hpp port in vcpkg is kept up to date by Microsoft team members and co
|
||||
|
||||
#### 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.
|
||||
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.
|
||||
|
||||
#### Custom views of Vulkan-Hpp objects in Visual Studio
|
||||
|
||||
The file VulkanHpp.natvis provides a custom view on vk::Flags for Visual Studio. If you add this file to the user-specific natvis directory of your Visual Studio installation (%USERPROFILE%\Documents\Visual Studio 2022\Visualizers), you get vk::Flags nicely formatted in your debugger with all your Visual Studio projects.
|
||||
The file `VulkanHpp.natvis` provides a custom view on `vk::Flags` for Visual Studio. If you add this file to the user-specific natvis directory of your Visual Studio installation (%USERPROFILE%\Documents\Visual Studio 2022\Visualizers), you get `vk::Flags` nicely formatted in your debugger with all your Visual Studio projects.
|
||||
|
||||
## 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
|
||||
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.
|
||||
* 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. If 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`.
|
||||
* `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.
|
||||
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
|
||||
|
||||
@ -88,24 +91,24 @@ Vulkan-Hpp declares a class for all handles to ensure full type safety and to ad
|
||||
|
||||
### 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.
|
||||
There is an additional header named [`vulkan_raii.hpp`](vulkan/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](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: `VkImage = static_cast<VkImage>(cppImage)` 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: `VkImage = static_cast<VkImage>(cppImage)` 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 to 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 |.
|
||||
The scoped enum feature adds type safety to the flags, but also prevents using the flag bits as input for bitwise operations such as `&` 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 class template `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++
|
||||
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 */, ...);
|
||||
PipelineShaderStageCreateInfo ci({} /* pass a flag without any bits set */, ...);
|
||||
```
|
||||
|
||||
### CreateInfo structs
|
||||
@ -129,16 +132,16 @@ ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ci.queueFamilyIndexCount = 0;
|
||||
ci.pQueueFamilyIndices = 0;
|
||||
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.
|
||||
* `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:
|
||||
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++
|
||||
vk::ImageCreateInfo ci({}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
|
||||
@ -149,7 +152,7 @@ vk::ImageCreateInfo ci({}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
|
||||
vk::Image image = device.createImage(ci);
|
||||
```
|
||||
|
||||
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++
|
||||
vk::Image image = device.createImage({{}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
|
||||
@ -161,7 +164,8 @@ vk::Image image = device.createImage({{}, vk::ImageType::e2D, vk::Format::eR8G8B
|
||||
|
||||
### 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
|
||||
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:
|
||||
|
||||
```c++
|
||||
// initialize the vk::ApplicationInfo structure
|
||||
vk::ApplicationInfo applicationInfo{ .pApplicationName = AppName,
|
||||
@ -171,24 +175,27 @@ vk::ApplicationInfo applicationInfo{ .pApplicationName = AppName,
|
||||
.apiVersion = VK_API_VERSION_1_1 };
|
||||
|
||||
// initialize the vk::InstanceCreateInfo
|
||||
vk::InstanceCreateInfo instanceCreateInfo{ .pApplicationInfo = & applicationInfo };
|
||||
vk::InstanceCreateInfo instanceCreateInfo{ .pApplicationInfo = &applicationInfo };
|
||||
```
|
||||
|
||||
instead of
|
||||
|
||||
```c++
|
||||
// initialize the vk::ApplicationInfo structure
|
||||
vk::ApplicationInfo applicationInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
|
||||
vk::ApplicationInfo applicationInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1);
|
||||
|
||||
// initialize the vk::InstanceCreateInfo
|
||||
vk::InstanceCreateInfo instanceCreateInfo( {}, &applicationInfo );
|
||||
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.
|
||||
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.
|
||||
The Vulkan API has several places 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 `vk::ArrayProxy` class template 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 `vk::ArrayProxy`:
|
||||
|
||||
```c++
|
||||
vk::CommandBuffer c;
|
||||
@ -197,26 +204,24 @@ vk::CommandBuffer c;
|
||||
c.setScissor(0, nullptr);
|
||||
|
||||
// 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);
|
||||
|
||||
// pass a temporary value.
|
||||
c.setScissor(0, { { 0, 0 },{ 640, 480 } });
|
||||
c.setScissor(0, { { 0, 0 }, { 640, 480 } });
|
||||
|
||||
// pass a fixed size array
|
||||
vk::Rect2D scissorRects[2] = { { { 0, 0 }, { 320, 240 } }, { { 320, 240 }, { 320, 240 } } };
|
||||
c.setScissor(0, scissorRects);
|
||||
|
||||
// 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 } };
|
||||
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 } }
|
||||
}
|
||||
);
|
||||
c.setScissor(0, { { { 0, 0 }, { 320, 240 } },
|
||||
{ { 320, 240 }, { 320, 240 } } });
|
||||
|
||||
// pass a std::array
|
||||
std::array<vk::Rect2D, 2> arr{ scissorRect1, scissorRect2 };
|
||||
@ -231,7 +236,7 @@ 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.
|
||||
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 `vk::Optional<T> const&`. This type accepts either a reference to `T` or `nullptr` as input and thus allows optional temporary structs.
|
||||
|
||||
```c++
|
||||
// C
|
||||
@ -248,7 +253,7 @@ auto layout = device.getImageSubresourceLayout(image, { {} /* flags*/, 0 /* mipl
|
||||
|
||||
### 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 class template 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.
|
||||
|
||||
```c++
|
||||
// This will compile successfully.
|
||||
@ -262,7 +267,7 @@ 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:
|
||||
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:
|
||||
|
||||
```c++
|
||||
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> c = {
|
||||
@ -271,8 +276,8 @@ vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> c =
|
||||
};
|
||||
```
|
||||
|
||||
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>()```.
|
||||
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:
|
||||
|
||||
@ -285,24 +290,24 @@ vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedR
|
||||
|
||||
To get just the base structure, without chaining, the other getter function provided does not need a template argument for the structure to get:
|
||||
|
||||
```
|
||||
```c++
|
||||
// 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 <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 `vk::ResultValue<SomeType>::type` is defined as the returned type.
|
||||
|
||||
To create a device you can now just write:
|
||||
|
||||
```C++
|
||||
```c++
|
||||
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:
|
||||
Some functions allow more than just `vk::Result::eSuccess` to be considered as a success code. For those functions, we always return a `vk::ResultValue<SomeType>`. An example is `acquireNextImage2KHR`, that can be used like this:
|
||||
|
||||
```C++
|
||||
```c++
|
||||
vk::ResultValue<uint32_t> result = device->acquireNextImage2KHR(acquireNextImageInfo);
|
||||
switch (result.result)
|
||||
{
|
||||
@ -320,41 +325,41 @@ switch (result.result)
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
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`.
|
||||
If exception handling is disabled by defining `VULKAN_HPP_NO_EXCEPTIONS` the type of `vk::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:
|
||||
|
||||
```c++
|
||||
// No exceptions, no return value transformation
|
||||
ShaderModuleCreateInfo createInfo(...);
|
||||
ShaderModule shader1;
|
||||
Result result = device.createShaderModule(&createInfo, allocator, &shader1);
|
||||
if (result.result != VK_SUCCESS)
|
||||
vk::ShaderModuleCreateInfo createInfo(...);
|
||||
vk::ShaderModule shader1;
|
||||
vk::Result result = device.createShaderModule(&createInfo, allocator, &shader1);
|
||||
if (result.result != vk::Result::eSuccess)
|
||||
{
|
||||
handle error code;
|
||||
cleanup?
|
||||
return?
|
||||
handle error code;
|
||||
cleanup?
|
||||
return?
|
||||
}
|
||||
|
||||
ShaderModule shader2;
|
||||
Result result = device.createShaderModule(&createInfo, allocator, &shader2);
|
||||
if (result != VK_SUCCESS)
|
||||
vk::ShaderModule shader2;
|
||||
vk::Result result = device.createShaderModule(&createInfo, allocator, &shader2);
|
||||
if (result != vk::Result::eSuccess)
|
||||
{
|
||||
handle error code;
|
||||
cleanup?
|
||||
return?
|
||||
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:
|
||||
|
||||
```c++
|
||||
ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */);
|
||||
if (shaderResult1.result != VK_SUCCESS)
|
||||
vk::ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */);
|
||||
if (shaderResult1.result != vk::Result::eSuccess)
|
||||
{
|
||||
handle error code;
|
||||
cleanup?
|
||||
@ -364,8 +369,8 @@ if (shaderResult1.result != VK_SUCCESS)
|
||||
// std::tie support.
|
||||
vk::Result result;
|
||||
vk::ShaderModule shaderModule2;
|
||||
std::tie(result, shaderModule2) = device.createShaderModule({...} /* createInfo temporary */);
|
||||
if (result != VK_SUCCESS)
|
||||
std::tie(result, shaderModule2) = device.createShaderModule({...} /* createInfo temporary */);
|
||||
if (result != vk::Result::eSuccess)
|
||||
{
|
||||
handle error code;
|
||||
cleanup?
|
||||
@ -373,7 +378,7 @@ if (result != VK_SUCCESS)
|
||||
}
|
||||
```
|
||||
|
||||
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 using structured bindings in C++17. They will allow us to get the result with a single line of code:
|
||||
|
||||
```c++
|
||||
auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo temporary */);
|
||||
@ -382,42 +387,46 @@ auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo tem
|
||||
Finally, the last code example is using exceptions and return value transformation. This is the default mode of the API.
|
||||
|
||||
```c++
|
||||
ShaderModule shader1;
|
||||
ShaderModule shader2;
|
||||
try {
|
||||
shader1 = device.createShaderModule({...});
|
||||
shader2 = device.createShaderModule({...});
|
||||
} catch(std::exception const &e) {
|
||||
// handle error and free resources
|
||||
}
|
||||
vk::ShaderModule shader1;
|
||||
vk::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!
|
||||
> [!IMPORTANT]
|
||||
> Vulkan-Hpp does not support RAII style handles, hence you need 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.
|
||||
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:
|
||||
|
||||
```c++
|
||||
std::vector<LayerProperties,Allocator> properties;
|
||||
std::vector<LayerProperties, Allocator> properties;
|
||||
uint32_t propertyCount;
|
||||
Result result;
|
||||
vk::Result result;
|
||||
do
|
||||
{
|
||||
// determine number of elements to query
|
||||
result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, nullptr ) );
|
||||
if ( ( result == Result::eSuccess ) && propertyCount )
|
||||
result = static_cast<vk::Result>(vk::enumerateDeviceLayerProperties(m_physicalDevice, &propertyCount, nullptr));
|
||||
if ((result == vk::Result::eSuccess) && propertyCount)
|
||||
{
|
||||
// allocate memory & query again
|
||||
properties.resize( propertyCount );
|
||||
result = static_cast<Result>( vk::enumerateDeviceLayerProperties( m_physicalDevice, &propertyCount, reinterpret_cast
|
||||
<VkLayerProperties*>( properties.data() ) ) );
|
||||
properties.resize(propertyCount);
|
||||
result = static_cast<vk::Result>(vk::enumerateDeviceLayerProperties(m_physicalDevice, &propertyCount, reinterpret_cast
|
||||
<VkLayerProperties*>(properties.data())));
|
||||
}
|
||||
} while ( result == Result::eIncomplete );
|
||||
} while (result == vk::Result::eIncomplete);
|
||||
// it's possible that the count has changed, start again if properties was not big enough
|
||||
properties.resize(propertyCount);
|
||||
```
|
||||
@ -440,14 +449,13 @@ Note that using `vk::UniqueHandle` comes at a cost since most deleters have to s
|
||||
|
||||
Vulkan-Hpp provides a `vk::SharedHandle<Type>` interface. For each Vulkan handle type `vk::Type` there is a shared handle `vk::SharedType` which will delete the underlying Vulkan resource upon destruction, e.g. `vk::SharedBuffer` is the shared handle for `vk::Buffer`.
|
||||
|
||||
Unlike UniqueHandle, SharedHandle takes shared ownership of the resource as well as its parent. This means that parent handle will not be destroyed until all child resources are deleted. This is useful for resources that are shared between multiple threads or objects.
|
||||
Unlike `vk::UniqueHandle`, `vk::SharedHandle` takes shared ownership of the resource as well as its parent. This means that the parent handle will not be destroyed until all child resources are deleted. This is useful for resources that are shared between multiple threads or objects.
|
||||
|
||||
This mechanism ensures correct destruction order even if the parent SharedHandle is destroyed before its child handle. Otherwise, the handle behaves like `std::shared_ptr`. `vk::SharedInstance` or any of its child object should be last to delete (first created, first in class declaration)
|
||||
This mechanism ensures correct destruction order even if the parent `vk::SharedHandle` is destroyed before its child handle. Otherwise, the handle behaves like `std::shared_ptr`. `vk::SharedInstance` or any of its child object should be last to delete (first created, first in class declaration).
|
||||
|
||||
There are no functions which return a `vk::SharedHandle` directly yet. Instead, you can construct a `vk::SharedHandle` from a `vk::Handle`:
|
||||
|
||||
```c++
|
||||
|
||||
vk::Buffer buffer = device.createBuffer(...);
|
||||
vk::SharedBuffer sharedBuffer(buffer, device); // sharedBuffer now owns the buffer
|
||||
```
|
||||
@ -466,9 +474,9 @@ vk::SwapchainKHR swapchain = device.createSwapchainKHR(...);
|
||||
vk::SharedSwapchainKHR sharedSwapchain(swapchain, device, surface); // sharedSwapchain now owns the swapchain and surface
|
||||
```
|
||||
|
||||
You can create a `vk::SharedHandle` overload for your own handle type or own shared handles by providing several template arguments to SharedHandleBase:
|
||||
You can create a `vk::SharedHandle` overload for your own handle type or own shared handles by providing several template arguments to `SharedHandleBase`:
|
||||
- A handle type
|
||||
- A parent handle type or a header structure, that contains parent
|
||||
- A parent handle type or a header structure, that contains the parent
|
||||
- A class itself for CRTP
|
||||
|
||||
With this, provide a custom static destruction function `internalDestroy`, that takes in a parent handle and a handle to destroy. Don't forget to add a friend declaration for the base class.
|
||||
@ -477,29 +485,29 @@ With this, provide a custom static destruction function `internalDestroy`, that
|
||||
// Example of a custom shared device, that takes in an instance as a parent
|
||||
class shared_handle<VkDevice> : public vk::SharedHandleBase<VkDevice, vk::SharedInstance, shared_handle<VkDevice>>
|
||||
{
|
||||
using base = vk::SharedHandleBase<VkDevice, vk::SharedInstance, shared_handle<VkDevice>>;
|
||||
friend base;
|
||||
using base = vk::SharedHandleBase<VkDevice, vk::SharedInstance, shared_handle<VkDevice>>;
|
||||
friend base;
|
||||
|
||||
public:
|
||||
shared_handle() = default;
|
||||
explicit shared_handle(VkDevice handle, vk::SharedInstance parent) noexcept
|
||||
: base(handle, std::move(parent)) {}
|
||||
shared_handle() = default;
|
||||
explicit shared_handle(VkDevice handle, vk::SharedInstance parent) noexcept
|
||||
: base(handle, std::move(parent)) {}
|
||||
|
||||
const auto& getParent() const noexcept {
|
||||
return getHeader();
|
||||
}
|
||||
const auto& getParent() const noexcept
|
||||
{
|
||||
return getHeader();
|
||||
}
|
||||
|
||||
protected:
|
||||
static void internalDestroy(const vk::SharedInstance& /*control*/, VkDevice handle) noexcept {
|
||||
vkDestroyDevice(handle);
|
||||
}
|
||||
static void internalDestroy(const vk::SharedInstance& /*control*/, VkDevice handle) noexcept
|
||||
{
|
||||
kDestroyDevice(handle);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The API will be extended to provide creation functions in the future.
|
||||
|
||||
|
||||
|
||||
### 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:
|
||||
@ -508,65 +516,64 @@ Sometimes it is required to use `std::vector` with custom allocators. Vulkan-Hpp
|
||||
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:
|
||||
You can also 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:
|
||||
|
||||
```c++
|
||||
MyStatefulCustomAllocator allocator;
|
||||
std::vector<LayerProperties, MyStatefulCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties( 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.
|
||||
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 in the file vulkan_static_assertions.hpp. You might include that file in at least one of your source files. 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.
|
||||
|
||||
There are a couple of static assertions for each handle class and each struct in the file [`vulkan_static_assertions.hpp`](vulkan/vulkan_static_assertions.hpp). You might include that file in at least one of your source files. 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.
|
||||
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.
|
||||
|
||||
```c++
|
||||
// Providing a function pointer resolving vkGetInstanceProcAddr, just the few functions not depending an an instance or a device are fetched
|
||||
vk::DispatchLoaderDynamic dld( getInstanceProcAddr );
|
||||
vk::DispatchLoaderDynamic dld(getInstanceProcAddr);
|
||||
|
||||
// Providing an already created VkInstance and a function pointer resolving vkGetInstanceProcAddr, all functions are fetched
|
||||
vk::DispatchLoaderDynamic dldi( instance, getInstanceProcAddr );
|
||||
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 );
|
||||
vk::DispatchLoaderDynamic dldid( nstance, getInstanceProcAddr, device);
|
||||
|
||||
// Pass dispatch class to function call as last parameter
|
||||
device.getQueue(graphics_queue_family_index, 0, &graphics_queue, dldid);
|
||||
```
|
||||
|
||||
To use the `vk::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 use the `vk::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.
|
||||
Creating a full featured `vk::DispatchLoaderDynamic` is a two- to three-step process, where you have three choices for the first step:
|
||||
1. Before any call into a vk-function you need to initialize the dynamic dispatcher by one of three methods
|
||||
- Let Vulkan-Hpp do all the work by internally using a little helper class `vk::DynamicLoader`:
|
||||
```c++
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init();
|
||||
```
|
||||
- Use your own dynamic loader, which just needs to provide a templated function `getProcAddress` (compare with `vk::DynamicLoader` in vulkan.hpp):
|
||||
- Use your own dynamic loader, which just needs to provide a templated function `getProcAddress` (compare with `vk::DynamicLoader` in `vulkan.hpp`):
|
||||
```c++
|
||||
YourDynamicLoader ydl;
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(ydl);
|
||||
```
|
||||
Note that you need to keep that dynamic loader object alive until after the last call to a vulkan function in your program. For example by making it static, or storing it somewhere globally.
|
||||
- Use your own initial function pointer of type PFN_vkGetInstanceProcAddr:
|
||||
> [!NOTE]
|
||||
> You need to keep that dynamic loader object alive until after the last call to a vulkan function in your program. For example by making it static, or storing it globally.
|
||||
- Use your own initial function pointer of type `PFN_vkGetInstanceProcAddr`:
|
||||
```c++
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = your_own_function_pointer_getter();
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
|
||||
```
|
||||
2. initialize it with a vk::Instance to get all the other function pointers:
|
||||
2. initialize it with a `vk::Instance` to get all the other function pointers:
|
||||
```c++
|
||||
vk::Instance instance = vk::createInstance({}, nullptr);
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);
|
||||
```
|
||||
3. optionally initialize it with a vk::Device to get device-specific function pointers
|
||||
3. optionally initialize it with a `vk::Device` to get device-specific function pointers
|
||||
```c++
|
||||
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
|
||||
assert(!physicalDevices.empty());
|
||||
@ -575,19 +582,19 @@ Creating a full featured `vk::DispatchLoaderDynamic` is a two- to three-step pro
|
||||
```
|
||||
After the second step above, the dispatcher is fully functional. Adding the third step can potentially result in more efficient code. But if you intend to use multiple devices, you could just omit that third step and let the driver do the device-dispatching.
|
||||
|
||||
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.
|
||||
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.
|
||||
For all functions, that `VULKAN_HPP_DEFAULT_DISPATCHER` is the default for the last argument to that function. If 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:
|
||||
`vulkan.hpp` provides a couple of type traits, easing template metaprogramming:
|
||||
- `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::eUint3`2, ...).
|
||||
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`
|
||||
@ -599,7 +606,7 @@ vulkan.hpp provides a couple of type traits, easing template programming:
|
||||
|
||||
### vk::Format trait functions
|
||||
|
||||
With the additional header `vulkan_format_traits.hpp`, a couple of trait functions on `vk::Format` are provided. With C++14 and above, all those functions are marked as `constexpr`, that is with appropriate arguments, they are resolved by the compiler.
|
||||
With the additional header [`vulkan_format_traits.hpp`](vulkan/vulkan_format_traits.hpp), a couple of trait functions on `vk::Format` are provided. With C++14 and above, all those functions are marked as `constexpr`, that is with appropriate arguments, they are resolved at compile time.
|
||||
- `uin8_t blockSize( vk::Format format );`
|
||||
Gets the texel block size of this format in bytes.
|
||||
- `uint8_t texelsPerBlock( vk::Format format );`
|
||||
@ -635,11 +642,11 @@ With the additional header `vulkan_format_traits.hpp`, a couple of trait functio
|
||||
|
||||
### 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.
|
||||
With the additional header [`vulkan_hash.hpp`](vulkan/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.
|
||||
|
||||
### Extension Inspection
|
||||
|
||||
With the additional header `vulkan_extension_inspection.hpp`, some functions to inspect extensions are provided. With C++20 and above, some of those functions are marked as `constexpr`, that is with appropriate arguments, they are resolved by the compiler.
|
||||
With the additional header [`vulkan_extension_inspection.hpp`](vulkan/vulkan_extension_inspection.hpp), some functions to inspect extensions are provided. With C++20 and above, some of those functions are marked as `constexpr`, that is with appropriate arguments, they are resolved at compile time.
|
||||
Each extension is identified by a string holding its name. Note that there exists a define with that name for each extension.
|
||||
Some functions might provide information that depends on the vulkan version. As all functions here work solely on strings, the vulkan versions are encoded by a string beginning with "VK_VERSION_", followed by the major and the minor version, separated by an undersore, like this: "VK_VERSION_1_0".
|
||||
- `std::set<std::string> const & getDeviceExtensions();`
|
||||
@ -680,7 +687,7 @@ Some functions might provide information that depends on the vulkan version. As
|
||||
|
||||
#### Overview
|
||||
|
||||
Vulkan-Hpp provides a [C++ named module](https://en.cppreference.com/w/cpp/language/modules), `vulkan_hpp` in [`vulkan.cppm`](vulkan/vulkan.cppm).
|
||||
Vulkan-Hpp provides a [C++ named module](https://en.cppreference.com/w/cpp/language/modules), `vulkan_hpp` in [`vulkan.cppm`](vulkan/vulkan.cppm).
|
||||
C++ modules are intended to supersede header files. Modules have potential to drastically improve compilation times for large projects, as declarations and definitions may be easily shared across translation units without repeatedly parsing headers.
|
||||
Vulkan-Hpp has some extremely long headers (e.g. [`vulkan_structs.hpp`](vulkan/vulkan_structs.hpp)), and the C++ module is likely to shorten compile times for projects currently using it.
|
||||
|
||||
@ -762,7 +769,7 @@ Furthermore, you may also prefer linking `VulkanHppModule` to just the `Vulkan::
|
||||
target_link_libraries( VulkanHppModule PUBLIC Vulkan::Headers )
|
||||
```
|
||||
|
||||
Finally, supply the macro `VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE` exactly once in your source code, just as in the non-module case. In order to have that macro available, include `<vulkan/vulkan_hpp_macros.hpp>`, a lightweight header providing all Vulkan-Hpp related macros and defines. And as explained above, you need to initialize that dispatcher in two or three steps:
|
||||
Finally, supply the macro `VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE` exactly once in your source code, just as in the non-module case. In order to have that macro available, include [`vulkan_hpp_macros.hpp`](vulkan/vulkan_hpp_macros.hpp), a lightweight header providing all Vulkan-Hpp related macros and defines. And as explained above, you need to initialize that dispatcher in two or three steps:
|
||||
|
||||
```cpp
|
||||
import vulkan_hpp;
|
||||
@ -780,7 +787,7 @@ auto main(int argc, char* const argv[]) -> int
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init();
|
||||
#endif
|
||||
|
||||
auto appInfo = vk::ApplicationInfo( "My App", 1, "My Engine", 1, vk::makeApiVersion( 1, 0, 0, 0 ) );
|
||||
auto appInfo = vk::ApplicationInfo("My App", 1, "My Engine", 1, vk::makeApiVersion(1, 0, 0, 0));
|
||||
// ...
|
||||
}
|
||||
```
|
||||
@ -823,137 +830,136 @@ When you configure your project using CMake, you can enable SAMPLES_BUILD to add
|
||||
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.
|
||||
|
||||
### Compile time issues
|
||||
As vulkan.hpp is pretty big, some compilers might need some time to digest all that stuff. In order to potentially reduce the time needed to compile that header, a couple of defines will be introduced, that allow you to hide certain features. Whenever you don't need that corresponding feature, defining that value might improve your compile time.
|
||||
As `vulkan.hpp` is pretty big, some compilers might need some time to digest all that stuff. In order to potentially reduce the time needed to compile that header, a couple of defines will be introduced, that allow you to hide certain features. Whenever you don't need that corresponding feature, defining that value might improve your compile time.
|
||||
Currently, there are just a couple of such defines:
|
||||
- ```VULKAN_HPP_NO_SPACESHIP_OPERATOR```, which removes the spaceship operator on structures (available with C++20)
|
||||
- ```VULKAN_HPP_NO_TO_STRING```, which removes the various vk::to_string functions on enums and bitmasks.
|
||||
- ```VULKAN_HPP_USE_REFLECT```, this one needs to be defined to use the reflection function on structures. It's very slow to compile, though!
|
||||
- `VULKAN_HPP_NO_SPACESHIP_OPERATOR`, which removes the spaceship operator on structures (available with C++20)
|
||||
- `VULKAN_HPP_NO_TO_STRING`, which removes the various `vk::to_string` functions on enums and bitmasks.
|
||||
- `VULKAN_HPP_USE_REFLECT`, this one needs to be defined to use the reflection function on structures. It's very slow to compile, though!
|
||||
|
||||
## Configuration Options
|
||||
|
||||
There are a couple of defines you can use to control the feature set and behaviour of vulkan.hpp:
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
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;
|
||||
* 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.
|
||||
* the helper class `vk::StructureChain` for compile-time construction of structure chains.
|
||||
|
||||
If this is not defined, you additionally get
|
||||
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
|
||||
* 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.
|
||||
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()```.
|
||||
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_EXPECTED
|
||||
|
||||
When this is not externally defined and VULKAN_HPP_CPP_VERSION is at least 23, VULKAN_HPP_EXPECTED is defined to be std::expected, and VULKAN_HPP_UNEXPECTED is defined to be std::unexpected.
|
||||
When this is not externally defined and `VULKAN_HPP_CPP_VERSION` is at least `23`, `VULKAN_HPP_EXPECTED` is defined to be `std::expected`, and `VULKAN_HPP_UNEXPECTED` is defined to be `std::unexpected`.
|
||||
|
||||
#### 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.
|
||||
By default, the member `m_mask` of the `Flags` class template 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.
|
||||
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.
|
||||
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.
|
||||
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_TO_STRING
|
||||
|
||||
By default, the file vulkan_to_string.hpp is included by vulkan.hpp and provides functions ```vk::to_string``` for enums and bitmasks. If you don't need those functions, you can define VULKAN_HPP_NO_TO_STRING to prevent that inclusion. If you have certain files where you want to use those functions nevertheless, you can explicitly include vulkan_to_string.hpp there.
|
||||
By default, the file [`vulkan_to_string.hpp`](vulkan/vulkan_to_string.hpp) is included by `vulkan.hpp` and provides functions `vk::to_string` for enums and bitmasks. If you don't need those functions, you can define `VULKAN_HPP_NO_TO_STRING` to prevent that inclusion. If you have certain files where you want to use those functions nevertheless, you can explicitly include `vulkan_to_string.hpp` there.
|
||||
|
||||
#### 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.
|
||||
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.
|
||||
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.
|
||||
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_SETTERS```before 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.
|
||||
By defining `VULKAN_HPP_NO_SETTERS` before 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.
|
||||
By defining `VULKAN_HPP_NO_SMART_HANDLE` before including `vulkan.hpp`, the helper class `vk::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.
|
||||
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_NO_WIN32_PROTOTYPES
|
||||
|
||||
By default, if ```VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL``` is enabled on Win32, ```vulkan.hpp``` declares ```HINSTANCE```, ```LoadLibraryA```, and other required symbols. It could cause conflicts with the ```Windows.h``` alternatives, such as ```WindowsHModular```.
|
||||
With this define, you can disable these declarations, but you will have to declare them before the ```vulkan.hpp``` is included.
|
||||
By default, if `VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL` is enabled on Win32, `vulkan.hpp` declares `HINSTANCE`, `LoadLibraryA`, and other required symbols. It could cause conflicts with the `Windows.h` alternatives, such as `WindowsHModular`.
|
||||
With this define, you can disable these declarations, but you will have to declare them before the `vulkan.hpp` is included.
|
||||
|
||||
#### VULKAN_HPP_RAII_NO_EXCEPTIONS
|
||||
|
||||
If both, VULKAN_HPP_NO_EXCEPTIONS and VULKAN_HPP_EXPECTED are defined, the vk::raii-classes don't throw exceptions. That is, the actual constructors are not available, but the creation-functions must be used. For more details have a look at the vk_raii_ProgrammingGuide.md.
|
||||
If both, `VULKAN_HPP_NO_EXCEPTIONS` and `VULKAN_HPP_EXPECTED` are defined, the vk::raii-classes don't throw exceptions. That is, the actual constructors are not available, but the creation-functions must be used. For more details have a look at the [`vk_raii_ProgrammingGuide.md`](vk_raii_ProgrammingGuide.md).
|
||||
|
||||
#### VULKAN_HPP_SMART_HANDLE_IMPLICIT_CAST
|
||||
|
||||
Even though the ```vk::UniqueHandles``` and the ```vk::SharedHandles``` are semantically close to pointers, an implicit cast operator to the underlying ```vk::Handle``` might be handy. You can add that implicit cast operator by defining ```VULKAN_HPP_SMART_HANDLE_IMPLICIT_CAST```.
|
||||
Even though `vk::UniqueHandle` and `vk::SharedHandle` are semantically close to pointers, an implicit cast operator to the underlying `vk::Handle` might be handy. You can add that implicit cast operator by defining `VULKAN_HPP_SMART_HANDLE_IMPLICIT_CAST`.
|
||||
|
||||
#### 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.
|
||||
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 non-dispatchable 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 1```. To disable this feature on 64-bit platforms, ```#define VULKAN_HPP_TYPESAFE_CONVERSION 0```.
|
||||
32-bit vulkan is not typesafe for non-dispatchable 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 1`. To disable this feature on 64-bit platforms, `#define VULKAN_HPP_TYPESAFE_CONVERSION 0`.
|
||||
|
||||
#### VULKAN_HPP_UNEXPECTED
|
||||
|
||||
See ```VULKAN_HPP_EXPECTED```.
|
||||
See `VULKAN_HPP_EXPECTED`.
|
||||
|
||||
#### VULKAN_HPP_USE_REFLECT
|
||||
|
||||
With this define you can include a reflection mechanism on the vk-structures. It adds a function ```reflect``` that returns a tuple-version of the structure. That tuple then could easily be iterated. But at least for now, that feature takes lots of compile-time resources, so currently it is recommended to enable that feature only if you're willing to pay that price.
|
||||
|
||||
With this define you can include a reflection mechanism on the vk-structures. It adds a function `reflect` that returns a tuple-version of the structure. That tuple then could easily be iterated. But at least for now, that feature takes lots of compile-time resources, so currently it is recommended to enable that feature only if you're willing to pay that price.
|
||||
|
||||
## See Also
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user