From 9e95c0072da4e7da9ccbb62b69c3f753715b9978 Mon Sep 17 00:00:00 2001 From: phantom10111 Date: Fri, 15 Apr 2022 11:24:30 +0200 Subject: [PATCH] Make type conversions implicit for dispatchable handles Vulkan handles are not typesafe on 32-bit platforms, but only for non-dispachable handles. Dispatchable handles are opaque struct pointers on all platforms, and thus typesafe. This commit makes all conversions for dispatchable handles implicit, regardless of VULKAN_HPP_TYPESAFE_CONVERSION setting. --- README.md | 4 ++-- VulkanHppGenerator.cpp | 26 ++++++++++++-------- VulkanHppGenerator.hpp | 6 ++++- vulkan/vulkan.hpp | 2 +- vulkan/vulkan_handles.hpp | 50 ++++++++++++++++----------------------- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index ac81501..dab5143 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ There is an additional header named vulkan_raii.hpp generated. That header holds ### C/C++ Interop for Handles -On 64-bit platforms Vulkan-Hpp supports implicit conversions between C++ Vulkan handles and C Vulkan handles. On 32-bit platforms all non-dispatchable handles are defined as `uint64_t`, thus preventing type-conversion checks at compile time which would catch assignments between incompatible handle types.. Due to that Vulkan-Hpp does not enable implicit conversion for 32-bit platforms by default and it is recommended to use a `static_cast` for the conversion like this: `VkDevice = static_cast(cppDevice)` to prevent converting some arbitrary int to a handle or vice versa by accident. If you're developing your code on a 64-bit platform, but want compile your code for a 32-bit platform without adding the explicit casts you can define `VULKAN_HPP_TYPESAFE_CONVERSION` to 1 in your build system or before including `vulkan.hpp`. On 64-bit platforms this define is set to 1 by default and can be set to 0 to disable implicit conversions. +On 64-bit platforms Vulkan-Hpp supports implicit conversions between C++ Vulkan handles and C Vulkan handles. On 32-bit platforms all non-dispatchable handles are defined as `uint64_t`, thus preventing type-conversion checks at compile time which would catch assignments between incompatible handle types. Due to that Vulkan-Hpp does not enable implicit conversion for 32-bit platforms by default and it is recommended to use a `static_cast` for the conversion like this: `VkImage = static_cast(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. ### Flags @@ -641,7 +641,7 @@ With this define you can specify whether the ```DispatchLoaderDynamic``` is impo #### VULKAN_HPP_TYPESAFE_CONVERSION -32-bit vulkan is not typesafe for handles, so we don't allow copy constructors on this platform by default. To enable this feature on 32-bit platforms define ```VULKAN_HPP_TYPESAFE_CONVERSION```. +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_USE_REFLECT diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index 8d756b6..78d82f1 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -89,7 +89,7 @@ const std::set specialPointerTypes = { "Display", "IDirectFB", "wl_ VulkanHppGenerator::VulkanHppGenerator( tinyxml2::XMLDocument const & document ) { // insert the default "handle" without class (for createInstance, and such) - m_handles.insert( std::make_pair( "", HandleData( {}, "", 0 ) ) ); + m_handles.insert( std::make_pair( "", HandleData( {}, "", false, 0 ) ) ); // read the document and check its correctness int line = document.GetLineNum(); @@ -5503,6 +5503,10 @@ std::string VulkanHppGenerator::generateHandle( std::pairfirst, valueIt->name, false, m_tags ) }, - { "usingAlias", usingAlias } } ); + { "usingAlias", usingAlias }, + { "typesafeExplicitKeyword", typesafeExplicitKeyword }, + { "typesafeConversionConditional", typesafeConversionConditional }, + { "typesafeConversionConditionalEnd", typesafeConversionConditionalEnd } } ); } listedHandles.insert( handleData.first ); @@ -13703,6 +13708,7 @@ void VulkanHppGenerator::readTypesTypeHandle( tinyxml2::XMLElement const * eleme NameData nameData; TypeInfo typeInfo; std::tie( nameData, typeInfo ) = readNameAndType( element ); + const bool isDispatchable = typeInfo.type == "VK_DEFINE_HANDLE"; check( beginsWith( nameData.name, "Vk" ), line, "name <" + nameData.name + "> does not begin with " ); check( nameData.arraySizes.empty(), line, "name <" + nameData.name + "> with unsupported arraySizes" ); @@ -13714,7 +13720,7 @@ void VulkanHppGenerator::readTypesTypeHandle( tinyxml2::XMLElement const * eleme check( !objTypeEnum.empty(), line, "handle <" + nameData.name + "> does not specify attribute \"objtypeenum\"" ); check( parent.find( ',' ) == std::string::npos, line, "mulitple parents specified for handle <" + nameData.name + ">" ); - check( m_handles.insert( std::make_pair( nameData.name, HandleData( parent, objTypeEnum, line ) ) ).second, + check( m_handles.insert( std::make_pair( nameData.name, HandleData( parent, objTypeEnum, isDispatchable, line ) ) ).second, line, "handle <" + nameData.name + "> already specified" ); check( m_types.insert( std::make_pair( nameData.name, TypeCategory::Handle ) ).second, line, "handle <" + nameData.name + "> already specified as a type" ); @@ -16900,7 +16906,7 @@ namespace VULKAN_HPP_NAMESPACE " , \"Wrong VK_HEADER_VERSION!\" );\n" "\n"; str += - "// 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default.\n" + "// 32-bit vulkan is not typesafe for non-dispatchable handles, so don't allow copy constructors on this platform by default.\n" "// To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION\n" + generator.getTypesafeCheck() + "\n" diff --git a/VulkanHppGenerator.hpp b/VulkanHppGenerator.hpp index a2d8b3d..f577014 100644 --- a/VulkanHppGenerator.hpp +++ b/VulkanHppGenerator.hpp @@ -272,7 +272,10 @@ private: struct HandleData { - HandleData( std::string const & p, std::string const & objType, int line ) : objTypeEnum( objType ), parent( p ), xmlLine( line ) {} + HandleData( std::string const & p, std::string const & objType, bool isDispatchable, int line ) + : objTypeEnum( objType ), parent( p ), isDispatchable( isDispatchable ), xmlLine( line ) + { + } std::string alias; std::set childrenHandles; @@ -282,6 +285,7 @@ private: std::string objTypeEnum; std::string parent; std::set secondLevelCommands; + bool isDispatchable; int xmlLine; // RAII data diff --git a/vulkan/vulkan.hpp b/vulkan/vulkan.hpp index c10a4f8..21b5bf7 100644 --- a/vulkan/vulkan.hpp +++ b/vulkan/vulkan.hpp @@ -121,7 +121,7 @@ extern "C" __declspec( dllimport ) FARPROC __stdcall GetProcAddress( HINSTANCE h static_assert( VK_HEADER_VERSION == 211, "Wrong VK_HEADER_VERSION!" ); -// 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default. +// 32-bit vulkan is not typesafe for non-dispatchable handles, so don't allow copy constructors on this platform by default. // To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION #if ( VK_USE_64_BIT_PTR_DEFINES == 1 ) # if !defined( VULKAN_HPP_TYPESAFE_CONVERSION ) diff --git a/vulkan/vulkan_handles.hpp b/vulkan/vulkan_handles.hpp index 6a856c5..c5d6a88 100644 --- a/vulkan/vulkan_handles.hpp +++ b/vulkan/vulkan_handles.hpp @@ -3051,17 +3051,15 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCommandBuffer; public: - VULKAN_HPP_CONSTEXPR CommandBuffer() = default; - VULKAN_HPP_CONSTEXPR CommandBuffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} - VULKAN_HPP_TYPESAFE_EXPLICIT CommandBuffer( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT : m_commandBuffer( commandBuffer ) {} + VULKAN_HPP_CONSTEXPR CommandBuffer() = default; + VULKAN_HPP_CONSTEXPR CommandBuffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} + CommandBuffer( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT : m_commandBuffer( commandBuffer ) {} -#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) CommandBuffer & operator=( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT { m_commandBuffer = commandBuffer; return *this; } -#endif CommandBuffer & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT { @@ -4822,7 +4820,7 @@ namespace VULKAN_HPP_NAMESPACE Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ - VULKAN_HPP_TYPESAFE_EXPLICIT operator VkCommandBuffer() const VULKAN_HPP_NOEXCEPT + operator VkCommandBuffer() const VULKAN_HPP_NOEXCEPT { return m_commandBuffer; } @@ -6628,17 +6626,15 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eQueue; public: - VULKAN_HPP_CONSTEXPR Queue() = default; - VULKAN_HPP_CONSTEXPR Queue( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} - VULKAN_HPP_TYPESAFE_EXPLICIT Queue( VkQueue queue ) VULKAN_HPP_NOEXCEPT : m_queue( queue ) {} + VULKAN_HPP_CONSTEXPR Queue() = default; + VULKAN_HPP_CONSTEXPR Queue( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} + Queue( VkQueue queue ) VULKAN_HPP_NOEXCEPT : m_queue( queue ) {} -#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) Queue & operator=( VkQueue queue ) VULKAN_HPP_NOEXCEPT { m_queue = queue; return *this; } -#endif Queue & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT { @@ -6812,7 +6808,7 @@ namespace VULKAN_HPP_NAMESPACE getCheckpointData2NV( CheckpointData2NVAllocator & checkpointData2NVAllocator, Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const; #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ - VULKAN_HPP_TYPESAFE_EXPLICIT operator VkQueue() const VULKAN_HPP_NOEXCEPT + operator VkQueue() const VULKAN_HPP_NOEXCEPT { return m_queue; } @@ -7120,17 +7116,15 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDevice; public: - VULKAN_HPP_CONSTEXPR Device() = default; - VULKAN_HPP_CONSTEXPR Device( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} - VULKAN_HPP_TYPESAFE_EXPLICIT Device( VkDevice device ) VULKAN_HPP_NOEXCEPT : m_device( device ) {} + VULKAN_HPP_CONSTEXPR Device() = default; + VULKAN_HPP_CONSTEXPR Device( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} + Device( VkDevice device ) VULKAN_HPP_NOEXCEPT : m_device( device ) {} -#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) Device & operator=( VkDevice device ) VULKAN_HPP_NOEXCEPT { m_device = device; return *this; } -#endif Device & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT { @@ -11224,7 +11218,7 @@ namespace VULKAN_HPP_NAMESPACE Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT; #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ - VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDevice() const VULKAN_HPP_NOEXCEPT + operator VkDevice() const VULKAN_HPP_NOEXCEPT { return m_device; } @@ -11372,17 +11366,15 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePhysicalDevice; public: - VULKAN_HPP_CONSTEXPR PhysicalDevice() = default; - VULKAN_HPP_CONSTEXPR PhysicalDevice( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} - VULKAN_HPP_TYPESAFE_EXPLICIT PhysicalDevice( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT : m_physicalDevice( physicalDevice ) {} + VULKAN_HPP_CONSTEXPR PhysicalDevice() = default; + VULKAN_HPP_CONSTEXPR PhysicalDevice( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} + PhysicalDevice( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT : m_physicalDevice( physicalDevice ) {} -#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) PhysicalDevice & operator=( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT { m_physicalDevice = physicalDevice; return *this; } -#endif PhysicalDevice & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT { @@ -12619,7 +12611,7 @@ namespace VULKAN_HPP_NAMESPACE # endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ - VULKAN_HPP_TYPESAFE_EXPLICIT operator VkPhysicalDevice() const VULKAN_HPP_NOEXCEPT + operator VkPhysicalDevice() const VULKAN_HPP_NOEXCEPT { return m_physicalDevice; } @@ -12695,17 +12687,15 @@ namespace VULKAN_HPP_NAMESPACE VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eInstance; public: - VULKAN_HPP_CONSTEXPR Instance() = default; - VULKAN_HPP_CONSTEXPR Instance( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} - VULKAN_HPP_TYPESAFE_EXPLICIT Instance( VkInstance instance ) VULKAN_HPP_NOEXCEPT : m_instance( instance ) {} + VULKAN_HPP_CONSTEXPR Instance() = default; + VULKAN_HPP_CONSTEXPR Instance( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} + Instance( VkInstance instance ) VULKAN_HPP_NOEXCEPT : m_instance( instance ) {} -#if defined( VULKAN_HPP_TYPESAFE_CONVERSION ) Instance & operator=( VkInstance instance ) VULKAN_HPP_NOEXCEPT { m_instance = instance; return *this; } -#endif Instance & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT { @@ -13308,7 +13298,7 @@ namespace VULKAN_HPP_NAMESPACE # endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ #endif /*VK_USE_PLATFORM_SCREEN_QNX*/ - VULKAN_HPP_TYPESAFE_EXPLICIT operator VkInstance() const VULKAN_HPP_NOEXCEPT + operator VkInstance() const VULKAN_HPP_NOEXCEPT { return m_instance; }