Skip to content

Commit

Permalink
Add support of noexcept-path for vk::raii classes (#1742)
Browse files Browse the repository at this point in the history
  • Loading branch information
asuessenbach authored Jan 2, 2024
1 parent 2cc4dbd commit 197017e
Show file tree
Hide file tree
Showing 21 changed files with 9,802 additions and 8,188 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,10 @@ This either selects the dynamic (when it's 1) or the static (when it's not 1) Di

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.

#### 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.
Expand Down Expand Up @@ -889,6 +893,10 @@ By defining ```VULKAN_HPP_NO_SMART_HANDLE``` before including vulkan.hpp, the he

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_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.

#### 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.
Expand All @@ -897,6 +905,10 @@ With this define you can specify whether the ```DispatchLoaderDynamic``` is impo

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```.

#### VULKAN_HPP_UNEXPECTED

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.
Expand Down
1,050 changes: 396 additions & 654 deletions VulkanHppGenerator.cpp

Large diffs are not rendered by default.

85 changes: 36 additions & 49 deletions VulkanHppGenerator.hpp

Large diffs are not rendered by default.

17 changes: 7 additions & 10 deletions snippets/includes.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
#ifndef VULKAN_HPP
#define VULKAN_HPP

#include <algorithm>
#include <array> // ArrayWrapperND
#include <string> // std::string
#include <string.h> // strnlen
#include <array> // ArrayWrapperND
#include <string.h> // strnlen
#include <string> // std::string
#include <vulkan/${vulkan_h}>
#include <vulkan/vulkan_hpp_macros.hpp>

#if 17 <= VULKAN_HPP_CPP_VERSION
# include <string_view> // std::string_view
# include <string_view>
#endif

#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE )
# include <tuple> // std::tie
# include <vector> // std::vector
# include <tuple> // std::tie
# include <vector> // std::vector
#endif

#if !defined( VULKAN_HPP_NO_EXCEPTIONS )
Expand All @@ -26,7 +23,7 @@
#endif

#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL == 1
# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined(__Fuchsia__)
# if defined( __unix__ ) || defined( __APPLE__ ) || defined( __QNX__ ) || defined( __Fuchsia__ )
# include <dlfcn.h>
# elif defined( _WIN32 )
typedef struct HINSTANCE__ * HINSTANCE;
Expand Down
44 changes: 31 additions & 13 deletions snippets/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
#endif

#if !defined( VULKAN_HPP_STATIC_ASSERT )
# define VULKAN_HPP_STATIC_ASSERT static_assert
# define VULKAN_HPP_STATIC_ASSERT static_assert
#endif

#if !defined( VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL )
Expand All @@ -85,8 +85,8 @@
# endif
#endif

#if defined(__GNUC__)
# define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ )
#if defined( __GNUC__ )
# define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ )
#endif

#if !defined( VULKAN_HPP_HAS_UNRESTRICTED_UNIONS )
Expand Down Expand Up @@ -134,7 +134,7 @@
# else
# define VULKAN_HPP_CONSTEXPR_14
# endif
# if ( 201907 <= __cpp_constexpr ) && ( !defined(__GNUC__) || ( 110400 < GCC_VERSION ) )
# if ( 201907 <= __cpp_constexpr ) && ( !defined( __GNUC__ ) || ( 110400 < GCC_VERSION ) )
# define VULKAN_HPP_CONSTEXPR_20 constexpr
# else
# define VULKAN_HPP_CONSTEXPR_20
Expand Down Expand Up @@ -194,12 +194,12 @@
#define VULKAN_HPP_STRINGIFY( text ) VULKAN_HPP_STRINGIFY2( text )
#define VULKAN_HPP_NAMESPACE_STRING VULKAN_HPP_STRINGIFY( VULKAN_HPP_NAMESPACE )

#if !defined(VULKAN_HPP_DISPATCH_LOADER_DYNAMIC)
# if defined( VK_NO_PROTOTYPES )
# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
# else
# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 0
# endif
#if !defined( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC )
# if defined( VK_NO_PROTOTYPES )
# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
# else
# define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 0
# endif
#endif

#if !defined( VULKAN_HPP_STORAGE_API )
Expand Down Expand Up @@ -233,11 +233,12 @@ namespace VULKAN_HPP_NAMESPACE
#if !defined( VULKAN_HPP_DEFAULT_DISPATCHER )
# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
# define VULKAN_HPP_DEFAULT_DISPATCHER ::VULKAN_HPP_NAMESPACE::defaultDispatchLoaderDynamic
# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE \
namespace VULKAN_HPP_NAMESPACE \
{ \
# define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE \
namespace VULKAN_HPP_NAMESPACE \
{ \
VULKAN_HPP_STORAGE_API ::VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic defaultDispatchLoaderDynamic; \
}

namespace VULKAN_HPP_NAMESPACE
{
extern VULKAN_HPP_STORAGE_API VULKAN_HPP_NAMESPACE::DispatchLoaderDynamic defaultDispatchLoaderDynamic;
Expand Down Expand Up @@ -265,3 +266,20 @@ namespace VULKAN_HPP_NAMESPACE
# define VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT = nullptr
# define VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT = VULKAN_HPP_DEFAULT_DISPATCHER
#endif

#if !defined( VULKAN_HPP_EXPECTED ) && ( 23 <= VULKAN_HPP_CPP_VERSION ) && defined( __cpp_lib_expected )
# include <expected>
# define VULKAN_HPP_EXPECTED std::expected
# define VULKAN_HPP_UNEXPECTED std::unexpected
#endif

#if !defined( VULKAN_HPP_RAII_NAMESPACE )
# define VULKAN_HPP_RAII_NAMESPACE raii
#endif

#if defined( VULKAN_HPP_NO_EXCEPTIONS ) && defined( VULKAN_HPP_EXPECTED )
# define VULKAN_HPP_RAII_NO_EXCEPTIONS
# define VULKAN_HPP_RAII_CREATE_NOEXCEPT noexcept
#else
# define VULKAN_HPP_RAII_CREATE_NOEXCEPT
#endif
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ add_subdirectory( FormatTraits )
add_subdirectory( Handles )
add_subdirectory( Hash )
add_subdirectory( NoExceptions )
if( ( "cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES ) AND NOT ( ( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" ) AND ( CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15.0 ) ) )
# This test is for C++23 only... but clang++13 and clang++14 seem to have a problem with it
add_subdirectory( NoExceptionsRAII )
endif()
add_subdirectory( StridedArrayProxy )
add_subdirectory( StructureChain )
add_subdirectory( UniqueHandle )
Expand Down
19 changes: 19 additions & 0 deletions tests/NoExceptionsRAII/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

vulkan_hpp__setup_test( NAME NoExceptionsRAII LIBRARIES utils CXX_STANDARD 23)

if( UNIX )
target_link_libraries( NoExceptionsRAII PRIVATE ${CMAKE_DL_LIBS} )
endif ()
75 changes: 75 additions & 0 deletions tests/NoExceptionsRAII/NoExceptionsRAII.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// VulkanHpp Samples : NoExceptionsRAII
// Compile test with VULKAN_HPP_NO_EXCEPTIONS set and using raii-classes
// Note: this is _no_ functional test!! Don't ever code this way!!

#define VULKAN_HPP_NO_EXCEPTIONS

// for this test, we need to include vulkan_hpp_macros.hpp first to determine if VULKAN_HPP_RAII_NO_EXCEPTIONS is defined in this context
#include <vulkan/vulkan_hpp_macros.hpp>

// only if VULKAN_HPP_RAII_NO_EXCEPTIONS really is defined, this test is meaningfull and needs to compile and run.
#if defined( VULKAN_HPP_RAII_NO_EXCEPTIONS )
#include <vulkan/vulkan_raii.hpp>

static char const * AppName = "NoExceptions";
static char const * EngineName = "Vulkan.hpp";
#endif

int main( int /*argc*/, char ** /*argv*/ )
{
#if defined( VULKAN_HPP_RAII_NO_EXCEPTIONS )
vk::raii::Context context;

vk::ApplicationInfo appInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
auto instance = context.createInstance( { {}, &appInfo } );
assert( instance.has_value() );

auto physicalDevices = instance->enumeratePhysicalDevices();
assert( physicalDevices.has_value() );
auto physicalDevice = std::move( physicalDevices->front() );

// get the QueueFamilyProperties of the first PhysicalDevice
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();

// get the first index into queueFamiliyProperties which supports graphics
size_t graphicsQueueFamilyIndex =
std::distance( queueFamilyProperties.begin(),
std::find_if( queueFamilyProperties.begin(),
queueFamilyProperties.end(),
[]( vk::QueueFamilyProperties const & qfp ) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; } ) );
assert( graphicsQueueFamilyIndex < queueFamilyProperties.size() );

// create a Device
float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo( vk::DeviceQueueCreateFlags(), static_cast<uint32_t>( graphicsQueueFamilyIndex ), 1, &queuePriority );
auto device = physicalDevice.createDevice( vk::DeviceCreateInfo( vk::DeviceCreateFlags(), deviceQueueCreateInfo ) );
assert( device.has_value() );

// create a CommandPool to allocate a CommandBuffer from
auto commandPool =
device->createCommandPool( vk::CommandPoolCreateInfo( vk::CommandPoolCreateFlags(), deviceQueueCreateInfo.queueFamilyIndex ) );
assert( commandPool.has_value() );

// allocate a CommandBuffer from the CommandPool
auto commandBuffers = device->allocateCommandBuffers( vk::CommandBufferAllocateInfo( **commandPool, vk::CommandBufferLevel::ePrimary, 1 ) );
assert( commandBuffers.has_value() );

auto commandBuffer = std::move( commandBuffers->front() );
#endif

return 0;
}
20 changes: 18 additions & 2 deletions vk_raii_ProgrammingGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ you would create a `vk::raii::Device`

That `vk::raii::Device` is automatically destroyed, when its scope is left.

Alternatively, you can use a creation function to create a `vk::raii::Device`:

// create a vk::raii::Device, given a vk::raii::PhysicalDevice physicalDevice and a vk::DeviceCreateInfo deviceCreateInfo
vk::raii::Device device = physicalDevice.createDevice( deviceCreateInfo );

Finally, if you have defined `VULKAN_HPP_NO_EXCPETIONS` and compile for at least C++23, the constructors as described above are not available (they would potentially throw an exception which is not allowed then) but you have to use the construction functions. Those functions then do not return the created object, but a `std::expected<vk::raii::Object, vk::Result>`:

// create a vk::raii::Device, given a vk::raii::PhysicalDevice physicalDevice and a vk::DeviceCreateInfo deviceCreateInfo
// when VULKAN_HPP_NO_EXCPETIONS is defined and your using at least C++23
auto deviceExpected = physicalDevice.createDevice( deviceCreateInfo );
if ( deviceExpected.has_value() )
{
device = std::move( *deviceExpected );
}

In the code snippets in this text, I will consistently use the constructor-approach.


Other than the `vk::Device`, you can assign the `vk::raii::Device` to a smart pointer:

// create a smart-pointer to a vk::raii::Device, given a smart-pointer to a vk::raii::PhysicalDevice pPhysicalDevice and a vk::DeviceCreateInfo deviceCreateInfo
Expand Down Expand Up @@ -83,8 +101,6 @@ The `vk::raii::Instance` now holds all the instance-related functions. For examp
// get all vk::PhysicalDeviceGroupProperties from a vk::raii::Instance instance
std::vector<vk::PhysicalDeviceGroupProperties> physicalDeviceGroupProperties = instance.enumeratePhysicalDeviceGroups();

Actually, "all the instance-related functions", as stated above, might be a bit misleading. There are just very few public functions available with the `vk::raii::Instance`, as most of the instance-related functions are creation functions that are not wrapped publicly but used internally when instantiating other vk::raii-objects.

### 02 Enumerate the vk::raii::PhysicalDevices

Enumerating the physical devices of an instance is slightly different in vk::raii namespace as you might be used to from the vk-namespace or the pure C-API. As there might be multiple physical devices attached, you would instantiate a `vk::raii::PhysicalDevices` (note the trailing 's' here!), which essentially is a `std::vector` of `vk::raii::PhysicalDevice`s (note the trailing 's' here!):
Expand Down
2 changes: 1 addition & 1 deletion vulkan/vulkan.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -4616,7 +4616,7 @@ export namespace VULKAN_HPP_NAMESPACE
using VULKAN_HPP_NAMESPACE::isObsoletedExtension;
using VULKAN_HPP_NAMESPACE::isPromotedExtension;

#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE ) && !defined( VULKAN_HPP_NO_EXCEPTIONS )
#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE )
namespace VULKAN_HPP_RAII_NAMESPACE
{
//======================
Expand Down
4 changes: 2 additions & 2 deletions vulkan/vulkan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <vulkan/vulkan_hpp_macros.hpp>

#if 17 <= VULKAN_HPP_CPP_VERSION
# include <string_view> // std::string_view
# include <string_view>
#endif

#if !defined( VULKAN_HPP_DISABLE_ENHANCED_MODE )
Expand Down Expand Up @@ -16303,7 +16303,7 @@ namespace VULKAN_HPP_NAMESPACE
# elif defined( __APPLE__ )
m_library = dlopen( "libvulkan.dylib", RTLD_NOW | RTLD_LOCAL );
# elif defined( _WIN32 )
m_library = ::LoadLibraryA( "vulkan-1.dll" );
m_library = ::LoadLibraryA( "vulkan-1.dll" );
# else
# error unsupported platform
# endif
Expand Down
Loading

0 comments on commit 197017e

Please sign in to comment.