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.
This commit is contained in:
phantom10111 2022-04-15 11:24:30 +02:00
parent 25256d1d59
commit 9e95c0072d
5 changed files with 44 additions and 44 deletions

View File

@ -74,7 +74,7 @@ There is an additional header named vulkan_raii.hpp generated. That header holds
### C/C++ Interop for Handles ### C/C++ Interop for Handles
On 64-bit platforms Vulkan-Hpp supports implicit conversions between C++ Vulkan handles and C Vulkan handles. On 32-bit platforms all non-dispatchable handles are defined as `uint64_t`, thus preventing type-conversion checks at compile time which would catch assignments between incompatible handle types.. Due to that Vulkan-Hpp does not enable implicit conversion for 32-bit platforms by default and it is recommended to use a `static_cast` for the conversion like this: `VkDevice = static_cast<VkDevice>(cppDevice)` to prevent converting some arbitrary int to a handle or vice versa by accident. If you're developing your code on a 64-bit platform, but want compile your code for a 32-bit platform without adding the explicit casts you can define `VULKAN_HPP_TYPESAFE_CONVERSION` to 1 in your build system or before including `vulkan.hpp`. On 64-bit platforms this define is set to 1 by default and can be set to 0 to disable implicit conversions. On 64-bit platforms Vulkan-Hpp supports implicit conversions between C++ Vulkan handles and C Vulkan handles. On 32-bit platforms all non-dispatchable handles are defined as `uint64_t`, thus preventing type-conversion checks at compile time which would catch assignments between incompatible handle types. Due to that Vulkan-Hpp does not enable implicit conversion for 32-bit platforms by default and it is recommended to use a `static_cast` for the conversion like this: `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.
### Flags ### Flags
@ -641,7 +641,7 @@ With this define you can specify whether the ```DispatchLoaderDynamic``` is impo
#### VULKAN_HPP_TYPESAFE_CONVERSION #### 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 #### VULKAN_HPP_USE_REFLECT

View File

@ -89,7 +89,7 @@ const std::set<std::string> specialPointerTypes = { "Display", "IDirectFB", "wl_
VulkanHppGenerator::VulkanHppGenerator( tinyxml2::XMLDocument const & document ) VulkanHppGenerator::VulkanHppGenerator( tinyxml2::XMLDocument const & document )
{ {
// insert the default "handle" without class (for createInstance, and such) // 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 // read the document and check its correctness
int line = document.GetLineNum(); int line = document.GetLineNum();
@ -5503,6 +5503,10 @@ std::string VulkanHppGenerator::generateHandle( std::pair<std::string, HandleDat
usingAlias += " using " + stripPrefix( handleData.second.alias, "Vk" ) + " = " + stripPrefix( handleData.first, "Vk" ) + ";\n"; usingAlias += " using " + stripPrefix( handleData.second.alias, "Vk" ) + " = " + stripPrefix( handleData.first, "Vk" ) + ";\n";
} }
const std::string typesafeExplicitKeyword = handleData.second.isDispatchable ? "" : "VULKAN_HPP_TYPESAFE_EXPLICIT ";
const std::string typesafeConversionConditional = handleData.second.isDispatchable ? "" : "#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)\n";
const std::string typesafeConversionConditionalEnd = handleData.second.isDispatchable ? "" : "#endif\n";
static const std::string templateString = R"( static const std::string templateString = R"(
${enter} class ${className} ${enter} class ${className}
{ {
@ -5517,18 +5521,16 @@ ${enter} class ${className}
VULKAN_HPP_CONSTEXPR ${className}() = default; VULKAN_HPP_CONSTEXPR ${className}() = default;
VULKAN_HPP_CONSTEXPR ${className}( std::nullptr_t ) VULKAN_HPP_NOEXCEPT VULKAN_HPP_CONSTEXPR ${className}( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
{} {}
VULKAN_HPP_TYPESAFE_EXPLICIT ${className}( Vk${className} ${memberName} ) VULKAN_HPP_NOEXCEPT ${typesafeExplicitKeyword}${className}( Vk${className} ${memberName} ) VULKAN_HPP_NOEXCEPT
: m_${memberName}( ${memberName} ) : m_${memberName}( ${memberName} )
{} {}
#if defined(VULKAN_HPP_TYPESAFE_CONVERSION) ${typesafeConversionConditional} ${className} & operator=(Vk${className} ${memberName}) VULKAN_HPP_NOEXCEPT
${className} & operator=(Vk${className} ${memberName}) VULKAN_HPP_NOEXCEPT
{ {
m_${memberName} = ${memberName}; m_${memberName} = ${memberName};
return *this; return *this;
} }
#endif ${typesafeConversionConditionalEnd}
${className} & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT ${className} & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
{ {
m_${memberName} = {}; m_${memberName} = {};
@ -5554,7 +5556,7 @@ ${enter} class ${className}
} }
#endif #endif
${commands} ${commands}
VULKAN_HPP_TYPESAFE_EXPLICIT operator Vk${className}() const VULKAN_HPP_NOEXCEPT ${typesafeExplicitKeyword}operator Vk${className}() const VULKAN_HPP_NOEXCEPT
{ {
return m_${memberName}; return m_${memberName};
} }
@ -5599,7 +5601,10 @@ ${usingAlias}${leave})";
{ "leave", leave }, { "leave", leave },
{ "memberName", startLowerCase( stripPrefix( handleData.first, "Vk" ) ) }, { "memberName", startLowerCase( stripPrefix( handleData.first, "Vk" ) ) },
{ "objTypeEnum", generateEnumValueName( enumIt->first, valueIt->name, false, m_tags ) }, { "objTypeEnum", generateEnumValueName( enumIt->first, valueIt->name, false, m_tags ) },
{ "usingAlias", usingAlias } } ); { "usingAlias", usingAlias },
{ "typesafeExplicitKeyword", typesafeExplicitKeyword },
{ "typesafeConversionConditional", typesafeConversionConditional },
{ "typesafeConversionConditionalEnd", typesafeConversionConditionalEnd } } );
} }
listedHandles.insert( handleData.first ); listedHandles.insert( handleData.first );
@ -13703,6 +13708,7 @@ void VulkanHppGenerator::readTypesTypeHandle( tinyxml2::XMLElement const * eleme
NameData nameData; NameData nameData;
TypeInfo typeInfo; TypeInfo typeInfo;
std::tie( nameData, typeInfo ) = readNameAndType( element ); 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 <Vk>" ); check( beginsWith( nameData.name, "Vk" ), line, "name <" + nameData.name + "> does not begin with <Vk>" );
check( nameData.arraySizes.empty(), line, "name <" + nameData.name + "> with unsupported arraySizes" ); 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( !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( 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, line,
"handle <" + nameData.name + "> already specified" ); "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" ); 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" " , \"Wrong VK_HEADER_VERSION!\" );\n"
"\n"; "\n";
str += 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" + "// To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION\n" +
generator.getTypesafeCheck() + generator.getTypesafeCheck() +
"\n" "\n"

View File

@ -272,7 +272,10 @@ private:
struct HandleData 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::string alias;
std::set<std::string> childrenHandles; std::set<std::string> childrenHandles;
@ -282,6 +285,7 @@ private:
std::string objTypeEnum; std::string objTypeEnum;
std::string parent; std::string parent;
std::set<std::string> secondLevelCommands; std::set<std::string> secondLevelCommands;
bool isDispatchable;
int xmlLine; int xmlLine;
// RAII data // RAII data

View File

@ -121,7 +121,7 @@ extern "C" __declspec( dllimport ) FARPROC __stdcall GetProcAddress( HINSTANCE h
static_assert( VK_HEADER_VERSION == 211, "Wrong VK_HEADER_VERSION!" ); 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 // To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION
#if ( VK_USE_64_BIT_PTR_DEFINES == 1 ) #if ( VK_USE_64_BIT_PTR_DEFINES == 1 )
# if !defined( VULKAN_HPP_TYPESAFE_CONVERSION ) # if !defined( VULKAN_HPP_TYPESAFE_CONVERSION )

View File

@ -3051,17 +3051,15 @@ namespace VULKAN_HPP_NAMESPACE
VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCommandBuffer; VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eCommandBuffer;
public: public:
VULKAN_HPP_CONSTEXPR CommandBuffer() = default; VULKAN_HPP_CONSTEXPR CommandBuffer() = default;
VULKAN_HPP_CONSTEXPR CommandBuffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} VULKAN_HPP_CONSTEXPR CommandBuffer( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT CommandBuffer( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT : m_commandBuffer( commandBuffer ) {} CommandBuffer( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT : m_commandBuffer( commandBuffer ) {}
#if defined( VULKAN_HPP_TYPESAFE_CONVERSION )
CommandBuffer & operator=( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT CommandBuffer & operator=( VkCommandBuffer commandBuffer ) VULKAN_HPP_NOEXCEPT
{ {
m_commandBuffer = commandBuffer; m_commandBuffer = commandBuffer;
return *this; return *this;
} }
#endif
CommandBuffer & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT 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; Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ #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; return m_commandBuffer;
} }
@ -6628,17 +6626,15 @@ namespace VULKAN_HPP_NAMESPACE
VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eQueue; VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eQueue;
public: public:
VULKAN_HPP_CONSTEXPR Queue() = default; VULKAN_HPP_CONSTEXPR Queue() = default;
VULKAN_HPP_CONSTEXPR Queue( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} VULKAN_HPP_CONSTEXPR Queue( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT Queue( VkQueue queue ) VULKAN_HPP_NOEXCEPT : m_queue( queue ) {} Queue( VkQueue queue ) VULKAN_HPP_NOEXCEPT : m_queue( queue ) {}
#if defined( VULKAN_HPP_TYPESAFE_CONVERSION )
Queue & operator=( VkQueue queue ) VULKAN_HPP_NOEXCEPT Queue & operator=( VkQueue queue ) VULKAN_HPP_NOEXCEPT
{ {
m_queue = queue; m_queue = queue;
return *this; return *this;
} }
#endif
Queue & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT 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; getCheckpointData2NV( CheckpointData2NVAllocator & checkpointData2NVAllocator, Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ #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; return m_queue;
} }
@ -7120,17 +7116,15 @@ namespace VULKAN_HPP_NAMESPACE
VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDevice; VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eDevice;
public: public:
VULKAN_HPP_CONSTEXPR Device() = default; VULKAN_HPP_CONSTEXPR Device() = default;
VULKAN_HPP_CONSTEXPR Device( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} VULKAN_HPP_CONSTEXPR Device( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT Device( VkDevice device ) VULKAN_HPP_NOEXCEPT : m_device( device ) {} Device( VkDevice device ) VULKAN_HPP_NOEXCEPT : m_device( device ) {}
#if defined( VULKAN_HPP_TYPESAFE_CONVERSION )
Device & operator=( VkDevice device ) VULKAN_HPP_NOEXCEPT Device & operator=( VkDevice device ) VULKAN_HPP_NOEXCEPT
{ {
m_device = device; m_device = device;
return *this; return *this;
} }
#endif
Device & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT 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; Dispatch const & d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT ) const VULKAN_HPP_NOEXCEPT;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ #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; return m_device;
} }
@ -11372,17 +11366,15 @@ namespace VULKAN_HPP_NAMESPACE
VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePhysicalDevice; VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::ePhysicalDevice;
public: public:
VULKAN_HPP_CONSTEXPR PhysicalDevice() = default; VULKAN_HPP_CONSTEXPR PhysicalDevice() = default;
VULKAN_HPP_CONSTEXPR PhysicalDevice( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} VULKAN_HPP_CONSTEXPR PhysicalDevice( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT PhysicalDevice( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT : m_physicalDevice( physicalDevice ) {} PhysicalDevice( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT : m_physicalDevice( physicalDevice ) {}
#if defined( VULKAN_HPP_TYPESAFE_CONVERSION )
PhysicalDevice & operator=( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT PhysicalDevice & operator=( VkPhysicalDevice physicalDevice ) VULKAN_HPP_NOEXCEPT
{ {
m_physicalDevice = physicalDevice; m_physicalDevice = physicalDevice;
return *this; return *this;
} }
#endif
PhysicalDevice & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT PhysicalDevice & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
{ {
@ -12619,7 +12611,7 @@ namespace VULKAN_HPP_NAMESPACE
# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ # endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
#endif /*VK_USE_PLATFORM_SCREEN_QNX*/ #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; return m_physicalDevice;
} }
@ -12695,17 +12687,15 @@ namespace VULKAN_HPP_NAMESPACE
VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eInstance; VULKAN_HPP_NAMESPACE::DebugReportObjectTypeEXT::eInstance;
public: public:
VULKAN_HPP_CONSTEXPR Instance() = default; VULKAN_HPP_CONSTEXPR Instance() = default;
VULKAN_HPP_CONSTEXPR Instance( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {} VULKAN_HPP_CONSTEXPR Instance( std::nullptr_t ) VULKAN_HPP_NOEXCEPT {}
VULKAN_HPP_TYPESAFE_EXPLICIT Instance( VkInstance instance ) VULKAN_HPP_NOEXCEPT : m_instance( instance ) {} Instance( VkInstance instance ) VULKAN_HPP_NOEXCEPT : m_instance( instance ) {}
#if defined( VULKAN_HPP_TYPESAFE_CONVERSION )
Instance & operator=( VkInstance instance ) VULKAN_HPP_NOEXCEPT Instance & operator=( VkInstance instance ) VULKAN_HPP_NOEXCEPT
{ {
m_instance = instance; m_instance = instance;
return *this; return *this;
} }
#endif
Instance & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT Instance & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
{ {
@ -13308,7 +13298,7 @@ namespace VULKAN_HPP_NAMESPACE
# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ # endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
#endif /*VK_USE_PLATFORM_SCREEN_QNX*/ #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; return m_instance;
} }