2017-12-04 13:27:47 +00:00
// Copyright(c) 2015-2016, 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.
# include <cassert>
# include <algorithm>
# include <fstream>
# include <functional>
# include <iostream>
# include <iterator>
# include <list>
# include <map>
# include <set>
# include <sstream>
# include <string>
# include <vector>
# include <exception>
# include <regex>
# include <iterator>
# include <tinyxml2.h>
const std : : string vkNamespace = R " (
# if !defined(VULKAN_HPP_NAMESPACE)
# define VULKAN_HPP_NAMESPACE vk
# endif
namespace VULKAN_HPP_NAMESPACE
{
) " ;
const std : : string exceptionHeader = R " (
# if defined(_MSC_VER) && (_MSC_VER == 1800)
# define noexcept _NOEXCEPT
# endif
class ErrorCategoryImpl : public std : : error_category
{
public :
virtual const char * name ( ) const noexcept override { return " VULKAN_HPP_NAMESPACE::Result " ; }
virtual std : : string message ( int ev ) const override { return to_string ( static_cast < Result > ( ev ) ) ; }
} ;
# if defined(_MSC_VER) && (_MSC_VER == 1800)
# undef noexcept
# endif
VULKAN_HPP_INLINE const std : : error_category & errorCategory ( )
{
static ErrorCategoryImpl instance ;
return instance ;
}
VULKAN_HPP_INLINE std : : error_code make_error_code ( Result e )
{
return std : : error_code ( static_cast < int > ( e ) , errorCategory ( ) ) ;
}
VULKAN_HPP_INLINE std : : error_condition make_error_condition ( Result e )
{
return std : : error_condition ( static_cast < int > ( e ) , errorCategory ( ) ) ;
}
) " ;
const std : : string exceptionClassesHeader = R " (
# if defined(_MSC_VER) && (_MSC_VER == 1800)
# define noexcept _NOEXCEPT
# endif
class Error
{
public :
virtual ~ Error ( ) = default ;
virtual const char * what ( ) const noexcept = 0 ;
} ;
class LogicError : public Error , public std : : logic_error
{
public :
explicit LogicError ( const std : : string & what )
: Error ( ) , std : : logic_error ( what ) { }
explicit LogicError ( char const * what )
: Error ( ) , std : : logic_error ( what ) { }
virtual ~ LogicError ( ) = default ;
virtual const char * what ( ) const noexcept { return std : : logic_error : : what ( ) ; }
} ;
class SystemError : public Error , public std : : system_error
{
public :
SystemError ( std : : error_code ec )
: Error ( ) , std : : system_error ( ec ) { }
SystemError ( std : : error_code ec , std : : string const & what )
: Error ( ) , std : : system_error ( ec , what ) { }
SystemError ( std : : error_code ec , char const * what )
: Error ( ) , std : : system_error ( ec , what ) { }
SystemError ( int ev , std : : error_category const & ecat )
: Error ( ) , std : : system_error ( ev , ecat ) { }
SystemError ( int ev , std : : error_category const & ecat , std : : string const & what )
: Error ( ) , std : : system_error ( ev , ecat , what ) { }
SystemError ( int ev , std : : error_category const & ecat , char const * what )
: Error ( ) , std : : system_error ( ev , ecat , what ) { }
virtual ~ SystemError ( ) = default ;
virtual const char * what ( ) const noexcept { return std : : system_error : : what ( ) ; }
} ;
# if defined(_MSC_VER) && (_MSC_VER == 1800)
# undef noexcept
# endif
) " ;
const std : : string flagsHeader = R " (
template < typename FlagBitsType > struct FlagTraits
{
enum { allFlags = 0 } ;
} ;
template < typename BitType , typename MaskType = VkFlags >
class Flags
{
public :
Flags ( )
: m_mask ( 0 )
{
}
Flags ( BitType bit )
: m_mask ( static_cast < MaskType > ( bit ) )
{
}
Flags ( Flags < BitType > const & rhs )
: m_mask ( rhs . m_mask )
{
}
explicit Flags ( MaskType flags )
: m_mask ( flags )
{
}
Flags < BitType > & operator = ( Flags < BitType > const & rhs )
{
m_mask = rhs . m_mask ;
return * this ;
}
Flags < BitType > & operator | = ( Flags < BitType > const & rhs )
{
m_mask | = rhs . m_mask ;
return * this ;
}
Flags < BitType > & operator & = ( Flags < BitType > const & rhs )
{
m_mask & = rhs . m_mask ;
return * this ;
}
Flags < BitType > & operator ^ = ( Flags < BitType > const & rhs )
{
m_mask ^ = rhs . m_mask ;
return * this ;
}
Flags < BitType > operator | ( Flags < BitType > const & rhs ) const
{
Flags < BitType > result ( * this ) ;
result | = rhs ;
return result ;
}
Flags < BitType > operator & ( Flags < BitType > const & rhs ) const
{
Flags < BitType > result ( * this ) ;
result & = rhs ;
return result ;
}
Flags < BitType > operator ^ ( Flags < BitType > const & rhs ) const
{
Flags < BitType > result ( * this ) ;
result ^ = rhs ;
return result ;
}
bool operator ! ( ) const
{
return ! m_mask ;
}
Flags < BitType > operator ~ ( ) const
{
Flags < BitType > result ( * this ) ;
result . m_mask ^ = FlagTraits < BitType > : : allFlags ;
return result ;
}
bool operator = = ( Flags < BitType > const & rhs ) const
{
return m_mask = = rhs . m_mask ;
}
bool operator ! = ( Flags < BitType > const & rhs ) const
{
return m_mask ! = rhs . m_mask ;
}
explicit operator bool ( ) const
{
return ! ! m_mask ;
}
explicit operator MaskType ( ) const
{
return m_mask ;
}
private :
MaskType m_mask ;
} ;
template < typename BitType >
Flags < BitType > operator | ( BitType bit , Flags < BitType > const & flags )
{
return flags | bit ;
}
template < typename BitType >
Flags < BitType > operator & ( BitType bit , Flags < BitType > const & flags )
{
return flags & bit ;
}
template < typename BitType >
Flags < BitType > operator ^ ( BitType bit , Flags < BitType > const & flags )
{
return flags ^ bit ;
}
) " ;
const std : : string optionalClassHeader = R " (
template < typename RefType >
class Optional
{
public :
Optional ( RefType & reference ) { m_ptr = & reference ; }
Optional ( RefType * ptr ) { m_ptr = ptr ; }
Optional ( std : : nullptr_t ) { m_ptr = nullptr ; }
operator RefType * ( ) const { return m_ptr ; }
RefType const * operator - > ( ) const { return m_ptr ; }
explicit operator bool ( ) const { return ! ! m_ptr ; }
private :
RefType * m_ptr ;
} ;
) " ;
const std : : string arrayProxyHeader = R " (
# ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
template < typename T >
class ArrayProxy
{
public :
ArrayProxy ( std : : nullptr_t )
: m_count ( 0 )
, m_ptr ( nullptr )
{ }
ArrayProxy ( T & ptr )
: m_count ( 1 )
, m_ptr ( & ptr )
{ }
ArrayProxy ( uint32_t count , T * ptr )
: m_count ( count )
, m_ptr ( ptr )
{ }
template < size_t N >
ArrayProxy ( std : : array < typename std : : remove_const < T > : : type , N > & data )
: m_count ( N )
, m_ptr ( data . data ( ) )
{ }
template < size_t N >
ArrayProxy ( std : : array < typename std : : remove_const < T > : : type , N > const & data )
: m_count ( N )
, m_ptr ( data . data ( ) )
{ }
template < class Allocator = std : : allocator < typename std : : remove_const < T > : : type > >
ArrayProxy ( std : : vector < typename std : : remove_const < T > : : type , Allocator > & data )
: m_count ( static_cast < uint32_t > ( data . size ( ) ) )
, m_ptr ( data . data ( ) )
{ }
template < class Allocator = std : : allocator < typename std : : remove_const < T > : : type > >
ArrayProxy ( std : : vector < typename std : : remove_const < T > : : type , Allocator > const & data )
: m_count ( static_cast < uint32_t > ( data . size ( ) ) )
, m_ptr ( data . data ( ) )
{ }
ArrayProxy ( std : : initializer_list < T > const & data )
: m_count ( static_cast < uint32_t > ( data . end ( ) - data . begin ( ) ) )
, m_ptr ( data . begin ( ) )
{ }
const T * begin ( ) const
{
return m_ptr ;
}
const T * end ( ) const
{
return m_ptr + m_count ;
}
const T & front ( ) const
{
assert ( m_count & & m_ptr ) ;
return * m_ptr ;
}
const T & back ( ) const
{
assert ( m_count & & m_ptr ) ;
return * ( m_ptr + m_count - 1 ) ;
}
bool empty ( ) const
{
return ( m_count = = 0 ) ;
}
uint32_t size ( ) const
{
return m_count ;
}
T * data ( ) const
{
return m_ptr ;
}
private :
uint32_t m_count ;
T * m_ptr ;
} ;
# endif
) " ;
const std : : string structureChainHeader = R " (
template < typename X , typename Y > struct isStructureChainValid { enum { value = false } ; } ;
template < class Element >
class StructureChainElement
{
public :
explicit operator Element & ( ) { return value ; }
explicit operator const Element & ( ) const { return value ; }
private :
Element value ;
} ;
template < typename . . . StructureElements >
class StructureChain : private StructureChainElement < StructureElements > . . .
{
public :
StructureChain ( )
{
link < StructureElements . . . > ( ) ;
}
StructureChain ( StructureChain const & rhs )
{
linkAndCopy < StructureElements . . . > ( rhs ) ;
}
StructureChain & operator = ( StructureChain const & rhs )
{
linkAndCopy < StructureElements . . . > ( rhs ) ;
return * this ;
}
template < typename ClassType > ClassType & get ( ) { return static_cast < ClassType & > ( * this ) ; }
private :
template < typename X >
void link ( )
{
}
template < typename X , typename Y , typename . . . Z >
void link ( )
{
static_assert ( isStructureChainValid < X , Y > : : value , " The structure chain is not valid! " ) ;
X & x = static_cast < X & > ( * this ) ;
Y & y = static_cast < Y & > ( * this ) ;
x . pNext = & y ;
link < Y , Z . . . > ( ) ;
}
template < typename X >
void linkAndCopy ( StructureChain const & rhs )
{
static_cast < X & > ( * this ) = static_cast < X const & > ( rhs ) ;
}
template < typename X , typename Y , typename . . . Z >
void linkAndCopy ( StructureChain const & rhs )
{
static_assert ( isStructureChainValid < X , Y > : : value , " The structure chain is not valid! " ) ;
X & x = static_cast < X & > ( * this ) ;
Y & y = static_cast < Y & > ( * this ) ;
x = static_cast < X const & > ( rhs ) ;
x . pNext = & y ;
linkAndCopy < Y , Z . . . > ( rhs ) ;
}
} ;
) " ;
const std : : string versionCheckHeader = R " (
# if !defined(VULKAN_HPP_HAS_UNRESTRICTED_UNIONS)
# if defined(__clang__)
# if __has_feature(cxx_unrestricted_unions)
# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
# endif
# elif defined(__GNUC__)
# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
# if 40600 <= GCC_VERSION
# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
# endif
# elif defined(_MSC_VER)
# if 1900 <= _MSC_VER
# define VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
# endif
# endif
# endif
) " ;
const std : : string inlineHeader = R " (
# if !defined(VULKAN_HPP_INLINE)
# if defined(__clang___)
# if __has_attribute(always_inline)
# define VULKAN_HPP_INLINE __attribute__((always_inline)) __inline__
# else
# define VULKAN_HPP_INLINE inline
# endif
# elif defined(__GNUC__)
# define VULKAN_HPP_INLINE __attribute__((always_inline)) __inline__
# elif defined(_MSC_VER)
# define VULKAN_HPP_INLINE __forceinline
# else
# define VULKAN_HPP_INLINE inline
# endif
# endif
) " ;
const std : : string explicitHeader = R " (
# if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
# define VULKAN_HPP_TYPESAFE_EXPLICIT
# else
# define VULKAN_HPP_TYPESAFE_EXPLICIT explicit
# endif
) " ;
const std : : string resultValueHeader = R " (
template < typename T >
struct ResultValue
{
ResultValue ( Result r , T & v )
: result ( r )
, value ( v )
{ }
Result result ;
T value ;
operator std : : tuple < Result & , T & > ( ) { return std : : tuple < Result & , T & > ( result , value ) ; }
} ;
template < typename T >
struct ResultValueType
{
# ifdef VULKAN_HPP_NO_EXCEPTIONS
typedef ResultValue < T > type ;
# else
typedef T type ;
# endif
} ;
template < >
struct ResultValueType < void >
{
# ifdef VULKAN_HPP_NO_EXCEPTIONS
typedef Result type ;
# else
typedef void type ;
# endif
} ;
) " ;
const std : : string createResultValueHeader = R " (
VULKAN_HPP_INLINE ResultValueType < void > : : type createResultValue ( Result result , char const * message )
{
# ifdef VULKAN_HPP_NO_EXCEPTIONS
assert ( result = = Result : : eSuccess ) ;
return result ;
# else
if ( result ! = Result : : eSuccess )
{
throwResultException ( result , message ) ;
}
# endif
}
template < typename T >
VULKAN_HPP_INLINE typename ResultValueType < T > : : type createResultValue ( Result result , T & data , char const * message )
{
# ifdef VULKAN_HPP_NO_EXCEPTIONS
assert ( result = = Result : : eSuccess ) ;
return ResultValue < T > ( result , data ) ;
# else
if ( result ! = Result : : eSuccess )
{
throwResultException ( result , message ) ;
}
return data ;
# endif
}
VULKAN_HPP_INLINE Result createResultValue ( Result result , char const * message , std : : initializer_list < Result > successCodes )
{
# ifdef VULKAN_HPP_NO_EXCEPTIONS
assert ( std : : find ( successCodes . begin ( ) , successCodes . end ( ) , result ) ! = successCodes . end ( ) ) ;
# else
if ( std : : find ( successCodes . begin ( ) , successCodes . end ( ) , result ) = = successCodes . end ( ) )
{
throwResultException ( result , message ) ;
}
# endif
return result ;
}
template < typename T >
VULKAN_HPP_INLINE ResultValue < T > createResultValue ( Result result , T & data , char const * message , std : : initializer_list < Result > successCodes )
{
# ifdef VULKAN_HPP_NO_EXCEPTIONS
assert ( std : : find ( successCodes . begin ( ) , successCodes . end ( ) , result ) ! = successCodes . end ( ) ) ;
# else
if ( std : : find ( successCodes . begin ( ) , successCodes . end ( ) , result ) = = successCodes . end ( ) )
{
throwResultException ( result , message ) ;
}
# endif
return ResultValue < T > ( result , data ) ;
}
) " ;
const std : : string uniqueHandleHeader = R " (
# ifndef VULKAN_HPP_NO_SMART_HANDLE
template < typename Type > class UniqueHandleTraits ;
template < typename Type >
class UniqueHandle : public UniqueHandleTraits < Type > : : deleter
{
private :
using Deleter = typename UniqueHandleTraits < Type > : : deleter ;
public :
explicit UniqueHandle ( Type const & value = Type ( ) , Deleter const & deleter = Deleter ( ) )
: Deleter ( deleter )
, m_value ( value )
{ }
UniqueHandle ( UniqueHandle const & ) = delete ;
UniqueHandle ( UniqueHandle & & other )
: Deleter ( std : : move ( static_cast < Deleter & > ( other ) ) )
, m_value ( other . release ( ) )
{ }
~ UniqueHandle ( )
{
this - > destroy ( m_value ) ;
}
UniqueHandle & operator = ( UniqueHandle const & ) = delete ;
UniqueHandle & operator = ( UniqueHandle & & other )
{
reset ( other . release ( ) ) ;
* static_cast < Deleter * > ( this ) = std : : move ( static_cast < Deleter & > ( other ) ) ;
return * this ;
}
explicit operator bool ( ) const
{
return m_value . operator bool ( ) ;
}
Type const * operator - > ( ) const
{
return & m_value ;
}
Type * operator - > ( )
{
return & m_value ;
}
Type const & operator * ( ) const
{
return m_value ;
}
Type & operator * ( )
{
return m_value ;
}
const Type & get ( ) const
{
return m_value ;
}
Type & get ( )
{
return m_value ;
}
void reset ( Type const & value = Type ( ) )
{
if ( m_value ! = value )
{
this - > destroy ( m_value ) ;
m_value = value ;
}
}
Type release ( )
{
Type value = m_value ;
m_value = nullptr ;
return value ;
}
void swap ( UniqueHandle < Type > & rhs )
{
std : : swap ( m_value , rhs . m_value ) ;
std : : swap ( static_cast < Deleter & > ( * this ) , static_cast < Deleter & > ( rhs ) ) ;
}
private :
Type m_value ;
} ;
template < typename Type >
VULKAN_HPP_INLINE void swap ( UniqueHandle < Type > & lhs , UniqueHandle < Type > & rhs )
{
lhs . swap ( rhs ) ;
}
# endif
) " ;
std : : string replaceWithMap ( std : : string const & input , std : : map < std : : string , std : : string > replacements )
{
// This will match ${someVariable} and contain someVariable in match group 1
std : : regex re ( R " ( \ $ \ {([^ \ }]+) \ }) " ) ;
auto it = std : : sregex_iterator ( input . begin ( ) , input . end ( ) , re ) ;
auto end = std : : sregex_iterator ( ) ;
// No match, just return the original string
if ( it = = end )
{
return input ;
}
std : : string result = " " ;
while ( it ! = end )
{
std : : smatch match = * it ;
auto itReplacement = replacements . find ( match [ 1 ] . str ( ) ) ;
assert ( itReplacement ! = replacements . end ( ) ) ;
result + = match . prefix ( ) . str ( ) + ( ( itReplacement ! = replacements . end ( ) ) ? itReplacement - > second : match [ 0 ] . str ( ) ) ;
+ + it ;
// we've passed the last match. Append the rest of the orignal string
if ( it = = end )
{
result + = match . suffix ( ) . str ( ) ;
}
}
return result ;
}
struct ParamData
{
std : : string type ;
std : : string name ;
std : : string arraySize ;
std : : string pureType ;
std : : string len ;
bool optional ;
} ;
struct CommandData
{
CommandData ( std : : string const & t , std : : string const & fn )
: returnType ( t )
, fullName ( fn )
, returnParam ( ~ 0 )
, templateParam ( ~ 0 )
, twoStep ( false )
{ }
std : : string className ;
std : : string enhancedReturnType ;
std : : string fullName ;
std : : vector < ParamData > params ;
std : : string protect ;
std : : string reducedName ;
size_t returnParam ;
std : : string returnType ;
std : : set < size_t > skippedParams ;
std : : vector < std : : string > successCodes ;
size_t templateParam ;
bool twoStep ;
std : : map < size_t , size_t > vectorParams ;
} ;
struct DependencyData
{
enum class Category
{
ALIAS ,
COMMAND ,
ENUM ,
FLAGS ,
FUNC_POINTER ,
HANDLE ,
REQUIRED ,
SCALAR ,
STRUCT ,
UNION
} ;
DependencyData ( Category c , std : : string const & n )
: category ( c )
, name ( n )
{ }
Category category ;
std : : string name ;
std : : set < std : : string > dependencies ;
std : : set < std : : string > forwardDependencies ;
} ;
struct AliasData
{
AliasData ( DependencyData : : Category c , std : : string const & v , std : : string const & p )
: category ( c )
, value ( v )
, protect ( p )
{ }
DependencyData : : Category category ;
std : : string value ;
std : : string protect ;
} ;
struct EnumValueData
{
std : : string name ;
std : : string value ;
std : : string alias ;
} ;
struct EnumData
{
EnumData ( std : : string const & n , bool b = false )
: name ( n )
, bitmask ( b )
{ }
void addEnumValue ( std : : string const & name , std : : string const & tag , std : : map < std : : string , std : : string > & nameMap ) ;
std : : string name ;
std : : string prefix ;
std : : string postfix ;
std : : vector < EnumValueData > values ;
std : : string protect ;
bool bitmask ;
} ;
struct FlagData
{
std : : string protect ;
std : : string alias ;
} ;
struct HandleData
{
std : : vector < std : : string > commands ;
std : : string protect ;
std : : string alias ;
} ;
struct ScalarData
{
std : : string protect ;
} ;
struct MemberData
{
std : : string type ;
std : : string name ;
std : : string arraySize ;
std : : string pureType ;
std : : string values ;
} ;
struct StructData
{
StructData ( )
: returnedOnly ( false )
{ }
bool returnedOnly ;
bool isUnion ;
std : : vector < MemberData > members ;
std : : string protect ;
std : : vector < std : : string > structExtends ;
} ;
struct DeleterData
{
std : : string pool ;
std : : string call ;
} ;
# if !defined(NDEBUG)
struct ExtensionData
{
std : : string protect ;
std : : vector < std : : string > requires ;
} ;
struct VendorIDData
{
std : : string name ;
std : : string id ;
std : : string comment ;
} ;
# endif
struct VkData
{
std : : map < std : : string , AliasData > aliases ; // Enum Aliases
std : : map < std : : string , CommandData > commands ;
std : : map < std : : string , std : : string > constants ;
std : : set < std : : string > defines ;
std : : list < DependencyData > dependencies ;
std : : map < std : : string , DeleterData > deleters ; // map from child types to corresponding deleter data
std : : map < std : : string , std : : set < std : : string > > deleterTypes ; // map from parent type to set of child types
std : : map < std : : string , EnumData > enums ;
std : : map < std : : string , FlagData > flags ;
std : : map < std : : string , HandleData > handles ;
std : : map < std : : string , std : : string > nameMap ;
std : : map < std : : string , ScalarData > scalars ;
std : : map < std : : string , StructData > structs ;
std : : set < std : : string > extendedStructs ; // structs which are referenced by the structextends tag
std : : set < std : : string > tags ;
std : : string typesafeCheck ;
std : : string version ;
std : : set < std : : string > vkTypes ;
std : : string vulkanLicenseHeader ;
# if !defined(NDEBUG)
std : : map < std : : string , ExtensionData > extensions ;
std : : vector < VendorIDData > vendorIDs ;
# endif
} ;
void aliasType ( VkData & vkData , DependencyData : : Category category , std : : string const & aliasName , std : : string const & newName , std : : string const & protect ) ;
void createDefaults ( VkData const & vkData , std : : map < std : : string , std : : string > & defaultValues ) ;
void determineEnhancedReturnType ( CommandData & commandData ) ;
void determineReducedName ( CommandData & commandData ) ;
void determineReturnParam ( CommandData & commandData ) ;
void determineSkippedParams ( CommandData & commandData ) ;
void determineTemplateParam ( CommandData & commandData ) ;
void determineVectorParams ( CommandData & commandData ) ;
void enterProtect ( std : : ostream & os , std : : string const & protect ) ;
std : : string extractTag ( std : : string const & name ) ;
std : : string findTag ( std : : string const & name , std : : set < std : : string > const & tags ) ;
std : : string generateEnumNameForFlags ( std : : string const & name ) ;
bool hasPointerParam ( std : : vector < ParamData > const & params ) ;
void leaveProtect ( std : : ostream & os , std : : string const & protect ) ;
void linkCommandToHandle ( VkData & vkData , CommandData & commandData ) ;
std : : string readArraySize ( tinyxml2 : : XMLNode * node , std : : string & name ) ;
bool readCommandParam ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & dependencies , std : : vector < ParamData > & params ) ;
void readCommandParams ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & dependencies , CommandData & commandData ) ;
tinyxml2 : : XMLNode * readCommandParamType ( tinyxml2 : : XMLNode * node , ParamData & param ) ;
CommandData & readCommandProto ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readCommands ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readCommandsCommand ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
std : : vector < std : : string > readCommandSuccessCodes ( tinyxml2 : : XMLElement * element , std : : set < std : : string > const & tags ) ;
void readComment ( tinyxml2 : : XMLElement * element , std : : string & header ) ;
void readEnums ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readEnumsConstant ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > & constants ) ;
void readEnumsEnum ( tinyxml2 : : XMLElement * element , EnumData & enumData , std : : map < std : : string , std : : string > & nameMap ) ;
void readDisabledExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readExtensionAlias ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect , std : : string const & tag ) ;
void readExtensionCommand ( tinyxml2 : : XMLElement * element , std : : map < std : : string , CommandData > & commands , std : : string const & protect ) ;
void readExtensionEnum ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : string const & tag , std : : map < std : : string , std : : string > & nameMap ) ;
void readExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect , std : : string const & tag ) ;
void readExtensions ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readExtensionsExtension ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readExtensionType ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect ) ;
void readFeature ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : map < std : : string , std : : string > & nameMap ) ;
void readFeatureRequire ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : map < std : : string , std : : string > & nameMap ) ;
void readFeatureRequireEnum ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : map < std : : string , std : : string > & nameMap ) ;
tinyxml2 : : XMLNode * readType ( tinyxml2 : : XMLNode * element , std : : string & type , std : : string & pureType ) ;
void readTypeBasetype ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies , std : : map < std : : string , std : : string > const & attributes ) ;
void readTypeBitmask ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : map < std : : string , std : : string > const & attributes ) ;
void readTypeDefine ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : map < std : : string , std : : string > const & attributes ) ;
void readTypeFuncpointer ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies ) ;
void readTypeHandle ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : map < std : : string , std : : string > const & attributes ) ;
void readTypeStruct ( tinyxml2 : : XMLElement * element , VkData & vkData , bool isUnion ) ;
void readTypeStructMember ( tinyxml2 : : XMLElement * element , VkData & vkData , StructData & structData ) ;
void readTag ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & tags ) ;
void readTags ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & tags ) ;
void readType ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readTypeName ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > const & attributes , std : : list < DependencyData > & dependencies ) ;
void readTypes ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
std : : string reduceName ( std : : string const & name , bool singular = false ) ;
void registerDeleter ( VkData & vkData , CommandData const & commandData ) ;
std : : string startLowerCase ( std : : string const & input ) ;
std : : string startUpperCase ( std : : string const & input ) ;
void sortDependencies ( std : : list < DependencyData > & dependencies ) ;
std : : string strip ( std : : string const & value , std : : string const & prefix , std : : string const & postfix = std : : string ( ) ) ;
std : : string stripPluralS ( std : : string const & name ) ;
std : : string toCamelCase ( std : : string const & value ) ;
std : : vector < std : : string > tokenize ( std : : string tokenString , char separator ) ;
std : : string toUpperCase ( std : : string const & name ) ;
std : : string trim ( std : : string const & input ) ;
std : : string trimEnd ( std : : string const & input ) ;
void writeCall ( std : : ostream & os , CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular ) ;
std : : string generateCall ( CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular ) ;
void writeCallCountParameter ( std : : ostream & os , CommandData const & commandData , bool singular , std : : map < size_t , size_t > : : const_iterator it ) ;
void writeCallPlainTypeParameter ( std : : ostream & os , ParamData const & paramData ) ;
void writeCallVectorParameter ( std : : ostream & os , CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular , std : : map < size_t , size_t > : : const_iterator it ) ;
void writeCallVulkanTypeParameter ( std : : ostream & os , ParamData const & paramData ) ;
void writeDeleterClasses ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleters ) ;
void writeDeleterForwardDeclarations ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleters ) ;
void writeEnumsToString ( std : : ostream & os , EnumData const & enumData ) ;
void writeFlagsToString ( std : : ostream & os , std : : string const & flagsName , EnumData const & enumData ) ;
void writeFunction ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition , bool enhanced , bool singular , bool unique , bool isStructureChain ) ;
void writeFunctionBodyEnhanced ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular , bool isStructureChain ) ;
void writeFunctionBodyEnhancedCall ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular ) ;
void writeFunctionBodyEnhancedCallResult ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular ) ;
void writeFunctionBodyEnhancedCallTwoStep ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData ) ;
void writeFunctionBodyEnhancedCallTwoStepChecked ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData ) ;
void writeFunctionBodyEnhancedCallTwoStepIterate ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData ) ;
void writeFunctionBodyEnhancedLocalCountVariable ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData ) ;
std : : string writeFunctionBodyEnhancedLocalReturnVariable ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool singular , bool isStructureChain ) ;
void writeFunctionBodyEnhancedMultiVectorSizeCheck ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData ) ;
void writeFunctionBodyEnhancedReturnResultValue ( std : : ostream & os , std : : string const & indentation , std : : string const & returnName , CommandData const & commandData , bool singular ) ;
void writeFunctionBodyStandard ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData ) ;
void writeFunctionBodyUnique ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular ) ;
void writeFunctionHeaderArguments ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool enhanced , bool singular , bool withDefaults ) ;
void writeFunctionHeaderArgumentsEnhanced ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool singular , bool withDefaults ) ;
void writeFunctionHeaderArgumentsStandard ( std : : ostream & os , CommandData const & commandData ) ;
void writeFunctionHeaderName ( std : : ostream & os , std : : string const & name , bool singular , bool unique ) ;
void writeFunctionHeaderReturnType ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool enhanced , bool singular , bool unique , bool isStructureChain ) ;
void writeFunctionHeaderTemplate ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool withDefault , bool isStructureChain ) ;
void writeReinterpretCast ( std : : ostream & os , bool leadingConst , bool vulkanType , std : : string const & type , bool trailingPointerToConst ) ;
void writeStandardOrEnhanced ( std : : ostream & os , std : : string const & standard , std : : string const & enhanced ) ;
void writeStructConstructor ( std : : ostream & os , std : : string const & name , StructData const & structData , std : : set < std : : string > const & vkTypes , std : : map < std : : string , std : : string > const & nameMap , std : : map < std : : string , std : : string > const & defaultValues ) ;
void writeStructSetter ( std : : ostream & os , std : : string const & structureName , MemberData const & memberData , std : : set < std : : string > const & vkTypes , std : : map < std : : string , StructData > const & structs ) ;
void writeTypeAlias ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData ) ;
void writeTypeCommand ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData ) ;
void writeTypeCommand ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition ) ;
void writeTypeEnum ( std : : ostream & os , EnumData const & enumData ) ;
bool isErrorEnum ( std : : string const & enumName ) ;
std : : string stripErrorEnumPrefix ( std : : string const & enumName ) ;
void writeExceptionsForEnum ( std : : ostream & os , EnumData const & enumData ) ;
void writeThrowExceptions ( std : : ostream & os , EnumData const & enumData ) ;
void writeTypeFlags ( std : : ostream & os , std : : string const & flagsName , FlagData const & flagData , EnumData const & enumData ) ;
void writeTypeHandle ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , HandleData const & handle , std : : list < DependencyData > const & dependencies ) ;
void writeTypeScalar ( std : : ostream & os , DependencyData const & dependencyData ) ;
void writeTypeStruct ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , std : : map < std : : string , std : : string > const & defaultValues ) ;
void writeTypeUnion ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , std : : map < std : : string , std : : string > const & defaultValues ) ;
void writeTypes ( std : : ostream & os , VkData const & vkData , std : : map < std : : string , std : : string > const & defaultValues ) ;
void writeVersionCheck ( std : : ostream & os , std : : string const & version ) ;
void writeTypesafeCheck ( std : : ostream & os , std : : string const & typesafeCheck ) ;
# if !defined(NDEBUG)
void skipTypeEnum ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > const & attributes ) ;
void skipTypeInclude ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > const & attributes ) ;
void skipVendorID ( tinyxml2 : : XMLElement * element , std : : vector < VendorIDData > & vendorIDs ) ;
void skipVendorIDs ( tinyxml2 : : XMLElement * element , std : : vector < VendorIDData > & vendorIDs ) ;
# endif
std : : string createEnumValueName ( std : : string const & name , std : : string const & prefix , std : : string const & postfix , bool bitmask , std : : string const & tag )
{
std : : string result = " e " + toCamelCase ( strip ( name , prefix , postfix ) ) ;
if ( bitmask )
{
size_t pos = result . find ( " Bit " ) ;
if ( pos ! = std : : string : : npos )
{
result . erase ( pos , 3 ) ;
}
}
if ( ! tag . empty ( ) & & ( result . substr ( result . length ( ) - tag . length ( ) ) = = toCamelCase ( tag ) ) )
{
result = result . substr ( 0 , result . length ( ) - tag . length ( ) ) + tag ;
}
return result ;
}
void EnumData : : addEnumValue ( std : : string const & name , std : : string const & tag , std : : map < std : : string , std : : string > & nameMap )
{
EnumValueData evd ;
evd . name = createEnumValueName ( name , prefix , postfix , bitmask , tag ) ;
evd . value = name ;
auto it = std : : find_if ( values . begin ( ) , values . end ( ) , [ & evd ] ( EnumValueData const & _evd ) { return _evd . name = = evd . name ; } ) ;
if ( it = = values . end ( ) )
{
values . push_back ( evd ) ;
assert ( nameMap . find ( name ) = = nameMap . end ( ) ) ;
nameMap [ name ] = this - > name + " :: " + evd . name ;
}
else
{
assert ( it - > value = = evd . value ) ;
}
}
void aliasType ( VkData & vkData , DependencyData : : Category category , std : : string const & aliasName , std : : string const & newName , std : : string const & protect )
{
auto aliasIt = vkData . aliases . find ( newName ) ;
if ( aliasIt = = vkData . aliases . end ( ) )
{
vkData . aliases . insert ( std : : make_pair ( newName , AliasData ( category , aliasName , protect ) ) ) ;
// we have to add the type to the set of vulkan types to ensure that the require type conversion takes place
vkData . vkTypes . insert ( newName ) ;
assert ( std : : find_if ( vkData . dependencies . begin ( ) , vkData . dependencies . end ( ) , [ newName ] ( DependencyData const & dd ) { return dd . name = = newName ; } ) = = vkData . dependencies . end ( ) ) ;
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : ALIAS , newName ) ) ;
vkData . dependencies . back ( ) . dependencies . insert ( aliasName ) ;
}
else
{
assert ( aliasIt - > second . protect = = protect ) ;
auto dependencyIt = std : : find_if ( vkData . dependencies . begin ( ) , vkData . dependencies . end ( ) , [ newName ] ( DependencyData const & dd ) { return dd . name = = newName ; } ) ;
assert ( ( dependencyIt ! = vkData . dependencies . end ( ) ) & & ( dependencyIt - > dependencies . size ( ) = = 1 ) & & ( dependencyIt - > dependencies . find ( aliasName ) ! = dependencyIt - > dependencies . end ( ) ) ) ;
}
}
static void setDefault ( std : : string const & name , std : : map < std : : string , std : : string > & defaultValues , EnumData const & enumData )
{
defaultValues [ name ] = name + ( enumData . values . empty ( ) ? " () " : ( " :: " + enumData . values . front ( ) . name ) ) ;
}
void createDefaults ( VkData const & vkData , std : : map < std : : string , std : : string > & defaultValues )
{
for ( auto dependency : vkData . dependencies )
{
assert ( defaultValues . find ( dependency . name ) = = defaultValues . end ( ) ) ;
switch ( dependency . category )
{
case DependencyData : : Category : : ALIAS :
{
auto aliasIt = vkData . aliases . find ( dependency . name ) ;
switch ( aliasIt - > second . category )
{
case DependencyData : : Category : : ENUM :
assert ( ( aliasIt ! = vkData . aliases . end ( ) ) & & ( vkData . enums . find ( aliasIt - > second . value ) ! = vkData . enums . end ( ) ) ) ;
setDefault ( dependency . name , defaultValues , vkData . enums . find ( aliasIt - > second . value ) - > second ) ;
break ;
case DependencyData : : Category : : STRUCT :
defaultValues [ dependency . name ] = dependency . name + " () " ;
break ;
default :
assert ( false ) ;
break ;
}
}
break ;
case DependencyData : : Category : : COMMAND : // commands should never be asked for defaults
break ;
case DependencyData : : Category : : ENUM :
assert ( vkData . enums . find ( dependency . name ) ! = vkData . enums . end ( ) ) ;
setDefault ( dependency . name , defaultValues , vkData . enums . find ( dependency . name ) - > second ) ;
break ;
case DependencyData : : Category : : FLAGS :
case DependencyData : : Category : : HANDLE :
case DependencyData : : Category : : STRUCT :
case DependencyData : : Category : : UNION : // just call the default constructor for flags, structs, and structs (which are mapped to classes)
defaultValues [ dependency . name ] = dependency . name + " () " ;
break ;
case DependencyData : : Category : : FUNC_POINTER : // func_pointers default to nullptr
defaultValues [ dependency . name ] = " nullptr " ;
break ;
case DependencyData : : Category : : REQUIRED : // all required default to "0"
case DependencyData : : Category : : SCALAR : // all scalars default to "0"
defaultValues [ dependency . name ] = " 0 " ;
break ;
default :
assert ( false ) ;
break ;
}
}
}
void determineReducedName ( CommandData & commandData )
{
commandData . reducedName = commandData . fullName ;
std : : string searchName = commandData . params [ 0 ] . pureType ;
size_t pos = commandData . fullName . find ( searchName ) ;
if ( ( pos = = std : : string : : npos ) & & isupper ( searchName [ 0 ] ) )
{
searchName [ 0 ] = tolower ( searchName [ 0 ] ) ;
pos = commandData . fullName . find ( searchName ) ;
}
if ( pos ! = std : : string : : npos )
{
commandData . reducedName . erase ( pos , searchName . length ( ) ) ;
}
else if ( ( searchName = = " commandBuffer " ) & & ( commandData . fullName . find ( " cmd " ) = = 0 ) )
{
commandData . reducedName . erase ( 0 , 3 ) ;
pos = 0 ;
}
if ( ( pos = = 0 ) & & isupper ( commandData . reducedName [ 0 ] ) )
{
commandData . reducedName [ 0 ] = tolower ( commandData . reducedName [ 0 ] ) ;
}
}
void determineEnhancedReturnType ( CommandData & commandData )
{
std : : string returnType ;
// if there is a return parameter of type void or Result, and if it's of type Result it either has just one success code
// or two success codes, where the second one is of type eIncomplete and it's a two-step process
// -> we can return that parameter
if ( ( commandData . returnParam ! = ~ 0 )
& & ( ( commandData . returnType = = " void " )
| | ( ( commandData . returnType = = " Result " )
& & ( ( commandData . successCodes . size ( ) = = 1 )
| | ( ( commandData . successCodes . size ( ) = = 2 )
& & ( commandData . successCodes [ 1 ] = = " eIncomplete " )
& & commandData . twoStep ) ) ) ) )
{
if ( commandData . vectorParams . find ( commandData . returnParam ) ! = commandData . vectorParams . end ( ) )
{
// the return parameter is a vector-type parameter
if ( commandData . params [ commandData . returnParam ] . pureType = = " void " )
{
// for a vector of void, we use a vector of uint8_t, instead
commandData . enhancedReturnType = " std::vector<uint8_t,Allocator> " ;
}
else
{
// for the other parameters, we use a vector of the pure type
commandData . enhancedReturnType = " std::vector< " + commandData . params [ commandData . returnParam ] . pureType + " ,Allocator> " ;
}
}
else
{
// it's a simple parameter -> get the type and just remove the trailing '*' (originally, it's a pointer)
assert ( commandData . params [ commandData . returnParam ] . type . back ( ) = = ' * ' ) ;
assert ( commandData . params [ commandData . returnParam ] . type . find ( " const " ) = = std : : string : : npos ) ;
commandData . enhancedReturnType = commandData . params [ commandData . returnParam ] . type ;
commandData . enhancedReturnType . pop_back ( ) ;
}
}
else if ( ( commandData . returnType = = " Result " ) & & ( commandData . successCodes . size ( ) = = 1 ) )
{
// an original return of type "Result" with just one successCode is changed to void, errors throw an exception
commandData . enhancedReturnType = " void " ;
}
else
{
// the return type just stays the original return type
commandData . enhancedReturnType = commandData . returnType ;
}
}
void determineReturnParam ( CommandData & commandData )
{
// for return types of type Result or void, we can replace determine a parameter to return
if ( ( commandData . returnType = = " Result " ) | | ( commandData . returnType = = " void " ) )
{
for ( size_t i = 0 ; i < commandData . params . size ( ) ; i + + )
{
if ( ( commandData . params [ i ] . type . find ( ' * ' ) ! = std : : string : : npos )
& & ( commandData . params [ i ] . type . find ( " const " ) = = std : : string : : npos )
& & std : : find_if ( commandData . vectorParams . begin ( ) , commandData . vectorParams . end ( ) , [ i ] ( std : : pair < size_t , size_t > const & vp ) { return vp . second = = i ; } ) = = commandData . vectorParams . end ( )
& & ( ( commandData . vectorParams . find ( i ) = = commandData . vectorParams . end ( ) ) | | commandData . twoStep | | ( commandData . successCodes . size ( ) = = 1 ) ) )
{
// it's a non-const pointer, not a vector-size parameter, if it's a vector parameter, its a two-step process or there's just one success code
// -> look for another non-cost pointer argument
auto paramIt = std : : find_if ( commandData . params . begin ( ) + i + 1 , commandData . params . end ( ) , [ ] ( ParamData const & pd )
{
return ( pd . type . find ( ' * ' ) ! = std : : string : : npos ) & & ( pd . type . find ( " const " ) = = std : : string : : npos ) ;
} ) ;
// if there is another such argument, we can't decide which one to return -> return none (~0)
// otherwise return the index of the selcted parameter
commandData . returnParam = paramIt ! = commandData . params . end ( ) ? ~ 0 : i ;
}
}
}
}
void determineSkippedParams ( CommandData & commandData )
{
// the size-parameters of vector parameters are not explicitly used in the enhanced API
std : : for_each ( commandData . vectorParams . begin ( ) , commandData . vectorParams . end ( ) , [ & commandData ] ( std : : pair < size_t , size_t > const & vp ) { if ( vp . second ! = ~ 0 ) commandData . skippedParams . insert ( vp . second ) ; } ) ;
// and the return parameter is also skipped
if ( commandData . returnParam ! = ~ 0 )
{
commandData . skippedParams . insert ( commandData . returnParam ) ;
}
}
void determineTemplateParam ( CommandData & commandData )
{
for ( size_t i = 0 ; i < commandData . params . size ( ) ; i + + )
{
// any vector parameter on the pure type void is templatized in the enhanced API
if ( ( commandData . vectorParams . find ( i ) ! = commandData . vectorParams . end ( ) ) & & ( commandData . params [ i ] . pureType = = " void " ) )
{
# if !defined(NDEBUG)
for ( size_t j = i + 1 ; j < commandData . params . size ( ) ; j + + )
{
assert ( ( commandData . vectorParams . find ( j ) = = commandData . vectorParams . end ( ) ) | | ( commandData . params [ j ] . pureType ! = " void " ) ) ;
}
# endif
commandData . templateParam = i ;
break ;
}
}
assert ( ( commandData . templateParam = = ~ 0 ) | | ( commandData . vectorParams . find ( commandData . templateParam ) ! = commandData . vectorParams . end ( ) ) ) ;
}
void determineVectorParams ( CommandData & commandData )
{
// look for the parameters whose len equals the name of an other parameter
for ( auto it = commandData . params . begin ( ) , begin = it , end = commandData . params . end ( ) ; it ! = end ; + + it )
{
if ( ! it - > len . empty ( ) )
{
auto findLambda = [ it ] ( ParamData const & pd ) { return pd . name = = it - > len ; } ;
auto findIt = std : : find_if ( begin , it , findLambda ) ; // look for a parameter named as the len of this parameter
assert ( ( std : : count_if ( begin , end , findLambda ) = = 0 ) | | ( findIt < it ) ) ; // make sure, there is no other parameter like that
// add this parameter as a vector parameter, using the len-name parameter as the second value (or ~0 if there is nothing like that)
commandData . vectorParams . insert ( std : : make_pair ( std : : distance ( begin , it ) , findIt < it ? std : : distance ( begin , findIt ) : ~ 0 ) ) ;
assert ( ( commandData . vectorParams [ std : : distance ( begin , it ) ] ! = ~ 0 )
| | ( it - > len = = " null-terminated " )
| | ( it - > len = = " pAllocateInfo::descriptorSetCount " )
| | ( it - > len = = " pAllocateInfo::commandBufferCount " ) ) ;
}
}
}
void enterProtect ( std : : ostream & os , std : : string const & protect )
{
if ( ! protect . empty ( ) )
{
os < < " #ifdef " < < protect < < std : : endl ;
}
}
std : : string extractTag ( std : : string const & name )
{
// the name is supposed to look like: VK_<tag>_<other>
size_t start = name . find ( ' _ ' ) ;
assert ( ( start ! = std : : string : : npos ) & & ( name . substr ( 0 , start ) = = " VK " ) ) ;
size_t end = name . find ( ' _ ' , start + 1 ) ;
assert ( end ! = std : : string : : npos ) ;
return name . substr ( start + 1 , end - start - 1 ) ;
}
std : : string findTag ( std : : string const & name , std : : set < std : : string > const & tags )
{
// find the tag in a name, return that tag or an empty string
auto tagIt = std : : find_if ( tags . begin ( ) , tags . end ( ) , [ & name ] ( std : : string const & t )
{
size_t pos = name . find ( t ) ;
return ( pos ! = std : : string : : npos ) & & ( pos = = name . length ( ) - t . length ( ) ) ;
} ) ;
return tagIt ! = tags . end ( ) ? * tagIt : " " ;
}
std : : string generateEnumNameForFlags ( std : : string const & name )
{
// create a string, where the substring "Flags" is replaced by "FlagBits"
std : : string generatedName = name ;
size_t pos = generatedName . rfind ( " Flags " ) ;
assert ( pos ! = std : : string : : npos ) ;
generatedName . replace ( pos , 5 , " FlagBits " ) ;
return generatedName ;
}
bool hasPointerParam ( std : : vector < ParamData > const & params )
{
// check if any of the parameters is a pointer
auto it = std : : find_if ( params . begin ( ) , params . end ( ) , [ ] ( ParamData const & pd )
{
return ( pd . type . find ( ' * ' ) ! = std : : string : : npos ) ;
} ) ;
return it ! = params . end ( ) ;
}
void leaveProtect ( std : : ostream & os , std : : string const & protect )
{
if ( ! protect . empty ( ) )
{
os < < " #endif /* " < < protect < < " */ " < < std : : endl ;
}
}
void linkCommandToHandle ( VkData & vkData , CommandData & commandData )
{
// first, find the handle named like the type of the first argument
// if there is no such handle, look for the unnamed "handle", that gathers all the functions not tied to a specific handle
assert ( ! commandData . params . empty ( ) ) ;
std : : map < std : : string , HandleData > : : iterator hit = vkData . handles . find ( commandData . params [ 0 ] . pureType ) ;
if ( hit = = vkData . handles . end ( ) )
{
hit = vkData . handles . find ( " " ) ;
}
assert ( hit ! = vkData . handles . end ( ) ) ;
// put the command into the handle's list of commands, and store the handle in the commands className
hit - > second . commands . push_back ( commandData . fullName ) ;
commandData . className = hit - > first ;
// add the dependencies of the command to the dependencies of the handle
DependencyData const & commandDD = vkData . dependencies . back ( ) ;
std : : list < DependencyData > : : iterator handleDD = std : : find_if ( vkData . dependencies . begin ( ) , vkData . dependencies . end ( ) , [ hit ] ( DependencyData const & dd ) { return dd . name = = hit - > first ; } ) ;
assert ( ( handleDD ! = vkData . dependencies . end ( ) ) | | hit - > first . empty ( ) ) ;
if ( handleDD ! = vkData . dependencies . end ( ) )
{
std : : copy_if ( commandDD . dependencies . begin ( ) , commandDD . dependencies . end ( ) , std : : inserter ( handleDD - > dependencies , handleDD - > dependencies . end ( ) ) , [ hit ] ( std : : string const & d ) { return d ! = hit - > first ; } ) ;
}
}
std : : string readArraySize ( tinyxml2 : : XMLNode * node , std : : string & name )
{
std : : string arraySize ;
if ( name . back ( ) = = ' ] ' )
{
// if the parameter has '[' and ']' in its name, get the stuff inbetween those as the array size and erase that part from the parameter name
assert ( ! node - > NextSibling ( ) ) ;
size_t pos = name . find ( ' [ ' ) ;
assert ( pos ! = std : : string : : npos ) ;
arraySize = name . substr ( pos + 1 , name . length ( ) - 2 - pos ) ;
name . erase ( pos ) ;
}
else
{
// otherwise look for a sibling of this node
node = node - > NextSibling ( ) ;
if ( node & & node - > ToText ( ) )
{
std : : string value = trimEnd ( node - > Value ( ) ) ;
if ( value = = " [ " )
{
// if this node has '[' as its value, the next node holds the array size, and the node after that needs to hold ']', and there should be no more siblings
node = node - > NextSibling ( ) ;
assert ( node & & node - > ToElement ( ) & & ( strcmp ( node - > Value ( ) , " enum " ) = = 0 ) ) ;
arraySize = node - > ToElement ( ) - > GetText ( ) ;
node = node - > NextSibling ( ) ;
assert ( node & & node - > ToText ( ) & & ( trimEnd ( node - > Value ( ) ) = = " ] " ) ) ;
}
else
{
// otherwise, the node holds '[' and ']', so get the stuff in between those as the array size
assert ( ( value . front ( ) = = ' [ ' ) & & ( value . back ( ) = = ' ] ' ) ) ;
arraySize = value . substr ( 1 , value . length ( ) - 2 ) ;
}
assert ( ! node - > NextSibling ( ) | | ( ( strcmp ( node - > NextSibling ( ) - > Value ( ) , " comment " ) = = 0 ) & & ! node - > NextSibling ( ) - > NextSibling ( ) ) ) ;
}
}
return arraySize ;
}
bool readCommandParam ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & dependencies , std : : vector < ParamData > & params )
{
ParamData param ;
bool isTwoStep = false ;
if ( element - > Attribute ( " len " ) )
{
param . len = element - > Attribute ( " len " ) ;
auto pit = std : : find_if ( params . begin ( ) , params . end ( ) , [ & param ] ( ParamData const & pd ) { return param . len = = pd . name ; } ) ;
if ( pit ! = params . end ( ) )
{
isTwoStep = ( pit - > type . find ( ' * ' ) ! = std : : string : : npos ) ;
}
}
// get the type of the parameter, and put it into the list of dependencies
tinyxml2 : : XMLNode * child = readCommandParamType ( element - > FirstChild ( ) , param ) ;
dependencies . insert ( param . pureType ) ;
assert ( child - > ToElement ( ) & & ( strcmp ( child - > Value ( ) , " name " ) = = 0 ) ) ;
param . name = child - > ToElement ( ) - > GetText ( ) ;
param . arraySize = readArraySize ( child , param . name ) ;
param . optional = element - > Attribute ( " optional " ) & & ( strcmp ( element - > Attribute ( " optional " ) , " true " ) = = 0 ) ;
params . push_back ( param ) ;
assert ( ! isTwoStep | | ( param . type . substr ( 0 , 6 ) ! = " const " ) ) ;
return isTwoStep ;
}
void readCommandParams ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & dependencies , CommandData & commandData )
{
// iterate over the siblings of the element and read the command parameters
assert ( element ) ;
while ( element = element - > NextSiblingElement ( ) )
{
std : : string value = element - > Value ( ) ;
if ( value = = " param " )
{
commandData . twoStep | = readCommandParam ( element , dependencies , commandData . params ) ;
}
else
{
// ignore these values!
assert ( ( value = = " implicitexternsyncparams " ) | | ( value = = " validity " ) ) ;
}
}
}
tinyxml2 : : XMLNode * readCommandParamType ( tinyxml2 : : XMLNode * node , ParamData & param )
{
assert ( node ) ;
if ( node - > ToText ( ) )
{
// start type with "const" or "struct", if needed
std : : string value = trim ( node - > Value ( ) ) ;
assert ( ( value = = " const " ) | | ( value = = " struct " ) ) ;
param . type = value + " " ;
node = node - > NextSibling ( ) ;
assert ( node ) ;
}
// get the pure type
assert ( node - > ToElement ( ) & & ( strcmp ( node - > Value ( ) , " type " ) = = 0 ) & & node - > ToElement ( ) - > GetText ( ) ) ;
std : : string type = strip ( node - > ToElement ( ) - > GetText ( ) , " Vk " ) ;
param . type + = type ;
param . pureType = type ;
// end with "*", "**", or "* const*", if needed
node = node - > NextSibling ( ) ;
assert ( node ) ;
if ( node - > ToText ( ) )
{
std : : string value = trimEnd ( node - > Value ( ) ) ;
assert ( ( value = = " * " ) | | ( value = = " ** " ) | | ( value = = " * const* " ) ) ;
param . type + = value ;
node = node - > NextSibling ( ) ;
}
return node ;
}
CommandData & readCommandProto ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ( strcmp ( typeElement - > Value ( ) , " type " ) = = 0 ) ) ;
tinyxml2 : : XMLElement * nameElement = typeElement - > NextSiblingElement ( ) ;
assert ( nameElement & & ( strcmp ( nameElement - > Value ( ) , " name " ) = = 0 ) ) ;
assert ( ! nameElement - > NextSiblingElement ( ) ) ;
// get return type and name of the command
std : : string type = strip ( typeElement - > GetText ( ) , " Vk " ) ;
std : : string name = startLowerCase ( strip ( nameElement - > GetText ( ) , " vk " ) ) ;
// add an empty DependencyData to this name
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : COMMAND , name ) ) ;
// insert an empty CommandData into the commands-map, and return the newly created CommandData
assert ( vkData . commands . find ( name ) = = vkData . commands . end ( ) ) ;
return vkData . commands . insert ( std : : make_pair ( name , CommandData ( type , name ) ) ) . first - > second ;
}
void readCommands ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( strcmp ( child - > Value ( ) , " command " ) = = 0 ) ;
readCommandsCommand ( child , vkData ) ;
}
}
void readCommandsCommand ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ( strcmp ( child - > Value ( ) , " proto " ) = = 0 ) ) ;
CommandData & commandData = readCommandProto ( child , vkData ) ;
commandData . successCodes = readCommandSuccessCodes ( element , vkData . tags ) ;
readCommandParams ( child , vkData . dependencies . back ( ) . dependencies , commandData ) ;
determineReducedName ( commandData ) ;
linkCommandToHandle ( vkData , commandData ) ;
registerDeleter ( vkData , commandData ) ;
determineVectorParams ( commandData ) ;
determineReturnParam ( commandData ) ;
determineTemplateParam ( commandData ) ;
determineEnhancedReturnType ( commandData ) ;
determineSkippedParams ( commandData ) ;
}
std : : vector < std : : string > readCommandSuccessCodes ( tinyxml2 : : XMLElement * element , std : : set < std : : string > const & tags )
{
std : : vector < std : : string > results ;
if ( element - > Attribute ( " successcodes " ) )
{
std : : string successCodes = element - > Attribute ( " successcodes " ) ;
results = tokenize ( successCodes , ' , ' ) ;
for ( auto & code : results )
{
std : : string tag = findTag ( code , tags ) ;
// on each success code: prepend 'e', strip "VK_" and a tag, convert it to camel case, and add the tag again
code = std : : string ( " e " ) + toCamelCase ( strip ( code , " VK_ " , tag ) ) + tag ;
}
}
return results ;
}
void readComment ( tinyxml2 : : XMLElement * element , std : : string & header )
{
assert ( ! element - > FirstAttribute ( ) & & ! element - > FirstChildElement ( ) ) ;
assert ( element - > GetText ( ) ) ;
std : : string text = element - > GetText ( ) ;
if ( text . find ( " \n Copyright " ) = = 0 )
{
assert ( header . empty ( ) ) ;
header = text ;
// erase the part after the Copyright text
size_t pos = header . find ( " \n \n ----- " ) ;
assert ( pos ! = std : : string : : npos ) ;
header . erase ( pos ) ;
// replace any '\n' with "\n// "
for ( size_t pos = header . find ( ' \n ' ) ; pos ! = std : : string : : npos ; pos = header . find ( ' \n ' , pos + 1 ) )
{
header . replace ( pos , 1 , " \n // " ) ;
}
// and add a little message on our own
header + = " \n \n // This header is generated from the Khronos Vulkan XML API Registry. " ;
}
}
void readEnums ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
if ( ! element - > Attribute ( " name " ) )
{
throw std : : runtime_error ( std : : string ( " spec error: enums element is missing the name attribute " ) ) ;
}
std : : string name = strip ( element - > Attribute ( " name " ) , " Vk " ) ;
if ( name = = " API Constants " )
{
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
readEnumsConstant ( child , vkData . constants ) ;
}
}
else
{
// add an empty DependencyData on this name into the dependencies list
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : ENUM , name ) ) ;
// ad an empty EnumData on this name into the enums map
std : : map < std : : string , EnumData > : : iterator it = vkData . enums . insert ( std : : make_pair ( name , EnumData ( name ) ) ) . first ;
if ( name = = " Result " )
{
// special handling for VKResult, as its enums just have VK_ in common
it - > second . prefix = " VK_ " ;
}
else
{
if ( ! element - > Attribute ( " type " ) )
{
throw std : : runtime_error ( std : : string ( " spec error: enums name= \" " + name + " \" is missing the type attribute " ) ) ;
}
std : : string type = element - > Attribute ( " type " ) ;
if ( type ! = " bitmask " & & type ! = " enum " )
{
throw std : : runtime_error ( std : : string ( " spec error: enums name= \" " + name + " \" has unknown type " + type ) ) ;
}
it - > second . bitmask = ( type = = " bitmask " ) ;
if ( it - > second . bitmask )
{
// for a bitmask enum, start with "VK", cut off the trailing "FlagBits", and convert that name to upper case
// end that with "Bit"
size_t pos = name . find ( " FlagBits " ) ;
assert ( pos ! = std : : string : : npos ) ;
it - > second . prefix = " VK " + toUpperCase ( name . substr ( 0 , pos ) ) + " _ " ;
}
else
{
// for a non-bitmask enum, start with "VK", and convert the name to upper case
it - > second . prefix = " VK " + toUpperCase ( name ) + " _ " ;
}
// if the enum name contains a tag move it from the prefix to the postfix to generate correct enum value names.
for ( std : : set < std : : string > : : const_iterator tit = vkData . tags . begin ( ) ; tit ! = vkData . tags . end ( ) ; + + tit )
{
if ( ( tit - > length ( ) < it - > second . prefix . length ( ) ) & & ( it - > second . prefix . substr ( it - > second . prefix . length ( ) - tit - > length ( ) - 1 ) = = ( * tit + " _ " ) ) )
{
it - > second . prefix . erase ( it - > second . prefix . length ( ) - tit - > length ( ) - 1 ) ;
it - > second . postfix = " _ " + * tit ;
break ;
}
else if ( ( tit - > length ( ) < it - > second . name . length ( ) ) & & ( it - > second . name . substr ( it - > second . name . length ( ) - tit - > length ( ) ) = = * tit ) )
{
it - > second . postfix = " _ " + * tit ;
break ;
}
}
}
readEnumsEnum ( element , it - > second , vkData . nameMap ) ;
// add this enum to the set of Vulkan data types
assert ( vkData . vkTypes . find ( name ) = = vkData . vkTypes . end ( ) ) ;
vkData . vkTypes . insert ( name ) ;
}
}
void readEnumsConstant ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > & constants )
{
assert ( ( strcmp ( element - > Value ( ) , " enum " ) = = 0 ) & & element - > Attribute ( " value " ) & & element - > Attribute ( " name " ) ) ;
std : : string name = element - > Attribute ( " name " ) ;
assert ( constants . find ( name ) = = constants . end ( ) ) ;
constants [ name ] = element - > Attribute ( " value " ) ;
}
void readEnumsEnum ( tinyxml2 : : XMLElement * element , EnumData & enumData , std : : map < std : : string , std : : string > & nameMap )
{
// read the names of the enum values
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
while ( child )
{
if ( child - > Attribute ( " name " ) )
{
enumData . addEnumValue ( child - > Attribute ( " name " ) , " " , nameMap ) ;
}
child = child - > NextSiblingElement ( ) ;
}
}
void readDisabledExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
std : : string value = child - > Value ( ) ;
if ( ( value = = " command " ) | | ( value = = " type " ) )
{
// disable a command or a type !
assert ( child - > Attribute ( " name " ) ) ;
std : : string name = ( value = = " command " ) ? startLowerCase ( strip ( child - > Attribute ( " name " ) , " vk " ) ) : strip ( child - > Attribute ( " name " ) , " Vk " ) ;
// search this name in the dependencies list and remove it
std : : list < DependencyData > : : const_iterator depIt = std : : find_if ( vkData . dependencies . begin ( ) , vkData . dependencies . end ( ) , [ & name ] ( DependencyData const & dd ) { return ( dd . name = = name ) ; } ) ;
assert ( depIt ! = vkData . dependencies . end ( ) ) ;
vkData . dependencies . erase ( depIt ) ;
// erase it from all dependency sets
for ( auto & dep : vkData . dependencies )
{
dep . dependencies . erase ( name ) ;
}
if ( value = = " command " )
{
// first unlink the command from its class
auto commandsIt = vkData . commands . find ( name ) ;
assert ( commandsIt ! = vkData . commands . end ( ) ) ;
assert ( ! commandsIt - > second . className . empty ( ) ) ;
auto handlesIt = vkData . handles . find ( commandsIt - > second . className ) ;
assert ( handlesIt ! = vkData . handles . end ( ) ) ;
auto it = std : : find ( handlesIt - > second . commands . begin ( ) , handlesIt - > second . commands . end ( ) , name ) ;
assert ( it ! = handlesIt - > second . commands . end ( ) ) ;
handlesIt - > second . commands . erase ( it ) ;
// then remove the command
vkData . commands . erase ( name ) ;
}
else
{
// a type simply needs to be removed from the structs and vkTypes sets
assert ( ( vkData . structs . find ( name ) ! = vkData . structs . end ( ) ) & & ( vkData . vkTypes . find ( name ) ! = vkData . vkTypes . end ( ) ) ) ;
vkData . structs . erase ( name ) ;
vkData . vkTypes . erase ( name ) ;
}
}
else
{
// nothing to do for enums, no other values ever encountered
assert ( value = = " enum " ) ;
}
}
}
void readExtensionAlias ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect , std : : string const & tag )
{
assert ( element - > Attribute ( " name " ) & & element - > Attribute ( " value " ) ) ;
std : : string name = element - > Attribute ( " name " ) ;
std : : string value = element - > Attribute ( " value " ) ;
auto commandsIt = vkData . commands . find ( startLowerCase ( strip ( value , " vk " ) ) ) ;
if ( commandsIt ! = vkData . commands . end ( ) )
{
// the alias is on a command -> add a command with that name
CommandData commandData = commandsIt - > second ;
commandData . fullName = startLowerCase ( strip ( name , " vk " ) ) ;
assert ( vkData . commands . find ( commandData . fullName ) = = vkData . commands . end ( ) ) ;
determineReducedName ( commandData ) ;
vkData . commands . insert ( std : : make_pair ( commandData . fullName , commandData ) ) ;
linkCommandToHandle ( vkData , commandData ) ;
// add an empty DependencyData to this name
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : COMMAND , commandData . fullName ) ) ;
}
else
{
auto constantsIt = vkData . constants . find ( value ) ;
if ( constantsIt ! = vkData . constants . end ( ) )
{
// alias on a constant -> just add it to the set of constants... we're doing nothing with them
auto it = vkData . constants . find ( name ) ;
assert ( ( vkData . constants . find ( name ) = = vkData . constants . end ( ) ) | | ( vkData . constants . find ( name ) - > second = = constantsIt - > second ) ) ;
vkData . constants [ name ] = constantsIt - > second ;
}
else
{
std : : string strippedValue = strip ( value , " Vk " ) ;
std : : string strippedName = strip ( name , " Vk " ) ;
auto enumsIt = vkData . enums . find ( strippedValue ) ;
if ( enumsIt ! = vkData . enums . end ( ) )
{
// the alias is on an enum -> set the alias, which will map to a using directive
assert ( vkData . enums . find ( strippedName ) = = vkData . enums . end ( ) ) ;
aliasType ( vkData , DependencyData : : Category : : ENUM , enumsIt - > first , strippedName , protect ) ;
}
else
{
auto flagsIt = vkData . flags . find ( strippedValue ) ;
if ( flagsIt ! = vkData . flags . end ( ) )
{
// the alias is on a flags -> set the alias, which will map to a using directive
assert ( vkData . flags . find ( strippedName ) = = vkData . flags . end ( ) ) ;
assert ( flagsIt - > second . alias . empty ( ) ) ;
flagsIt - > second . alias = strippedName ;
// adjust the generated enum name as well, if it's empty (and therefore auto-generated)
std : : string enumName = generateEnumNameForFlags ( strippedValue ) ;
std : : map < std : : string , EnumData > : : iterator enumsIt = vkData . enums . find ( enumName ) ;
assert ( enumsIt ! = vkData . enums . end ( ) ) ;
if ( enumsIt - > second . values . empty ( ) )
{
aliasType ( vkData , DependencyData : : Category : : ENUM , enumsIt - > first , generateEnumNameForFlags ( flagsIt - > second . alias ) , protect ) ;
}
}
else
{
auto handlesIt = vkData . handles . find ( strippedValue ) ;
if ( handlesIt ! = vkData . handles . end ( ) )
{
assert ( vkData . handles . find ( strippedName ) = = vkData . handles . end ( ) ) ;
assert ( handlesIt - > second . protect = = protect ) ;
assert ( handlesIt - > second . alias . empty ( ) ) ;
handlesIt - > second . alias = strippedName ;
}
else
{
auto structsIt = vkData . structs . find ( strippedValue ) ;
if ( structsIt ! = vkData . structs . end ( ) )
{
// the alias is on a structure -> set the alias, which will map to a using directive
assert ( vkData . structs . find ( strippedName ) = = vkData . structs . end ( ) ) ;
aliasType ( vkData , DependencyData : : Category : : STRUCT , structsIt - > first , strippedName , protect ) ;
}
else
{
// final catch: it has to be an enum value
bool found = false ;
for ( auto & e : vkData . enums )
{
auto valueIt = std : : find_if ( e . second . values . begin ( ) , e . second . values . end ( ) , [ & value ] ( EnumValueData const & evd ) { return evd . value = = value ; } ) ;
if ( valueIt ! = e . second . values . end ( ) )
{
assert ( std : : find_if ( e . second . values . begin ( ) , e . second . values . end ( ) , [ & name ] ( EnumValueData const & evd ) { return evd . value = = name ; } ) = = e . second . values . end ( ) ) ;
assert ( valueIt - > alias . empty ( ) ) ;
valueIt - > alias = createEnumValueName ( name , e . second . prefix , e . second . postfix , e . second . bitmask , tag ) ;
found = true ;
break ;
}
}
assert ( found ) ;
}
}
}
}
}
}
}
void readExtensionCommand ( tinyxml2 : : XMLElement * element , std : : map < std : : string , CommandData > & commands , std : : string const & protect )
{
// just add the protect string to the CommandData
if ( ! protect . empty ( ) )
{
assert ( element - > Attribute ( " name " ) ) ;
std : : string name = startLowerCase ( strip ( element - > Attribute ( " name " ) , " vk " ) ) ;
std : : map < std : : string , CommandData > : : iterator cit = commands . find ( name ) ;
assert ( cit ! = commands . end ( ) ) ;
cit - > second . protect = protect ;
}
}
void readExtensionEnum ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : string const & tag , std : : map < std : : string , std : : string > & nameMap )
{
// TODO process enums which don't extend existing enums
if ( element - > Attribute ( " extends " ) )
{
assert ( element - > Attribute ( " name " ) ) ;
std : : string extends = strip ( element - > Attribute ( " extends " ) , " Vk " ) ;
assert ( enums . find ( extends ) ! = enums . end ( ) ) ;
assert ( ! ! element - > Attribute ( " bitpos " ) + ! ! element - > Attribute ( " offset " ) + ! ! element - > Attribute ( " value " ) = = 1 ) ;
auto enumIt = enums . find ( extends ) ;
assert ( enumIt ! = enums . end ( ) ) ;
enumIt - > second . addEnumValue ( element - > Attribute ( " name " ) , tag , nameMap ) ;
}
}
void readExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect , std : : string const & tag )
{
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
std : : string value = child - > Value ( ) ;
if ( value = = " alias " )
{
readExtensionAlias ( child , vkData , protect , tag ) ;
}
else if ( value = = " command " )
{
readExtensionCommand ( child , vkData . commands , protect ) ;
}
else if ( value = = " type " )
{
readExtensionType ( child , vkData , protect ) ;
}
else if ( value = = " enum " )
{
readExtensionEnum ( child , vkData . enums , tag , vkData . nameMap ) ;
}
else
{
assert ( ( value = = " comment " ) | | ( value = = " usage " ) ) ;
}
}
}
void readExtensions ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( strcmp ( child - > Value ( ) , " extension " ) = = 0 ) ;
readExtensionsExtension ( child , vkData ) ;
}
}
void readExtensionsExtension ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
if ( strcmp ( element - > Attribute ( " supported " ) , " disabled " ) = = 0 )
{
// kick out all the disabled stuff we've read before !!
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( strcmp ( child - > Value ( ) , " require " ) = = 0 ) ;
readDisabledExtensionRequire ( child , vkData ) ;
}
}
else
{
assert ( element - > Attribute ( " name " ) ) ;
std : : string name = element - > Attribute ( " name " ) ;
std : : string tag = extractTag ( name ) ;
assert ( vkData . tags . find ( tag ) ! = vkData . tags . end ( ) ) ;
std : : string protect ;
if ( element - > Attribute ( " protect " ) )
{
protect = element - > Attribute ( " protect " ) ;
}
else if ( element - > Attribute ( " platform " ) )
{
assert ( element - > Attribute ( " author " ) ) ;
protect = " VK_USE_PLATFORM_ " + toUpperCase ( element - > Attribute ( " platform " ) ) + " _ " + element - > Attribute ( " author " ) ;
}
# if !defined(NDEBUG)
assert ( vkData . extensions . find ( name ) = = vkData . extensions . end ( ) ) ;
ExtensionData & extension = vkData . extensions . insert ( std : : make_pair ( name , ExtensionData ( ) ) ) . first - > second ;
extension . protect = protect ;
if ( element - > Attribute ( " requires " ) )
{
extension . requires = tokenize ( element - > Attribute ( " requires " ) , ' , ' ) ;
}
# endif
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( strcmp ( child - > Value ( ) , " require " ) = = 0 ) ;
readExtensionRequire ( child , vkData , protect , tag ) ;
}
}
}
void readExtensionType ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect )
{
// add the protect-string to the appropriate type: enum, flag, handle, scalar, or struct
if ( ! protect . empty ( ) )
{
assert ( element - > Attribute ( " name " ) ) ;
std : : string name = strip ( element - > Attribute ( " name " ) , " Vk " ) ;
std : : map < std : : string , EnumData > : : iterator eit = vkData . enums . find ( name ) ;
if ( eit ! = vkData . enums . end ( ) )
{
eit - > second . protect = protect ;
}
else
{
std : : map < std : : string , FlagData > : : iterator fit = vkData . flags . find ( name ) ;
if ( fit ! = vkData . flags . end ( ) )
{
fit - > second . protect = protect ;
// if the enum of this flags is auto-generated, protect it as well
std : : string enumName = generateEnumNameForFlags ( name ) ;
std : : map < std : : string , EnumData > : : iterator eit = vkData . enums . find ( enumName ) ;
assert ( eit ! = vkData . enums . end ( ) ) ;
if ( eit - > second . values . empty ( ) )
{
eit - > second . protect = protect ;
}
}
else
{
std : : map < std : : string , HandleData > : : iterator hait = vkData . handles . find ( name ) ;
if ( hait ! = vkData . handles . end ( ) )
{
hait - > second . protect = protect ;
}
else
{
std : : map < std : : string , ScalarData > : : iterator scit = vkData . scalars . find ( name ) ;
if ( scit ! = vkData . scalars . end ( ) )
{
scit - > second . protect = protect ;
}
else
{
std : : map < std : : string , StructData > : : iterator stit = vkData . structs . find ( name ) ;
if ( stit ! = vkData . structs . end ( ) )
{
stit - > second . protect = protect ;
}
else
{
assert ( vkData . defines . find ( name ) ! = vkData . defines . end ( ) ) ;
}
}
}
}
}
}
}
void readFeature ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : map < std : : string , std : : string > & nameMap )
{
assert ( element - > Attribute ( " api " ) & & ( strcmp ( element - > Attribute ( " api " ) , " vulkan " ) = = 0 ) ) ;
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( child - > Value ( ) ) ;
std : : string value = child - > Value ( ) ;
assert ( value = = " require " ) ;
readFeatureRequire ( child , enums , nameMap ) ;
}
}
void readFeatureRequire ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : map < std : : string , std : : string > & nameMap )
{
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( child - > Value ( ) ) ;
std : : string value = child - > Value ( ) ;
if ( value = = " enum " )
{
readFeatureRequireEnum ( child , enums , nameMap ) ;
}
else
{
assert ( ( value = = " command " ) | | ( value = = " type " ) ) ;
}
}
}
void readFeatureRequireEnum ( tinyxml2 : : XMLElement * element , std : : map < std : : string , EnumData > & enums , std : : map < std : : string , std : : string > & nameMap )
{
if ( element - > Attribute ( " extends " ) )
{
assert ( ( strncmp ( element - > Attribute ( " extends " ) , " Vk " , 2 ) = = 0 ) & & element - > Attribute ( " name " ) ) ;
std : : string extends = strip ( element - > Attribute ( " extends " ) , " Vk " ) ;
auto enumIt = enums . find ( extends ) ;
assert ( enumIt ! = enums . end ( ) ) ;
enumIt - > second . addEnumValue ( element - > Attribute ( " name " ) , " " , nameMap ) ;
}
}
tinyxml2 : : XMLNode * readType ( tinyxml2 : : XMLNode * element , std : : string & type , std : : string & pureType )
{
assert ( element ) ;
if ( element - > ToText ( ) )
{
std : : string value = trim ( element - > Value ( ) ) ;
assert ( ( value = = " const " ) | | ( value = = " struct " ) ) ;
type = value + " " ;
element = element - > NextSibling ( ) ;
assert ( element ) ;
}
assert ( element - > ToElement ( ) ) ;
assert ( ( strcmp ( element - > Value ( ) , " type " ) = = 0 ) & & element - > ToElement ( ) & & element - > ToElement ( ) - > GetText ( ) ) ;
pureType = strip ( element - > ToElement ( ) - > GetText ( ) , " Vk " ) ;
type + = pureType ;
element = element - > NextSibling ( ) ;
assert ( element ) ;
if ( element - > ToText ( ) )
{
std : : string value = trimEnd ( element - > Value ( ) ) ;
assert ( ( value = = " * " ) | | ( value = = " ** " ) | | ( value = = " * const* " ) ) ;
type + = value ;
element = element - > NextSibling ( ) ;
}
return element ;
}
void readTypeBasetype ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies , std : : map < std : : string , std : : string > const & attributes )
{
assert ( ( attributes . size ( ) = = 1 ) & & ( attributes . find ( " category " ) ! = attributes . end ( ) ) & & ( attributes . find ( " category " ) - > second = = " basetype " ) ) ;
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ! typeElement - > FirstAttribute ( ) & & ( strcmp ( typeElement - > Value ( ) , " type " ) = = 0 ) & & typeElement - > GetText ( ) ) ;
std : : string type = typeElement - > GetText ( ) ;
assert ( ( type = = " uint32_t " ) | | ( type = = " uint64_t " ) ) ;
tinyxml2 : : XMLElement * nameElement = typeElement - > NextSiblingElement ( ) ;
assert ( nameElement & & ! nameElement - > FirstAttribute ( ) & & ( strcmp ( nameElement - > Value ( ) , " name " ) = = 0 ) & & nameElement - > GetText ( ) ) ;
std : : string name = strip ( nameElement - > GetText ( ) , " Vk " ) ;
assert ( ! nameElement - > NextSiblingElement ( ) ) ;
// skip "Flags",
if ( name ! = " Flags " )
{
dependencies . push_back ( DependencyData ( DependencyData : : Category : : SCALAR , name ) ) ;
dependencies . back ( ) . dependencies . insert ( type ) ;
}
else
{
assert ( type = = " uint32_t " ) ;
}
}
void readTypeBitmask ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : map < std : : string , std : : string > const & attributes )
{
assert ( ( attributes . find ( " category " ) ! = attributes . end ( ) ) & & ( attributes . find ( " category " ) - > second = = " bitmask " ) ) ;
assert ( ( attributes . size ( ) = = 1 ) | | ( ( attributes . size ( ) = = 2 ) & & ( attributes . find ( " requires " ) ! = attributes . end ( ) ) ) ) ;
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ! typeElement - > FirstAttribute ( ) & & ( strcmp ( typeElement - > Value ( ) , " type " ) = = 0 ) & & typeElement - > GetText ( ) & & ( strcmp ( typeElement - > GetText ( ) , " VkFlags " ) = = 0 ) ) ;
std : : string type = typeElement - > GetText ( ) ;
tinyxml2 : : XMLElement * nameElement = typeElement - > NextSiblingElement ( ) ;
assert ( nameElement & & ! nameElement - > FirstAttribute ( ) & & ( strcmp ( nameElement - > Value ( ) , " name " ) = = 0 ) & & nameElement - > GetText ( ) ) ;
std : : string name = strip ( nameElement - > GetText ( ) , " Vk " ) ;
assert ( ! nameElement - > NextSiblingElement ( ) ) ;
std : : string requires ;
auto requiresIt = attributes . find ( " requires " ) ;
if ( requiresIt ! = attributes . end ( ) )
{
requires = strip ( requiresIt - > second , " Vk " ) ;
}
else
{
// Generate FlagBits name, add a DependencyData for that name, and add it to the list of enums and vulkan types
requires = generateEnumNameForFlags ( name ) ;
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : ENUM , requires ) ) ;
vkData . enums . insert ( std : : make_pair ( requires , EnumData ( requires , true ) ) ) ;
vkData . vkTypes . insert ( requires ) ;
}
// add a DependencyData for the bitmask name, with the required type as its first dependency
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : FLAGS , name ) ) ;
vkData . dependencies . back ( ) . dependencies . insert ( requires ) ;
vkData . flags . insert ( std : : make_pair ( name , FlagData ( ) ) ) ;
assert ( vkData . vkTypes . find ( name ) = = vkData . vkTypes . end ( ) ) ;
vkData . vkTypes . insert ( name ) ;
}
void readTypeDefine ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : map < std : : string , std : : string > const & attributes )
{
assert ( ( attributes . find ( " category " ) ! = attributes . end ( ) ) & & ( attributes . find ( " category " ) - > second = = " define " ) ) ;
assert ( ( attributes . size ( ) = = 1 ) | | ( ( attributes . size ( ) = = 2 ) & & ( attributes . find ( " name " ) ! = attributes . end ( ) ) ) ) ;
auto nameIt = attributes . find ( " name " ) ;
if ( nameIt ! = attributes . end ( ) )
{
assert ( ! element - > FirstChildElement ( ) ) ;
assert ( nameIt - > second = = " VK_DEFINE_NON_DISPATCHABLE_HANDLE " ) ;
// filter out the check for the different types of VK_DEFINE_NON_DISPATCHABLE_HANDLE
std : : string text = element - > LastChild ( ) - > ToText ( ) - > Value ( ) ;
size_t start = text . find ( " #if defined(__LP64__) " ) ;
size_t end = text . find_first_of ( " \r \n " , start + 1 ) ;
vkData . typesafeCheck = text . substr ( start , end - start ) ;
}
else if ( element - > GetText ( ) & & ( trim ( element - > GetText ( ) ) = = " struct " ) )
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ( strcmp ( child - > Value ( ) , " name " ) = = 0 ) & & child - > GetText ( ) ) ;
vkData . defines . insert ( child - > GetText ( ) ) ;
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : REQUIRED , child - > GetText ( ) ) ) ;
}
else
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ! child - > FirstAttribute ( ) & & ( strcmp ( child - > Value ( ) , " name " ) = = 0 ) & & child - > GetText ( ) ) ;
std : : string text = trim ( child - > GetText ( ) ) ;
if ( text = = " VK_HEADER_VERSION " )
{
vkData . version = element - > LastChild ( ) - > ToText ( ) - > Value ( ) ;
}
// ignore all the other defines
assert ( ! child - > NextSiblingElement ( ) | | ( child - > NextSiblingElement ( ) & & ! child - > NextSiblingElement ( ) - > FirstAttribute ( ) & & ( strcmp ( child - > NextSiblingElement ( ) - > Value ( ) , " type " ) = = 0 ) & & ! child - > NextSiblingElement ( ) - > NextSiblingElement ( ) ) ) ;
}
}
void readTypeFuncpointer ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies )
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ( strcmp ( child - > Value ( ) , " name " ) = = 0 ) & & child - > GetText ( ) ) ;
dependencies . push_back ( DependencyData ( DependencyData : : Category : : FUNC_POINTER , child - > GetText ( ) ) ) ;
}
void readTypeHandle ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : map < std : : string , std : : string > const & attributes )
{
assert ( ( attributes . find ( " category " ) ! = attributes . end ( ) ) & & ( attributes . find ( " category " ) - > second = = " handle " ) ) ;
assert ( ( attributes . size ( ) = = 1 ) | | ( ( attributes . size ( ) = = 2 ) & & ( attributes . find ( " parent " ) ! = attributes . end ( ) ) ) ) ;
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ! typeElement - > FirstAttribute ( ) & & ( strcmp ( typeElement - > Value ( ) , " type " ) = = 0 ) & & typeElement - > GetText ( ) ) ;
# if !defined(NDEBUG)
std : : string type = typeElement - > GetText ( ) ;
assert ( ( type . find ( " VK_DEFINE_HANDLE " ) = = 0 ) | | ( type . find ( " VK_DEFINE_NON_DISPATCHABLE_HANDLE " ) = = 0 ) ) ;
# endif
tinyxml2 : : XMLElement * nameElement = typeElement - > NextSiblingElement ( ) ;
assert ( nameElement & & ! nameElement - > FirstAttribute ( ) & & ( strcmp ( nameElement - > Value ( ) , " name " ) = = 0 ) & & nameElement - > GetText ( ) ) ;
std : : string name = strip ( nameElement - > GetText ( ) , " Vk " ) ;
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : HANDLE , name ) ) ;
assert ( vkData . vkTypes . find ( name ) = = vkData . vkTypes . end ( ) ) ;
vkData . vkTypes . insert ( name ) ;
assert ( vkData . handles . find ( name ) = = vkData . handles . end ( ) ) ;
vkData . handles [ name ] ;
}
void readTypeStruct ( tinyxml2 : : XMLElement * element , VkData & vkData , bool isUnion )
{
assert ( ! element - > Attribute ( " returnedonly " ) | | ( strcmp ( element - > Attribute ( " returnedonly " ) , " true " ) = = 0 ) ) ;
assert ( element - > Attribute ( " name " ) ) ;
std : : string name = strip ( element - > Attribute ( " name " ) , " Vk " ) ;
vkData . dependencies . push_back ( DependencyData ( isUnion ? DependencyData : : Category : : UNION : DependencyData : : Category : : STRUCT , name ) ) ;
assert ( vkData . structs . find ( name ) = = vkData . structs . end ( ) ) ;
std : : map < std : : string , StructData > : : iterator it = vkData . structs . insert ( std : : make_pair ( name , StructData ( ) ) ) . first ;
it - > second . returnedOnly = ! ! element - > Attribute ( " returnedonly " ) ;
it - > second . isUnion = isUnion ;
if ( element - > Attribute ( " structextends " ) )
{
std : : vector < std : : string > structExtends = tokenize ( element - > Attribute ( " structextends " ) , ' , ' ) ;
for ( auto const & s : structExtends )
{
assert ( s . substr ( 0 , 2 ) = = " Vk " ) ;
std : : string strippedName = s . substr ( 2 ) ;
it - > second . structExtends . push_back ( strippedName ) ;
vkData . extendedStructs . insert ( strippedName ) ;
}
assert ( ! it - > second . structExtends . empty ( ) ) ;
}
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( child - > Value ( ) ) ;
std : : string value = child - > Value ( ) ;
assert ( ( value = = " comment " ) | | ( value = = " member " ) ) ;
if ( value = = " member " )
{
readTypeStructMember ( child , vkData , it - > second ) ;
}
}
assert ( vkData . vkTypes . find ( name ) = = vkData . vkTypes . end ( ) ) ;
vkData . vkTypes . insert ( name ) ;
}
void readTypeStructMember ( tinyxml2 : : XMLElement * element , VkData & vkData , StructData & structData )
{
structData . members . push_back ( MemberData ( ) ) ;
MemberData & member = structData . members . back ( ) ;
char const * values = element - > Attribute ( " values " ) ;
if ( values )
{
member . values = values ;
}
tinyxml2 : : XMLNode * child = readType ( element - > FirstChild ( ) , member . type , member . pureType ) ;
vkData . dependencies . back ( ) . dependencies . insert ( member . pureType ) ;
assert ( ( child - > ToElement ( ) & & strcmp ( child - > Value ( ) , " name " ) = = 0 ) ) ;
member . name = child - > ToElement ( ) - > GetText ( ) ;
member . arraySize = readArraySize ( child , member . name ) ;
}
void readTag ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & tags )
{
for ( auto attribute = element - > FirstAttribute ( ) ; attribute ; attribute = attribute - > Next ( ) )
{
std : : string name = attribute - > Name ( ) ;
if ( name = = " name " )
{
std : : string value = attribute - > Value ( ) ;
tags . insert ( value ) ;
}
else
{
assert ( ( name = = " author " ) | | ( name = = " contact " ) ) ;
}
}
assert ( ! element - > FirstChildElement ( ) ) ;
}
void readTags ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & tags )
{
assert ( element - > FirstAttribute ( ) & & ! element - > FirstAttribute ( ) - > Next ( ) ) ;
assert ( strcmp ( element - > FirstAttribute ( ) - > Name ( ) , " comment " ) = = 0 ) ;
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
std : : string value = child - > Value ( ) ;
assert ( value = = " tag " ) ;
readTag ( child , tags ) ;
}
}
void readType ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
std : : map < std : : string , std : : string > attributes ;
for ( auto attribute = element - > FirstAttribute ( ) ; attribute ; attribute = attribute - > Next ( ) )
{
assert ( attributes . find ( attribute - > Name ( ) ) = = attributes . end ( ) ) ;
attributes [ attribute - > Name ( ) ] = attribute - > Value ( ) ;
}
auto categoryIt = attributes . find ( " category " ) ;
if ( categoryIt ! = attributes . end ( ) )
{
if ( categoryIt - > second = = " basetype " )
{
readTypeBasetype ( element , vkData . dependencies , attributes ) ;
}
else if ( categoryIt - > second = = " bitmask " )
{
readTypeBitmask ( element , vkData , attributes ) ;
}
# if !defined(NDEBUG)
else if ( categoryIt - > second = = " enum " )
{
skipTypeEnum ( element , attributes ) ;
}
# endif
else if ( categoryIt - > second = = " define " )
{
readTypeDefine ( element , vkData , attributes ) ;
}
else if ( categoryIt - > second = = " funcpointer " )
{
readTypeFuncpointer ( element , vkData . dependencies ) ;
}
else if ( categoryIt - > second = = " handle " )
{
readTypeHandle ( element , vkData , attributes ) ;
}
# if !defined(NDEBUG)
else if ( categoryIt - > second = = " include " )
{
skipTypeInclude ( element , attributes ) ;
}
# endif
else if ( categoryIt - > second = = " struct " )
{
readTypeStruct ( element , vkData , false ) ;
}
else if ( categoryIt - > second = = " union " )
{
readTypeStruct ( element , vkData , true ) ;
}
else
{
assert ( false ) ;
}
}
else
{
auto nameIt = attributes . find ( " name " ) ;
assert ( nameIt ! = attributes . end ( ) ) ;
readTypeName ( element , attributes , vkData . dependencies ) ;
}
}
void readTypeName ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > const & attributes , std : : list < DependencyData > & dependencies )
{
assert ( ( attributes . size ( ) = = 1 ) | | ( ( attributes . size ( ) = = 2 ) & & ( attributes . find ( " requires " ) ! = attributes . end ( ) ) ) ) ;
assert ( ! element - > FirstChildElement ( ) ) ;
auto nameIt = attributes . find ( " name " ) ;
assert ( nameIt ! = attributes . end ( ) ) ;
dependencies . push_back ( DependencyData ( DependencyData : : Category : : REQUIRED , nameIt - > second ) ) ;
}
void readTypes ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
assert ( element - > FirstAttribute ( ) & & ! element - > FirstAttribute ( ) - > Next ( ) ) ;
assert ( strcmp ( element - > FirstAttribute ( ) - > Name ( ) , " comment " ) = = 0 ) ;
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( child - > Value ( ) ) ;
std : : string value = child - > Value ( ) ;
if ( value = = " type " )
{
readType ( child , vkData ) ;
}
else
{
assert ( value = = " comment " ) ;
}
}
}
std : : string reduceName ( std : : string const & name , bool singular )
{
std : : string reducedName ;
if ( ( name [ 0 ] = = ' p ' ) & & ( 1 < name . length ( ) ) & & ( isupper ( name [ 1 ] ) | | name [ 1 ] = = ' p ' ) )
{
reducedName = strip ( name , " p " ) ;
reducedName [ 0 ] = tolower ( reducedName [ 0 ] ) ;
}
else
{
reducedName = name ;
}
if ( singular )
{
size_t pos = reducedName . rfind ( ' s ' ) ;
assert ( pos ! = std : : string : : npos ) ;
reducedName . erase ( pos , 1 ) ;
}
return reducedName ;
}
void registerDeleter ( VkData & vkData , CommandData const & commandData )
{
if ( ( commandData . fullName . substr ( 0 , 7 ) = = " destroy " ) | | ( commandData . fullName . substr ( 0 , 4 ) = = " free " ) )
{
std : : string key ;
size_t valueIndex ;
switch ( commandData . params . size ( ) )
{
case 2 :
case 3 :
assert ( commandData . params . back ( ) . pureType = = " AllocationCallbacks " ) ;
key = ( commandData . params . size ( ) = = 2 ) ? " " : commandData . params [ 0 ] . pureType ;
valueIndex = commandData . params . size ( ) - 2 ;
break ;
case 4 :
key = commandData . params [ 0 ] . pureType ;
valueIndex = 3 ;
assert ( vkData . deleters . find ( commandData . params [ valueIndex ] . pureType ) = = vkData . deleters . end ( ) ) ;
vkData . deleters [ commandData . params [ valueIndex ] . pureType ] . pool = commandData . params [ 1 ] . pureType ;
break ;
default :
assert ( false ) ;
}
if ( commandData . fullName = = " destroyDevice " )
{
key = " PhysicalDevice " ;
}
assert ( vkData . deleterTypes [ key ] . find ( commandData . params [ valueIndex ] . pureType ) = = vkData . deleterTypes [ key ] . end ( ) ) ;
vkData . deleterTypes [ key ] . insert ( commandData . params [ valueIndex ] . pureType ) ;
vkData . deleters [ commandData . params [ valueIndex ] . pureType ] . call = commandData . reducedName ;
}
}
void sortDependencies ( std : : list < DependencyData > & dependencies )
{
std : : set < std : : string > listedTypes = { " VkFlags " } ;
std : : list < DependencyData > sortedDependencies ;
while ( ! dependencies . empty ( ) )
{
bool found = false ;
for ( std : : list < DependencyData > : : iterator it = dependencies . begin ( ) ; it ! = dependencies . end ( ) ; + + it )
{
if ( std : : find_if ( it - > dependencies . begin ( ) , it - > dependencies . end ( ) , [ & listedTypes ] ( std : : string const & d ) { return listedTypes . find ( d ) = = listedTypes . end ( ) ; } ) = = it - > dependencies . end ( ) )
{
sortedDependencies . push_back ( * it ) ;
listedTypes . insert ( it - > name ) ;
dependencies . erase ( it ) ;
found = true ;
break ;
}
}
if ( ! found )
{
// resolve direct circular dependencies
for ( std : : list < DependencyData > : : iterator it = dependencies . begin ( ) ; ! found & & it ! = dependencies . end ( ) ; + + it )
{
for ( std : : set < std : : string > : : const_iterator dit = it - > dependencies . begin ( ) ; dit ! = it - > dependencies . end ( ) ; + + dit )
{
std : : list < DependencyData > : : const_iterator depIt = std : : find_if ( dependencies . begin ( ) , dependencies . end ( ) , [ & dit ] ( DependencyData const & dd ) { return ( dd . name = = * dit ) ; } ) ;
if ( depIt ! = dependencies . end ( ) )
{
if ( depIt - > dependencies . find ( it - > name ) ! = depIt - > dependencies . end ( ) )
{
// we only have just one case, for now!
assert ( ( it - > category = = DependencyData : : Category : : HANDLE ) & & ( depIt - > category = = DependencyData : : Category : : STRUCT ) ) ;
it - > forwardDependencies . insert ( * dit ) ;
it - > dependencies . erase ( * dit ) ;
found = true ;
break ;
}
}
# if !defined(NDEBUG)
else
{
assert ( std : : find_if ( sortedDependencies . begin ( ) , sortedDependencies . end ( ) , [ & dit ] ( DependencyData const & dd ) { return ( dd . name = = * dit ) ; } ) ! = sortedDependencies . end ( ) ) ;
}
# endif
}
}
}
assert ( found ) ;
}
dependencies . swap ( sortedDependencies ) ;
}
std : : string startLowerCase ( std : : string const & input )
{
return static_cast < char > ( tolower ( input [ 0 ] ) ) + input . substr ( 1 ) ;
}
std : : string startUpperCase ( std : : string const & input )
{
return static_cast < char > ( toupper ( input [ 0 ] ) ) + input . substr ( 1 ) ;
}
bool beginsWith ( std : : string const & text , std : : string const & prefix )
{
return ! prefix . empty ( ) & & text . substr ( 0 , prefix . length ( ) ) = = prefix ;
}
bool endsWith ( std : : string const & text , std : : string const & postfix )
{
return ! postfix . empty ( ) & & ( postfix . length ( ) < text . length ( ) ) & & ( text . substr ( text . length ( ) - postfix . length ( ) ) = = postfix ) ;
}
std : : string strip ( std : : string const & value , std : : string const & prefix , std : : string const & postfix )
{
std : : string strippedValue = value ;
if ( beginsWith ( strippedValue , prefix ) )
{
strippedValue . erase ( 0 , prefix . length ( ) ) ;
}
if ( endsWith ( strippedValue , postfix ) )
{
strippedValue . erase ( strippedValue . length ( ) - postfix . length ( ) ) ;
}
return strippedValue ;
}
std : : string stripPluralS ( std : : string const & name )
{
std : : string strippedName ( name ) ;
size_t pos = strippedName . rfind ( ' s ' ) ;
assert ( pos ! = std : : string : : npos ) ;
strippedName . erase ( pos , 1 ) ;
return strippedName ;
}
std : : string toCamelCase ( std : : string const & value )
{
assert ( ! value . empty ( ) & & ( isupper ( value [ 0 ] ) | | isdigit ( value [ 0 ] ) ) ) ;
std : : string result ;
result . reserve ( value . size ( ) ) ;
result . push_back ( value [ 0 ] ) ;
for ( size_t i = 1 ; i < value . size ( ) ; i + + )
{
if ( value [ i ] ! = ' _ ' )
{
if ( ( value [ i - 1 ] = = ' _ ' ) | | isdigit ( value [ i - 1 ] ) )
{
result . push_back ( value [ i ] ) ;
}
else
{
result . push_back ( tolower ( value [ i ] ) ) ;
}
}
}
return result ;
}
std : : vector < std : : string > tokenize ( std : : string tokenString , char separator )
{
std : : vector < std : : string > tokens ;
size_t start = 0 , end ;
do
{
end = tokenString . find ( separator , start ) ;
tokens . push_back ( tokenString . substr ( start , end - start ) ) ;
start = end + 1 ;
} while ( end ! = std : : string : : npos ) ;
return tokens ;
}
std : : string toUpperCase ( std : : string const & name )
{
std : : string convertedName ;
for ( size_t i = 0 ; i < name . length ( ) ; i + + )
{
if ( isupper ( name [ i ] ) & & ( ( i = = 0 ) | | islower ( name [ i - 1 ] ) | | isdigit ( name [ i - 1 ] ) ) )
{
convertedName . push_back ( ' _ ' ) ;
}
convertedName . push_back ( toupper ( name [ i ] ) ) ;
}
return convertedName ;
}
std : : string trim ( std : : string const & input )
{
std : : string result = input ;
result . erase ( result . begin ( ) , std : : find_if ( result . begin ( ) , result . end ( ) , [ ] ( char c ) { return ! std : : isspace ( c ) ; } ) ) ;
result . erase ( std : : find_if ( result . rbegin ( ) , result . rend ( ) , [ ] ( char c ) { return ! std : : isspace ( c ) ; } ) . base ( ) , result . end ( ) ) ;
return result ;
}
// trim from end
std : : string trimEnd ( std : : string const & input )
{
std : : string result = input ;
result . erase ( std : : find_if ( result . rbegin ( ) , result . rend ( ) , [ ] ( char c ) { return ! std : : isspace ( c ) ; } ) . base ( ) , result . end ( ) ) ;
return result ;
}
std : : string generateCall ( CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular )
{
std : : ostringstream call ;
writeCall ( call , commandData , vkTypes , firstCall , singular ) ;
return call . str ( ) ;
}
void writeCall ( std : : ostream & os , CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular )
{
// get the parameter indices of the counter for vector parameters
std : : map < size_t , size_t > countIndices ;
for ( std : : map < size_t , size_t > : : const_iterator it = commandData . vectorParams . begin ( ) ; it ! = commandData . vectorParams . end ( ) ; + + it )
{
countIndices . insert ( std : : make_pair ( it - > second , it - > first ) ) ;
}
// the original function call
os < < " vk " < < startUpperCase ( commandData . fullName ) < < " ( " ;
if ( ! commandData . className . empty ( ) )
{
// if it's member of a class -> add the first parameter with "m_" as prefix
os < < " m_ " < < commandData . params [ 0 ] . name ;
}
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
{
if ( 0 < i )
{
os < < " , " ;
}
std : : map < size_t , size_t > : : const_iterator it = countIndices . find ( i ) ;
if ( it ! = countIndices . end ( ) )
{
writeCallCountParameter ( os , commandData , singular , it ) ;
}
else if ( ( it = commandData . vectorParams . find ( i ) ) ! = commandData . vectorParams . end ( ) )
{
writeCallVectorParameter ( os , commandData , vkTypes , firstCall , singular , it ) ;
}
else if ( vkTypes . find ( commandData . params [ i ] . pureType ) ! = vkTypes . end ( ) )
{
writeCallVulkanTypeParameter ( os , commandData . params [ i ] ) ;
}
else
{
writeCallPlainTypeParameter ( os , commandData . params [ i ] ) ;
}
}
os < < " ) " ;
}
void writeCallCountParameter ( std : : ostream & os , CommandData const & commandData , bool singular , std : : map < size_t , size_t > : : const_iterator it )
{
// this parameter is a count parameter for a vector parameter
if ( ( commandData . returnParam = = it - > second ) & & commandData . twoStep )
{
// the corresponding vector parameter is the return parameter and it's a two-step algorithm
// -> use the pointer to a local variable named like the counter parameter without leading 'p'
os < < " & " < < startLowerCase ( strip ( commandData . params [ it - > first ] . name , " p " ) ) ;
}
else
{
// the corresponding vector parameter is not the return parameter, or it's not a two-step algorithm
if ( singular )
{
// for the singular version, the count is just 1.
os < < " 1 " ;
}
else
{
// for the non-singular version, the count is the size of the vector parameter
// -> use the vector parameter name without leading 'p' to get the size (in number of elements, not in bytes)
os < < startLowerCase ( strip ( commandData . params [ it - > second ] . name , " p " ) ) < < " .size() " ;
}
if ( commandData . templateParam = = it - > second )
{
// if the vector parameter is templatized -> multiply by the size of that type to get the size in bytes
os < < " * sizeof( T ) " ;
}
}
}
void writeCallPlainTypeParameter ( std : : ostream & os , ParamData const & paramData )
{
// this parameter is just a plain type
if ( paramData . type . back ( ) = = ' * ' )
{
// it's a pointer
std : : string parameterName = startLowerCase ( strip ( paramData . name , " p " ) ) ;
if ( paramData . type . find ( " const " ) ! = std : : string : : npos )
{
// it's a const pointer
if ( paramData . pureType = = " char " )
{
// it's a const pointer to char -> it's a string -> get the data via c_str()
os < < parameterName ;
if ( paramData . optional )
{
// it's optional -> might use nullptr
os < < " ? " < < parameterName < < " ->c_str() : nullptr " ;
}
else
{
os < < " .c_str() " ;
}
}
else
{
// it's const pointer to void (only other type that occurs) -> just use the name
assert ( ( paramData . pureType = = " void " ) & & ! paramData . optional ) ;
os < < paramData . name ;
}
}
else
{
// it's a non-const pointer, and char is the only type that occurs -> use the address of the parameter
assert ( paramData . type . find ( " char " ) = = std : : string : : npos ) ;
os < < " & " < < parameterName ;
}
}
else
{
// it's a plain parameter -> just use its name
os < < paramData . name ;
}
}
void writeCallVectorParameter ( std : : ostream & os , CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular , std : : map < size_t , size_t > : : const_iterator it )
{
// this parameter is a vector parameter
assert ( commandData . params [ it - > first ] . type . back ( ) = = ' * ' ) ;
if ( ( commandData . returnParam = = it - > first ) & & commandData . twoStep & & firstCall )
{
// this parameter is the return parameter, and it's the first call of a two-step algorithm -> just just nullptr
os < < " nullptr " ;
}
else
{
std : : string parameterName = startLowerCase ( strip ( commandData . params [ it - > first ] . name , " p " ) ) ;
std : : set < std : : string > : : const_iterator vkit = vkTypes . find ( commandData . params [ it - > first ] . pureType ) ;
if ( ( vkit ! = vkTypes . end ( ) ) | | ( it - > first = = commandData . templateParam ) )
{
// CHECK for !commandData.params[it->first].optional
// this parameter is a vulkan type or a templated type -> need to reinterpret cast
writeReinterpretCast ( os , commandData . params [ it - > first ] . type . find ( " const " ) = = 0 , vkit ! = vkTypes . end ( ) , commandData . params [ it - > first ] . pureType ,
commandData . params [ it - > first ] . type . rfind ( " * const " ) ! = std : : string : : npos ) ;
os < < " ( " ;
if ( singular )
{
// in singular case, strip the plural-S from the name, and use the pointer to that thing
os < < " & " < < stripPluralS ( parameterName ) ;
}
else
{
// in plural case, get the pointer to the data
os < < parameterName < < " .data() " ;
}
os < < " ) " ;
}
else if ( commandData . params [ it - > first ] . pureType = = " char " )
{
// the parameter is a vector to char -> it might be optional
// besides that, the parameter now is a std::string -> get the pointer via c_str()
os < < parameterName ;
if ( commandData . params [ it - > first ] . optional )
{
os < < " ? " < < parameterName < < " ->c_str() : nullptr " ;
}
else
{
os < < " .c_str() " ;
}
}
else
{
// this parameter is just a vetor -> get the pointer to its data
os < < parameterName < < " .data() " ;
}
}
}
void writeCallVulkanTypeParameter ( std : : ostream & os , ParamData const & paramData )
{
// this parameter is a vulkan type
if ( paramData . type . back ( ) = = ' * ' )
{
// it's a pointer -> needs a reinterpret cast to the vulkan type
std : : string parameterName = startLowerCase ( strip ( paramData . name , " p " ) ) ;
writeReinterpretCast ( os , paramData . type . find ( " const " ) ! = std : : string : : npos , true , paramData . pureType , false ) ;
os < < " ( " ;
if ( paramData . optional )
{
// for an optional parameter, we need also a static_cast from optional type to const-pointer to pure type
os < < " static_cast<const " < < paramData . pureType < < " *>( " < < parameterName < < " ) " ;
}
else
{
// other parameters can just use the pointer
os < < " & " < < parameterName ;
}
os < < " ) " ;
}
else
{
// a non-pointer parameter needs a static_cast from vk::-type to vulkan type
os < < " static_cast<Vk " < < paramData . pureType < < " >( " < < paramData . name < < " ) " ;
}
}
void writeFunction ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition , bool enhanced , bool singular , bool unique , bool isStructureChain )
{
if ( enhanced & & ( ! singular | | isStructureChain ) )
{
writeFunctionHeaderTemplate ( os , indentation , commandData , ! definition , isStructureChain ) ;
}
os < < indentation < < ( definition ? " VULKAN_HPP_INLINE " : " " ) ;
writeFunctionHeaderReturnType ( os , indentation , commandData , enhanced , singular , unique , isStructureChain ) ;
if ( definition & & ! commandData . className . empty ( ) )
{
os < < commandData . className < < " :: " ;
}
writeFunctionHeaderName ( os , commandData . reducedName , singular , unique ) ;
writeFunctionHeaderArguments ( os , vkData , commandData , enhanced , singular , ! definition ) ;
os < < ( definition ? " " : " ; " ) < < std : : endl ;
if ( definition )
{
// write the function body
os < < indentation < < " { " < < std : : endl ;
if ( enhanced )
{
if ( unique )
{
writeFunctionBodyUnique ( os , indentation , vkData , commandData , singular ) ;
}
else
{
writeFunctionBodyEnhanced ( os , indentation , vkData , commandData , singular , isStructureChain ) ;
}
}
else
{
writeFunctionBodyStandard ( os , indentation , vkData , commandData ) ;
}
os < < indentation < < " } " < < std : : endl ;
}
}
void writeFunctionBodyEnhanced ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular , bool isStructureChain )
{
if ( 1 < commandData . vectorParams . size ( ) )
{
writeFunctionBodyEnhancedMultiVectorSizeCheck ( os , indentation , commandData ) ;
}
std : : string returnName ;
if ( commandData . returnParam ! = ~ 0 )
{
returnName = writeFunctionBodyEnhancedLocalReturnVariable ( os , indentation , commandData , singular , isStructureChain ) ;
}
if ( commandData . twoStep )
{
assert ( ! singular ) ;
writeFunctionBodyEnhancedLocalCountVariable ( os , indentation , commandData ) ;
// we now might have to check the result, resize the returned vector accordingly, and call the function again
std : : map < size_t , size_t > : : const_iterator returnit = commandData . vectorParams . find ( commandData . returnParam ) ;
assert ( returnit ! = commandData . vectorParams . end ( ) & & ( returnit - > second ! = ~ 0 ) ) ;
std : : string sizeName = startLowerCase ( strip ( commandData . params [ returnit - > second ] . name , " p " ) ) ;
if ( commandData . returnType = = " Result " )
{
if ( 1 < commandData . successCodes . size ( ) )
{
writeFunctionBodyEnhancedCallTwoStepIterate ( os , indentation , vkData . vkTypes , returnName , sizeName , commandData ) ;
}
else
{
writeFunctionBodyEnhancedCallTwoStepChecked ( os , indentation , vkData . vkTypes , returnName , sizeName , commandData ) ;
}
}
else
{
writeFunctionBodyEnhancedCallTwoStep ( os , indentation , vkData . vkTypes , returnName , sizeName , commandData ) ;
}
}
else
{
if ( commandData . returnType = = " Result " )
{
writeFunctionBodyEnhancedCallResult ( os , indentation , vkData . vkTypes , commandData , singular ) ;
}
else
{
writeFunctionBodyEnhancedCall ( os , indentation , vkData . vkTypes , commandData , singular ) ;
}
}
if ( ( commandData . returnType = = " Result " ) | | ! commandData . successCodes . empty ( ) )
{
writeFunctionBodyEnhancedReturnResultValue ( os , indentation , returnName , commandData , singular ) ;
}
else if ( ( commandData . returnParam ! = ~ 0 ) & & ( commandData . returnType ! = commandData . enhancedReturnType ) )
{
// for the other returning cases, when the return type is somhow enhanced, just return the local returnVariable
os < < indentation < < " return " < < returnName < < " ; " < < std : : endl ;
}
}
void writeFunctionBodyEnhanced ( std : : ostream & os , std : : string const & templateString , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular )
{
os < < replaceWithMap ( templateString , {
{ " call " , generateCall ( commandData , vkTypes , true , singular ) } ,
{ " i " , indentation }
} ) ;
}
void writeFunctionBodyEnhancedCall ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular )
{
std : : string const templateString = " ${i} return ${call}; \n " ;
std : : string const templateStringVoid = " ${i} ${call}; \n " ;
writeFunctionBodyEnhanced ( os , commandData . returnType = = " void " ? templateStringVoid : templateString , indentation , vkTypes , commandData , singular ) ;
}
void writeFunctionBodyEnhancedCallResult ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular )
{
std : : string const templateString = " ${i} Result result = static_cast<Result>( ${call} ); \n " ;
writeFunctionBodyEnhanced ( os , templateString , indentation , vkTypes , commandData , singular ) ;
}
void writeFunctionBodyTwoStep ( std : : ostream & os , std : : string const & templateString , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData )
{
std : : map < std : : string , std : : string > replacements = {
{ " sizeName " , sizeName } ,
{ " returnName " , returnName } ,
{ " call1 " , generateCall ( commandData , vkTypes , true , false ) } ,
{ " call2 " , generateCall ( commandData , vkTypes , false , false ) } ,
{ " i " , indentation }
} ;
os < < replaceWithMap ( templateString , replacements ) ;
}
void writeFunctionBodyEnhancedCallTwoStep ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData )
{
std : : string const templateString =
R " (${i} ${call1};
$ { i } $ { returnName } . resize ( $ { sizeName } ) ;
$ { i } $ { call2 } ;
) " ;
writeFunctionBodyTwoStep ( os , templateString , indentation , vkTypes , returnName , sizeName , commandData ) ;
}
void writeFunctionBodyEnhancedCallTwoStepChecked ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData )
{
std : : string const templateString =
R " (${i} Result result = static_cast<Result>( ${call1} );
$ { i } if ( ( result = = Result : : eSuccess ) & & $ { sizeName } )
$ { i } {
$ { i } $ { returnName } . resize ( $ { sizeName } ) ;
$ { i } result = static_cast < Result > ( $ { call2 } ) ;
$ { i } }
) " ;
writeFunctionBodyTwoStep ( os , templateString , indentation , vkTypes , returnName , sizeName , commandData ) ;
}
void writeFunctionBodyEnhancedCallTwoStepIterate ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , std : : string const & returnName , std : : string const & sizeName , CommandData const & commandData )
{
std : : string const templateString =
R " (${i} Result result;
$ { i } do
$ { i } {
$ { i } result = static_cast < Result > ( $ { call1 } ) ;
$ { i } if ( ( result = = Result : : eSuccess ) & & $ { sizeName } )
$ { i } {
$ { i } $ { returnName } . resize ( $ { sizeName } ) ;
$ { i } result = static_cast < Result > ( $ { call2 } ) ;
$ { i } }
$ { i } } while ( result = = Result : : eIncomplete ) ;
$ { i } assert ( $ { sizeName } < = $ { returnName } . size ( ) ) ;
$ { i } $ { returnName } . resize ( $ { sizeName } ) ;
) " ;
writeFunctionBodyTwoStep ( os , templateString , indentation , vkTypes , returnName , sizeName , commandData ) ;
}
void writeFunctionBodyEnhancedLocalCountVariable ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData )
{
// local count variable to hold the size of the vector to fill
assert ( commandData . returnParam ! = ~ 0 ) ;
std : : map < size_t , size_t > : : const_iterator returnit = commandData . vectorParams . find ( commandData . returnParam ) ;
assert ( returnit ! = commandData . vectorParams . end ( ) & & ( returnit - > second ! = ~ 0 ) ) ;
assert ( ( commandData . returnType = = " Result " ) | | ( commandData . returnType = = " void " ) ) ;
// take the pure type of the size parameter; strip the leading 'p' from its name for its local name
os < < indentation < < " " < < commandData . params [ returnit - > second ] . pureType < < " " < < startLowerCase ( strip ( commandData . params [ returnit - > second ] . name , " p " ) ) < < " ; " < < std : : endl ;
}
std : : string writeFunctionBodyEnhancedLocalReturnVariable ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool singular , bool isStructureChain )
{
std : : string returnName = startLowerCase ( strip ( commandData . params [ commandData . returnParam ] . name , " p " ) ) ;
// there is a returned parameter -> we need a local variable to hold that value
if ( commandData . returnType ! = commandData . enhancedReturnType )
{
// the returned parameter is somehow enhanced by us
os < < indentation < < " " ;
if ( singular )
{
if ( isStructureChain )
{
std : : string const & pureType = commandData . params [ commandData . returnParam ] . pureType ;
// For StructureChains use the template parameters
os < < " StructureChain<T...> structureChain; " < < std : : endl ;
returnName = stripPluralS ( returnName ) ;
os < < indentation < < " " < < pureType < < " & " < < returnName < < " = structureChain.template get< " < < pureType < < " >() " ;
returnName = " structureChain " ;
}
else
{
// in singular case, just use the return parameters pure type for the return variable
returnName = stripPluralS ( returnName ) ;
os < < commandData . params [ commandData . returnParam ] . pureType < < " " < < returnName ;
}
}
else
{
// in non-singular case, use the enhanced type for the return variable (like vector<...>)
if ( isStructureChain )
{
std : : string const & returnType = commandData . enhancedReturnType ;
// For StructureChains use the template parameters
os < < " StructureChain<T...> structureChain; " < < std : : endl ;
os < < indentation < < " " < < returnType < < " & " < < returnName < < " = structureChain.template get< " < < returnType < < " >() " ;
returnName = " structureChain " ;
}
else
{
os < < commandData . enhancedReturnType < < " " < < returnName ;
}
std : : map < size_t , size_t > : : const_iterator it = commandData . vectorParams . find ( commandData . returnParam ) ;
if ( it ! = commandData . vectorParams . end ( ) & & ! commandData . twoStep )
{
// if the return parameter is a vector parameter, and not part of a two-step algorithm, initialize its size
std : : string size ;
if ( it - > second = = ~ 0 )
{
assert ( ! commandData . params [ commandData . returnParam ] . len . empty ( ) ) ;
// the size of the vector is not given by an other parameter, but by some member of a parameter, described as 'parameter::member'
// -> replace the '::' by '.' and filter out the leading 'p' to access that value
size = startLowerCase ( strip ( commandData . params [ commandData . returnParam ] . len , " p " ) ) ;
size_t pos = size . find ( " :: " ) ;
assert ( pos ! = std : : string : : npos ) ;
size . replace ( pos , 2 , " . " ) ;
}
else
{
// the size of the vector is given by an other parameter
// that means (as this is not a two-step algorithm) it's size is determined by some other vector parameter!
// -> look for it and get it's actual size
for ( auto const & vectorParam : commandData . vectorParams )
{
if ( ( vectorParam . first ! = commandData . returnParam ) & & ( vectorParam . second = = it - > second ) )
{
size = startLowerCase ( strip ( commandData . params [ vectorParam . first ] . name , " p " ) ) + " .size() " ;
break ;
}
}
}
assert ( ! size . empty ( ) ) ;
os < < " ( " < < size < < " ) " ;
}
}
os < < " ; " < < std : : endl ;
}
else
{
// the return parameter is not enhanced -> the type is supposed to be a Result and there are more than one success codes!
assert ( ( commandData . returnType = = " Result " ) & & ( 1 < commandData . successCodes . size ( ) ) ) ;
os < < indentation < < " " < < commandData . params [ commandData . returnParam ] . pureType < < " " < < returnName < < " ; " < < std : : endl ;
}
return returnName ;
}
void writeFunctionBodyEnhancedMultiVectorSizeCheck ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData )
{
std : : string const templateString =
R " #(#ifdef VULKAN_HPP_NO_EXCEPTIONS
$ { i } assert ( $ { firstVectorName } . size ( ) = = $ { secondVectorName } . size ( ) ) ;
# else
$ { i } if ( $ { firstVectorName } . size ( ) ! = $ { secondVectorName } . size ( ) )
$ { i } {
$ { i } throw LogicError ( " VULKAN_HPP_NAMESPACE::${className}::${reducedName}: ${firstVectorName}.size() ! = $ { secondVectorName } . size ( ) " );
$ { i } }
# endif // VULKAN_HPP_NO_EXCEPTIONS
) # " ;
// add some error checks if multiple vectors need to have the same size
for ( std : : map < size_t , size_t > : : const_iterator it0 = commandData . vectorParams . begin ( ) ; it0 ! = commandData . vectorParams . end ( ) ; + + it0 )
{
if ( it0 - > first ! = commandData . returnParam )
{
for ( std : : map < size_t , size_t > : : const_iterator it1 = std : : next ( it0 ) ; it1 ! = commandData . vectorParams . end ( ) ; + + it1 )
{
if ( ( it1 - > first ! = commandData . returnParam ) & & ( it0 - > second = = it1 - > second ) )
{
os < < replaceWithMap ( templateString , std : : map < std : : string , std : : string > ( {
{ " firstVectorName " , startLowerCase ( strip ( commandData . params [ it0 - > first ] . name , " p " ) ) } ,
{ " secondVectorName " , startLowerCase ( strip ( commandData . params [ it1 - > first ] . name , " p " ) ) } ,
{ " className " , commandData . className } ,
{ " reducedName " , commandData . reducedName } ,
{ " i " , indentation }
} ) ) ;
}
}
}
}
}
void writeFunctionBodyEnhancedReturnResultValue ( std : : ostream & os , std : : string const & indentation , std : : string const & returnName , CommandData const & commandData , bool singular )
{
// if the return type is "Result" or there is at least one success code, create the Result/Value construct to return
os < < indentation < < " return createResultValue( result, " ;
if ( commandData . returnParam ! = ~ 0 )
{
// if there's a return parameter, list it in the Result/Value constructor
os < < returnName < < " , " ;
}
// now the function name (with full namespace) as a string
os < < " \" VULKAN_HPP_NAMESPACE:: " < < ( commandData . className . empty ( ) ? " " : commandData . className + " :: " ) < < ( singular ? stripPluralS ( commandData . reducedName ) : commandData . reducedName ) < < " \" " ;
if ( ! commandData . twoStep & & ( 1 < commandData . successCodes . size ( ) ) )
{
// and for the single-step algorithms with more than one success code list them all
os < < " , { Result:: " < < commandData . successCodes [ 0 ] ;
for ( size_t i = 1 ; i < commandData . successCodes . size ( ) ; i + + )
{
os < < " , Result:: " < < commandData . successCodes [ i ] ;
}
os < < " } " ;
}
os < < " ); " < < std : : endl ;
}
void writeFunctionBodyStandard ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData )
{
os < < indentation < < " " ;
bool castReturn = false ;
if ( commandData . returnType ! = " void " )
{
// there's something to return...
os < < " return " ;
castReturn = ( vkData . vkTypes . find ( commandData . returnType ) ! = vkData . vkTypes . end ( ) ) ;
if ( castReturn )
{
// the return-type is a vulkan type -> need to cast to vk::-type
os < < " static_cast< " < < commandData . returnType < < " >( " ;
}
}
// call the original function
os < < " vk " < < startUpperCase ( commandData . fullName ) < < " ( " ;
if ( ! commandData . className . empty ( ) )
{
// the command is part of a class -> the first argument is the member variable, starting with "m_"
os < < " m_ " < < commandData . params [ 0 ] . name ;
}
// list all the arguments
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
{
if ( 0 < i )
{
os < < " , " ;
}
if ( vkData . vkTypes . find ( commandData . params [ i ] . pureType ) ! = vkData . vkTypes . end ( ) )
{
// the parameter is a vulkan type
if ( commandData . params [ i ] . type . back ( ) = = ' * ' )
{
// it's a pointer -> need to reinterpret_cast it
writeReinterpretCast ( os , commandData . params [ i ] . type . find ( " const " ) = = 0 , true , commandData . params [ i ] . pureType , commandData . params [ i ] . type . find ( " * const " ) ! = std : : string : : npos ) ;
}
else
{
// it's a value -> need to static_cast ist
os < < " static_cast<Vk " < < commandData . params [ i ] . pureType < < " > " ;
}
os < < " ( " < < commandData . params [ i ] . name < < " ) " ;
}
else
{
// it's a non-vulkan type -> just use it
os < < commandData . params [ i ] . name ;
}
}
os < < " ) " ;
if ( castReturn )
{
// if we cast the return -> close the static_cast
os < < " ) " ;
}
os < < " ; " < < std : : endl ;
}
void writeFunctionBodyUnique ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular )
{
// the unique version needs a Deleter object for destruction of the newly created stuff
std : : string type = commandData . params [ commandData . returnParam ] . pureType ;
std : : string typeValue = startLowerCase ( type ) ;
os < < indentation < < " " < < type < < " Deleter deleter( " ;
if ( vkData . deleters . find ( commandData . className ) ! = vkData . deleters . end ( ) )
{
// if the Deleter is specific to the command's class, add '*this' to the deleter
os < < " *this, " ;
}
// get the DeleterData corresponding to the returned type
std : : map < std : : string , DeleterData > : : const_iterator ddit = vkData . deleters . find ( type ) ;
assert ( ddit ! = vkData . deleters . end ( ) ) ;
if ( ddit - > second . pool . empty ( ) )
{
// if this type isn't pooled, use the allocator (provided as a function argument)
os < < " allocator " ;
}
else
{
// otherwise use the pool, which always is a member of the second argument
os < < startLowerCase ( strip ( commandData . params [ 1 ] . name , " p " ) ) < < " . " < < startLowerCase ( ddit - > second . pool ) ;
}
os < < " ); " < < std : : endl ;
bool returnsVector = ! singular & & ( commandData . vectorParams . find ( commandData . returnParam ) ! = commandData . vectorParams . end ( ) ) ;
if ( returnsVector )
{
// if a vector of data is returned, use a local variable to hold the returned data from the non-unique function call
os < < indentation < < " std::vector< " < < type < < " ,Allocator> " < < typeValue < < " s = " ;
}
else
{
// otherwise create a Unique stuff out of the returned data from the non-unique function call
os < < indentation < < " return Unique " < < type < < " ( " ;
}
// the call to the non-unique function
os < < ( singular ? stripPluralS ( commandData . fullName ) : commandData . fullName ) < < " ( " ;
bool argEncountered = false ;
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
{
if ( commandData . skippedParams . find ( i ) = = commandData . skippedParams . end ( ) )
{
if ( argEncountered )
{
os < < " , " ;
}
argEncountered = true ;
// strip off the leading 'p' for pointer arguments
std : : string argumentName = ( commandData . params [ i ] . type . back ( ) = = ' * ' ) ? startLowerCase ( strip ( commandData . params [ i ] . name , " p " ) ) : commandData . params [ i ] . name ;
if ( singular & & ( commandData . vectorParams . find ( i ) ! = commandData . vectorParams . end ( ) ) )
{
// and strip off the plural 's' if appropriate
argumentName = stripPluralS ( argumentName ) ;
}
os < < argumentName ;
}
}
os < < " ) " ;
if ( returnsVector )
{
std : : string const stringTemplate = R " (;
$ { i } std : : vector < Unique $ { type } > unique $ { type } s ;
$ { i } unique $ { type } s . reserve ( $ { typeValue } s . size ( ) ) ;
$ { i } for ( auto $ { typeValue } : $ { typeValue } s )
$ { i } {
$ { i } unique $ { type } s . push_back ( Unique $ { type } ( $ { typeValue } , deleter ) ) ;
$ { i } }
$ { i } return unique $ { type } s ;
) " ;
os < < replaceWithMap ( stringTemplate , std : : map < std : : string , std : : string > {
{ " i " , indentation } ,
{ " type " , type } ,
{ " typeValue " , typeValue }
} ) ;
}
else
{
// for non-vector returns, just add the deleter (local variable) to the Unique-stuff constructor
os < < " , deleter ); " < < std : : endl ;
}
}
void writeFunctionHeaderArguments ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool enhanced , bool singular , bool withDefaults )
{
os < < " ( " ;
if ( enhanced )
{
writeFunctionHeaderArgumentsEnhanced ( os , vkData , commandData , singular , withDefaults ) ;
}
else
{
writeFunctionHeaderArgumentsStandard ( os , commandData ) ;
}
os < < " ) " ;
if ( ! commandData . className . empty ( ) )
{
os < < " const " ;
}
}
void writeFunctionHeaderArgumentsEnhanced ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool singular , bool withDefaults )
{
// check if there's at least one argument left to put in here
if ( commandData . skippedParams . size ( ) + ( commandData . className . empty ( ) ? 0 : 1 ) < commandData . params . size ( ) )
{
// determine the last argument, where we might provide some default for
size_t lastArgument = ~ 0 ;
for ( size_t i = commandData . params . size ( ) - 1 ; i < commandData . params . size ( ) ; i - - )
{
if ( commandData . skippedParams . find ( i ) = = commandData . skippedParams . end ( ) )
{
lastArgument = i ;
break ;
}
}
os < < " " ;
bool argEncountered = false ;
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
{
if ( commandData . skippedParams . find ( i ) = = commandData . skippedParams . end ( ) )
{
if ( argEncountered )
{
os < < " , " ;
}
std : : string strippedParameterName = startLowerCase ( strip ( commandData . params [ i ] . name , " p " ) ) ;
std : : map < size_t , size_t > : : const_iterator it = commandData . vectorParams . find ( i ) ;
size_t rightStarPos = commandData . params [ i ] . type . rfind ( ' * ' ) ;
if ( it = = commandData . vectorParams . end ( ) )
{
// the argument ist not a vector
if ( rightStarPos = = std : : string : : npos )
{
// and its not a pointer -> just use its type and name here
os < < commandData . params [ i ] . type < < " " < < commandData . params [ i ] . name ;
if ( ! commandData . params [ i ] . arraySize . empty ( ) )
{
os < < " [ " < < commandData . params [ i ] . arraySize < < " ] " ;
}
if ( withDefaults & & ( lastArgument = = i ) )
{
// check if the very last argument is a flag without any bits -> provide some empty default for it
std : : map < std : : string , FlagData > : : const_iterator flagIt = vkData . flags . find ( commandData . params [ i ] . pureType ) ;
if ( flagIt ! = vkData . flags . end ( ) )
{
// get the enum corresponding to this flag, to check if it's empty
std : : list < DependencyData > : : const_iterator depIt = std : : find_if ( vkData . dependencies . begin ( ) , vkData . dependencies . end ( ) , [ & flagIt ] ( DependencyData const & dd ) { return ( dd . name = = flagIt - > first ) ; } ) ;
assert ( ( depIt ! = vkData . dependencies . end ( ) ) & & ( depIt - > dependencies . size ( ) = = 1 ) ) ;
std : : map < std : : string , EnumData > : : const_iterator enumIt = vkData . enums . find ( * depIt - > dependencies . begin ( ) ) ;
assert ( enumIt ! = vkData . enums . end ( ) ) ;
if ( enumIt - > second . values . empty ( ) )
{
// there are no bits in this flag -> provide the default
os < < " = " < < commandData . params [ i ] . pureType < < " () " ;
}
}
}
}
else
{
// the argument is not a vector, but a pointer
assert ( commandData . params [ i ] . type [ rightStarPos ] = = ' * ' ) ;
if ( commandData . params [ i ] . optional )
{
// for an optional argument, trim the trailing '*' from the type, and the leading 'p' from the name
os < < " Optional< " < < trimEnd ( commandData . params [ i ] . type . substr ( 0 , rightStarPos ) ) < < " > " < < strippedParameterName ;
if ( withDefaults )
{
os < < " = nullptr " ;
}
}
else if ( commandData . params [ i ] . pureType = = " void " )
{
// for void-pointer, just use type and name
os < < commandData . params [ i ] . type < < " " < < commandData . params [ i ] . name ;
}
else if ( commandData . params [ i ] . pureType ! = " char " )
{
// for non-char-pointer, change to reference
os < < trimEnd ( commandData . params [ i ] . type . substr ( 0 , rightStarPos ) ) < < " & " < < strippedParameterName ;
}
else
{
// for char-pointer, change to const reference to std::string
os < < " const std::string & " < < strippedParameterName ;
}
}
}
else
{
// the argument is a vector
// it's optional, if it's marked as optional and there's no size specified
bool optional = commandData . params [ i ] . optional & & ( it - > second = = ~ 0 ) ;
assert ( ( rightStarPos ! = std : : string : : npos ) & & ( commandData . params [ i ] . type [ rightStarPos ] = = ' * ' ) ) ;
if ( commandData . params [ i ] . type . find ( " char " ) ! = std : : string : : npos )
{
// it's a char-vector -> use a std::string (either optional or a const-reference
if ( optional )
{
os < < " Optional<const std::string> " < < strippedParameterName ;
if ( withDefaults )
{
os < < " = nullptr " ;
}
}
else
{
os < < " const std::string & " < < strippedParameterName ;
}
}
else
{
// it's a non-char vector (they are never optional)
assert ( ! optional ) ;
if ( singular )
{
// in singular case, change from pointer to reference
os < < trimEnd ( commandData . params [ i ] . type . substr ( 0 , rightStarPos ) ) < < " & " < < stripPluralS ( strippedParameterName ) ;
}
else
{
// otherwise, use our ArrayProxy
bool isConst = ( commandData . params [ i ] . type . find ( " const " ) ! = std : : string : : npos ) ;
os < < " ArrayProxy< " < < ( ( commandData . templateParam = = i ) ? ( isConst ? " const T " : " T " ) : trimEnd ( commandData . params [ i ] . type . substr ( 0 , rightStarPos ) ) ) < < " > " < < strippedParameterName ;
}
}
}
argEncountered = true ;
}
}
os < < " " ;
}
}
void writeFunctionHeaderArgumentsStandard ( std : : ostream & os , CommandData const & commandData )
{
// for the standard case, just list all the arguments as we've got them
bool argEncountered = false ;
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
{
if ( argEncountered )
{
os < < " , " ;
}
os < < " " < < commandData . params [ i ] . type < < " " < < commandData . params [ i ] . name ;
if ( ! commandData . params [ i ] . arraySize . empty ( ) )
{
os < < " [ " < < commandData . params [ i ] . arraySize < < " ] " ;
}
argEncountered = true ;
}
if ( argEncountered )
{
os < < " " ;
}
}
void writeFunctionHeaderName ( std : : ostream & os , std : : string const & name , bool singular , bool unique )
{
os < < ( singular ? stripPluralS ( name ) : name ) ;
if ( unique )
{
os < < " Unique " ;
}
}
void writeFunctionHeaderReturnType ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool enhanced , bool singular , bool unique , bool isStructureChain )
{
std : : string templateString ;
std : : string returnType ;
if ( enhanced )
{
// the enhanced function might return some pretty complex return stuff
if ( unique )
{
// the unique version returns something prefixed with 'Unique'; potentially a vector of that stuff
// it's a vector, if it's not the singular version and the return parameter is a vector parameter
bool returnsVector = ! singular & & ( commandData . vectorParams . find ( commandData . returnParam ) ! = commandData . vectorParams . end ( ) ) ;
templateString = returnsVector ? " std::vector<Unique${returnType}> " : " Unique${returnType} " ;
returnType = isStructureChain ? " StructureChain<T...> " : commandData . params [ commandData . returnParam ] . pureType ;
}
else if ( ( commandData . enhancedReturnType ! = commandData . returnType ) & & ( commandData . returnType ! = " void " ) )
{
// if the enhanced return type differs from the original return type, and it's not void, we return a ResultValueType<...>::type
if ( isStructureChain | | ( ! singular & & ( commandData . enhancedReturnType . find ( " Allocator " ) ! = std : : string : : npos ) ) )
{
// for the non-singular case with allocation, we need to prepend with 'typename' to keep compilers happy
templateString = " typename " ;
}
templateString + = " ResultValueType<${returnType}>::type " ;
assert ( commandData . returnType = = " Result " ) ;
// in singular case, we create the ResultValueType from the pure return type, otherwise from the enhanced return type
if ( isStructureChain )
{
returnType = " StructureChain<T...> " ;
}
else
{
returnType = singular ? commandData . params [ commandData . returnParam ] . pureType : commandData . enhancedReturnType ;
}
}
else if ( ( commandData . returnParam ! = ~ 0 ) & & ( 1 < commandData . successCodes . size ( ) ) )
{
// if there is a return parameter at all, and there are multiple success codes, we return a ResultValue<...> with the pure return type
assert ( commandData . returnType = = " Result " ) ;
templateString = " ResultValue<${returnType}> " ;
returnType = isStructureChain ? " StructureChain<T...> " : commandData . params [ commandData . returnParam ] . pureType ;
}
else
{
// and in every other case, we just return the enhanced return type.
templateString = " ${returnType} " ;
returnType = isStructureChain ? " StructureChain<T...> " : commandData . enhancedReturnType ;
}
}
else
{
// the non-enhanced function just uses the return type
templateString = " ${returnType} " ;
returnType = commandData . returnType ;
}
os < < replaceWithMap ( templateString , { { " returnType " , returnType } } ) ;
}
void writeFunctionHeaderTemplate ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool withDefault , bool isStructureChain )
{
if ( isStructureChain )
{
os < < indentation < < " template <typename ...T> " < < std : : endl ;
}
else if ( ( commandData . templateParam ! = ~ 0 ) & & ( ( commandData . templateParam ! = commandData . returnParam ) | | ( commandData . enhancedReturnType = = " Result " ) ) )
{
// if there's a template parameter, not being the return parameter or where the enhanced return type is 'Result' -> templatize on type 'T'
assert ( commandData . enhancedReturnType . find ( " Allocator " ) = = std : : string : : npos ) ;
os < < indentation < < " template <typename T> " < < std : : endl ;
}
else if ( ( commandData . enhancedReturnType . find ( " Allocator " ) ! = std : : string : : npos ) )
{
// otherwise, if there's an Allocator used in the enhanced return type, we templatize on that Allocator
assert ( ( commandData . enhancedReturnType . substr ( 0 , 12 ) = = " std::vector< " ) & & ( commandData . enhancedReturnType . find ( ' , ' ) ! = std : : string : : npos ) & & ( 12 < commandData . enhancedReturnType . find ( ' , ' ) ) ) ;
os < < indentation < < " template <typename Allocator " ;
if ( withDefault )
{
// for the default type get the type from the enhancedReturnType, which is of the form 'std::vector<Type,Allocator>'
os < < " = std::allocator< " < < commandData . enhancedReturnType . substr ( 12 , commandData . enhancedReturnType . find ( ' , ' ) - 12 ) < < " > " ;
}
os < < " > " < < std : : endl ;
}
}
void writeReinterpretCast ( std : : ostream & os , bool leadingConst , bool vulkanType , std : : string const & type , bool trailingPointerToConst )
{
os < < " reinterpret_cast< " ;
if ( leadingConst )
{
os < < " const " ;
}
if ( vulkanType )
{
os < < " Vk " ;
}
os < < type ;
if ( trailingPointerToConst )
{
os < < " * const " ;
}
os < < " *> " ;
}
void writeStandardOrEnhanced ( std : : ostream & os , std : : string const & standard , std : : string const & enhanced )
{
if ( standard = = enhanced )
{
// standard and enhanced string are equal -> just use one of them and we're done
os < < standard ;
}
else
{
// standard and enhanced string differ -> use both, wrapping the enhanced by !VULKAN_HPP_DISABLE_ENHANCED_MODE
// determine the argument list of that standard, and compare it with that of the enhanced
// if they are equal -> need to have just one; if they differ -> need to have both
size_t standardStart = standard . find ( ' ( ' ) ;
size_t standardCount = standard . find ( ' ) ' , standardStart ) - standardStart ;
size_t enhancedStart = enhanced . find ( ' ( ' ) ;
bool unchangedInterface = ( standard . substr ( standardStart , standardCount ) = = enhanced . substr ( enhancedStart , standardCount ) ) ;
if ( unchangedInterface )
{
os < < " #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE " < < std : : endl ;
}
os < < standard
< < ( unchangedInterface ? " #else " : " #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE " ) < < std : : endl
< < enhanced
< < " #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ " < < std : : endl ;
}
}
void writeStructConstructor ( std : : ostream & os , std : : string const & name , StructData const & structData , std : : set < std : : string > const & vkTypes ,
std : : map < std : : string , std : : string > const & nameMap , std : : map < std : : string , std : : string > const & defaultValues )
{
// the constructor with all the elements as arguments, with defaults
os < < " " < < name < < " ( " ;
bool listedArgument = false ;
if ( ! structData . returnedOnly )
{
for ( size_t i = 0 ; i < structData . members . size ( ) ; i + + )
{
if ( listedArgument )
{
os < < " , " ;
}
// skip members 'pNext' and 'sType', as they are never explicitly set
if ( ( structData . members [ i ] . name ! = " pNext " ) & & ( structData . members [ i ] . name ! = " sType " ) )
{
// find a default value for the given pure type
std : : map < std : : string , std : : string > : : const_iterator defaultIt = defaultValues . find ( structData . members [ i ] . pureType ) ;
assert ( defaultIt ! = defaultValues . end ( ) ) ;
if ( structData . members [ i ] . arraySize . empty ( ) )
{
// the arguments name get a trailing '_', to distinguish them from the actual struct members
// pointer arguments get a nullptr as default
os < < structData . members [ i ] . type < < " " < < structData . members [ i ] . name < < " _ = " < < ( structData . members [ i ] . type . back ( ) = = ' * ' ? " nullptr " : defaultIt - > second ) ;
}
else
{
// array members are provided as const reference to a std::array
// the arguments name get a trailing '_', to distinguish them from the actual struct members
// list as many default values as there are elements in the array
os < < " std::array< " < < structData . members [ i ] . type < < " , " < < structData . members [ i ] . arraySize < < " > const& " < < structData . members [ i ] . name < < " _ = { { " < < defaultIt - > second ;
size_t n = atoi ( structData . members [ i ] . arraySize . c_str ( ) ) ;
assert ( 0 < n ) ;
for ( size_t j = 1 ; j < n ; j + + )
{
os < < " , " < < defaultIt - > second ;
}
os < < " } } " ;
}
listedArgument = true ;
}
}
}
os < < " ) " < < std : : endl ;
// copy over the simple arguments
bool firstArgument = true ;
for ( size_t i = 0 ; i < structData . members . size ( ) ; i + + )
{
if ( structData . members [ i ] . arraySize . empty ( ) )
{
// here, we can only handle non-array arguments
std : : string templateString = " ${sep} ${member}( ${value} ) \n " ;
std : : string sep = firstArgument ? " : " : " , " ;
std : : string member = structData . members [ i ] . name ;
std : : string value ;
// 'pNext' and 'sType' don't get an argument, use nullptr and the correct StructureType enum value to initialize them
if ( structData . members [ i ] . name = = " pNext " )
{
value = " nullptr " ;
}
else if ( structData . members [ i ] . name = = " sType " )
{
assert ( ! structData . members [ i ] . values . empty ( ) ) ;
auto nameIt = nameMap . find ( structData . members [ i ] . values ) ;
assert ( nameIt ! = nameMap . end ( ) ) ;
value = nameIt - > second ;
}
else
{
if ( ! structData . returnedOnly )
{
// the other elements are initialized by the corresponding argument (with trailing '_', as mentioned above)
value = structData . members [ i ] . name + " _ " ;
}
else
{
templateString = " " ;
}
}
os < < replaceWithMap ( templateString , { { " sep " , sep } , { " member " , member } , { " value " , value } } ) ;
firstArgument = false ;
}
}
// the body of the constructor, copying over data from argument list into wrapped struct
os < < " { " < < std : : endl ;
if ( ! structData . returnedOnly )
{
for ( size_t i = 0 ; i < structData . members . size ( ) ; i + + )
{
if ( ! structData . members [ i ] . arraySize . empty ( ) )
{
// here we can handle the arrays, copying over from argument (with trailing '_') to member
// size is arraySize times sizeof type
std : : string member = structData . members [ i ] . name ;
std : : string arraySize = structData . members [ i ] . arraySize ;
std : : string type = structData . members [ i ] . type ;
os < < replaceWithMap ( " memcpy( &${member}, ${member}_.data(), ${arraySize} * sizeof( ${type} ) ); \n " ,
{ { " member " , member } , { " arraySize " , arraySize } , { " type " , type } } ) ;
}
}
}
os < < " } \n \n " ;
std : : string templateString =
R " ( ${name}( Vk${name} const & rhs )
{
memcpy ( this , & rhs , sizeof ( $ { name } ) ) ;
}
$ { name } & operator = ( Vk $ { name } const & rhs )
{
memcpy ( this , & rhs , sizeof ( $ { name } ) ) ;
return * this ;
}
) " ;
os < < replaceWithMap ( templateString , { { " name " , name } } ) ;
}
void writeStructSetter ( std : : ostream & os , std : : string const & structureName , MemberData const & memberData , std : : set < std : : string > const & vkTypes )
{
if ( memberData . type ! = " StructureType " ) // filter out StructureType, which is supposed to be immutable !
{
// the setters return a reference to the structure
os < < " " < < structureName < < " & set " < < startUpperCase ( memberData . name ) < < " ( " ;
if ( memberData . arraySize . empty ( ) )
{
os < < memberData . type < < " " ;
}
else
{
os < < " std::array< " < < memberData . type < < " , " < < memberData . arraySize < < " > " ;
}
// add a trailing '_' to the argument to distinguish it from the structure member
os < < memberData . name < < " _ ) " < < std : : endl
< < " { " < < std : : endl ;
// copy over the argument, either by assigning simple data, or by memcpy array data
if ( memberData . arraySize . empty ( ) )
{
os < < " " < < memberData . name < < " = " < < memberData . name < < " _ " ;
}
else
{
os < < " memcpy( & " < < memberData . name < < " , " < < memberData . name < < " _.data(), " < < memberData . arraySize < < " * sizeof( " < < memberData . type < < " ) ) " ;
}
os < < " ; " < < std : : endl
< < " return *this; " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
}
}
void writeTypeAlias ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData )
{
auto aliasIt = vkData . aliases . find ( dependencyData . name ) ;
assert ( aliasIt ! = vkData . aliases . end ( ) ) ;
assert ( ( ( aliasIt - > second . category = = DependencyData : : Category : : ENUM ) & & ( vkData . enums . find ( aliasIt - > second . value ) ! = vkData . enums . end ( ) ) )
| | ( ( aliasIt - > second . category = = DependencyData : : Category : : STRUCT ) & & ( vkData . structs . find ( aliasIt - > second . value ) ! = vkData . structs . end ( ) ) ) ) ;
enterProtect ( os , aliasIt - > second . protect ) ;
os < < " using " < < aliasIt - > first < < " = " < < aliasIt - > second . value < < " ; " < < std : : endl ;
leaveProtect ( os , aliasIt - > second . protect ) ;
os < < std : : endl ;
}
void writeTypeCommand ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData )
{
assert ( vkData . commands . find ( dependencyData . name ) ! = vkData . commands . end ( ) ) ;
CommandData const & commandData = vkData . commands . find ( dependencyData . name ) - > second ;
if ( commandData . className . empty ( ) )
{
if ( commandData . fullName = = " createInstance " )
{
// special handling for createInstance, as we need to explicitly place the forward declarations and the deleter classes here
auto deleterTypesIt = vkData . deleterTypes . find ( " " ) ;
assert ( ( deleterTypesIt ! = vkData . deleterTypes . end ( ) ) & & ( deleterTypesIt - > second . size ( ) = = 1 ) ) ;
writeDeleterForwardDeclarations ( os , * deleterTypesIt , vkData . deleters ) ;
writeTypeCommand ( os , " " , vkData , commandData , false ) ;
writeDeleterClasses ( os , * deleterTypesIt , vkData . deleters ) ;
}
else
{
writeTypeCommand ( os , " " , vkData , commandData , false ) ;
}
writeTypeCommand ( os , " " , vkData , commandData , true ) ;
os < < std : : endl ;
}
}
void writeTypeCommand ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition )
{
enterProtect ( os , commandData . protect ) ;
bool isStructureChain = vkData . extendedStructs . find ( commandData . enhancedReturnType ) ! = vkData . extendedStructs . end ( ) ;
// first create the standard version of the function
std : : ostringstream standard ;
writeFunction ( standard , indentation , vkData , commandData , definition , false , false , false , false ) ;
// then the enhanced version, composed by up to five parts
std : : ostringstream enhanced ;
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , false , false , false ) ;
if ( isStructureChain )
{
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , false , false , true ) ;
}
// then a singular version, if a sized vector would be returned
std : : map < size_t , size_t > : : const_iterator returnVector = commandData . vectorParams . find ( commandData . returnParam ) ;
bool singular = ( returnVector ! = commandData . vectorParams . end ( ) ) & & ( returnVector - > second ! = ~ 0 ) & & ( commandData . params [ returnVector - > second ] . type . back ( ) ! = ' * ' ) ;
if ( singular )
{
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , true , false , false ) ;
}
// special handling for createDevice and createInstance !
bool specialWriteUnique = ( commandData . reducedName = = " createDevice " ) | | ( commandData . reducedName = = " createInstance " ) ;
// and then the same for the Unique* versions (a Deleter is available for the commandData's class, and the function starts with 'allocate' or 'create')
if ( ( ( vkData . deleters . find ( commandData . className ) ! = vkData . deleters . end ( ) ) | | specialWriteUnique ) & & ( ( commandData . reducedName . substr ( 0 , 8 ) = = " allocate " ) | | ( commandData . reducedName . substr ( 0 , 6 ) = = " create " ) ) )
{
enhanced < < " #ifndef VULKAN_HPP_NO_SMART_HANDLE " < < std : : endl ;
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , false , true , false ) ;
if ( singular )
{
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , true , true , false ) ;
}
enhanced < < " #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ " < < std : : endl ;
}
// and write one or both of them
writeStandardOrEnhanced ( os , standard . str ( ) , enhanced . str ( ) ) ;
leaveProtect ( os , commandData . protect ) ;
os < < std : : endl ;
}
void writeTypeEnum ( std : : ostream & os , EnumData const & enumData )
{
// a named enum per enum, listing all its values by setting them to the original Vulkan names
enterProtect ( os , enumData . protect ) ;
os < < " enum class " < < enumData . name < < std : : endl
< < " { " < < std : : endl ;
for ( size_t i = 0 ; i < enumData . values . size ( ) ; i + + )
{
os < < " " < < enumData . values [ i ] . name < < " = " < < enumData . values [ i ] . value ;
if ( ! enumData . values [ i ] . alias . empty ( ) )
{
os < < " , " < < std : : endl
< < " " < < enumData . values [ i ] . alias < < " = " < < enumData . values [ i ] . value ;
}
if ( i < enumData . values . size ( ) - 1 )
{
os < < " , " ;
}
os < < std : : endl ;
}
os < < " }; " < < std : : endl ;
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
}
bool isErrorEnum ( std : : string const & enumName )
{
return ( enumName . substr ( 0 , 6 ) = = " eError " ) ;
}
std : : string stripErrorEnumPrefix ( std : : string const & enumName )
{
assert ( isErrorEnum ( enumName ) ) ;
return strip ( enumName , " eError " ) ;
}
// Intended only for `enum class Result`!
void writeExceptionsForEnum ( std : : ostream & os , EnumData const & enumData )
{
std : : string templateString =
R " ( class ${className} : public SystemError
{
public :
$ { className } ( std : : string const & message )
: SystemError ( make_error_code ( $ { enumName } : : $ { enumMemberName } ) , message ) { }
$ { className } ( char const * message )
: SystemError ( make_error_code ( $ { enumName } : : $ { enumMemberName } ) , message ) { }
} ;
) " ;
enterProtect ( os , enumData . protect ) ;
for ( size_t i = 0 ; i < enumData . values . size ( ) ; i + + )
{
if ( ! isErrorEnum ( enumData . values [ i ] . name ) )
{
continue ;
}
os < < replaceWithMap ( templateString ,
{ { " className " , stripErrorEnumPrefix ( enumData . values [ i ] . name ) + " Error " } ,
{ " enumName " , enumData . name } ,
{ " enumMemberName " , enumData . values [ i ] . name }
} ) ;
}
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
}
void writeThrowExceptions ( std : : ostream & os , EnumData const & enumData )
{
enterProtect ( os , enumData . protect ) ;
os < <
R " ( VULKAN_HPP_INLINE void throwResultException( Result result, char const * message )
{
switch ( result )
{
) " ;
for ( size_t i = 0 ; i < enumData . values . size ( ) ; i + + )
{
if ( ! isErrorEnum ( enumData . values [ i ] . name ) )
{
continue ;
}
const std : : string strippedExceptionName = stripErrorEnumPrefix ( enumData . values [ i ] . name ) ;
os < < " case " < < enumData . name < < " :: " < < enumData . values [ i ] . name < < " : "
< < " throw " < < strippedExceptionName < < " Error ( message ); " < < std : : endl ;
}
os < <
R " ( default: throw SystemError( make_error_code( result ) );
}
}
) " ;
leaveProtect ( os , enumData . protect ) ;
}
void writeDeleterClasses ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleters )
{
// A Deleter class for each of the Unique* classes... but only if smart handles are not switched off
os < < " #ifndef VULKAN_HPP_NO_SMART_HANDLE " < < std : : endl ;
bool first = true ;
// get type and name of the parent (holder) type
std : : string parentType = deleterTypes . first ;
std : : string parentName = parentType . empty ( ) ? " " : startLowerCase ( parentType ) ;
// iterate over the deleter types parented by this type
for ( auto const & deleterType : deleterTypes . second )
{
std : : string deleterName = startLowerCase ( deleterType ) ;
bool standardDeleter = ! parentType . empty ( ) & & ( deleterType ! = " Device " ) ; // this detects the 'standard' case for a deleter
// if this Deleter is pooled, make such a pool the last argument, otherwise an Optional allocator
auto const & dd = deleters . find ( deleterType ) ;
assert ( dd ! = deleters . end ( ) ) ;
std : : string poolName = ( dd - > second . pool . empty ( ) ? " " : startLowerCase ( dd - > second . pool ) ) ;
if ( ! first )
{
os < < std : : endl ;
}
first = false ;
os < < " class " < < deleterType < < " Deleter " < < std : : endl
< < " { " < < std : : endl
< < " public: " < < std : : endl
< < " " < < deleterType < < " Deleter( " ;
if ( standardDeleter )
{
// the standard deleter gets a parent type in the constructor
os < < parentType < < " " < < parentName < < " = " < < parentType < < " (), " ;
}
if ( poolName . empty ( ) )
{
os < < " Optional<const AllocationCallbacks> allocator = nullptr ) " < < std : : endl ;
}
else
{
assert ( ! dd - > second . pool . empty ( ) ) ;
os < < dd - > second . pool < < " " < < poolName < < " = " < < dd - > second . pool < < " () ) " < < std : : endl ;
}
// now the initializer list of the Deleter constructor
os < < " : " ;
if ( standardDeleter )
{
// the standard deleter has a parent type as a member
os < < " m_ " < < parentName < < " ( " < < parentName < < " ) " < < std : : endl
< < " , " ;
}
if ( poolName . empty ( ) )
{
// non-pooled deleter have an allocator as a member
os < < " m_allocator( allocator ) " < < std : : endl ;
}
else
{
// pooled deleter have a pool as a member
os < < " m_ " < < poolName < < " ( " < < poolName < < " ) " < < std : : endl ;
}
// besides that, the constructor is empty
os < < " {} " < < std : : endl
< < std : : endl ;
// getter for the parent type
if ( standardDeleter )
{
os < < " " < < parentType < < " get " < < parentType < < " () const { return m_ " < < parentName < < " ; } \n " ;
}
// getter for pool
if ( ! poolName . empty ( ) )
{
os < < " " < < dd - > second . pool < < " get " < < dd - > second . pool < < " () const { return m_ " < < poolName < < " ; } \n " ;
}
else // getter for allocator
{
os < < " Optional<const AllocationCallbacks> getAllocator() const { return m_allocator; } \n " ;
}
os < < " \n " ;
// the operator() calls the delete/destroy function
os < < " protected: \n "
< < " void destroy( " < < deleterType < < " " < < deleterName < < " ) \n "
< < " { \n " ;
// the delete/destroy function is either part of the parent member of the deleter argument
if ( standardDeleter )
{
os < < " m_ " < < parentName < < " . " ;
}
else
{
os < < " " < < deleterName < < " . " ;
}
os < < dd - > second . call < < " ( " ;
if ( ! poolName . empty ( ) )
{
// pooled Deleter gets the pool as the first argument
os < < " m_ " < < poolName < < " , " ;
}
if ( standardDeleter )
{
// the standard deleter gets the deleter argument as an argument
os < < deleterName ;
}
// the non-pooled deleter get the allocate as an argument (potentially after the deleterName
if ( poolName . empty ( ) )
{
if ( standardDeleter )
{
os < < " , " ;
}
os < < " m_allocator " ;
}
os < < " ); " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
// now the members of the Deleter class
os < < " private: " < < std : : endl ;
if ( standardDeleter )
{
// the parentType for the standard deleter
os < < " " < < parentType < < " m_ " < < parentName < < " ; " < < std : : endl ;
}
// the allocator for the non-pooled deleters, the pool for the pooled ones
if ( poolName . empty ( ) )
{
os < < " Optional<const AllocationCallbacks> m_allocator; " < < std : : endl ;
}
else
{
os < < " " < < dd - > second . pool < < " m_ " < < poolName < < " ; " < < std : : endl ;
}
os < < " }; " < < std : : endl ;
}
os < < " #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ " < < std : : endl
< < std : : endl ;
}
void writeDeleterForwardDeclarations ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleters )
{
// if smart handles are supported, all the Deleter classes need to be forward declared
os < < " #ifndef VULKAN_HPP_NO_SMART_HANDLE " < < std : : endl ;
bool first = true ;
std : : string firstName = deleterTypes . first . empty ( ) ? " " : startLowerCase ( deleterTypes . first ) ;
for ( auto const & dt : deleterTypes . second )
{
os < < " class " < < dt < < " Deleter; " < < std : : endl ;
os < < " template <> class UniqueHandleTraits< " < < dt < < " > {public: using deleter = " < < dt < < " Deleter; }; \n " ;
os < < " using Unique " < < dt < < " = UniqueHandle< " < < dt < < " >; " < < std : : endl ;
}
os < < " #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ " < < std : : endl
< < std : : endl ;
}
void writeEnumsToString ( std : : ostream & os , EnumData const & enumData )
{
// the helper functions to make strings out of enum values
enterProtect ( os , enumData . protect ) ;
os < < " VULKAN_HPP_INLINE std::string to_string( " < < enumData . name < < ( enumData . values . empty ( ) ? " ) " : " value) " ) < < std : : endl
< < " { " < < std : : endl ;
if ( enumData . values . empty ( ) )
{
// no enum values in this enum -> return "(void)"
os < < " return \" (void) \" ; " < < std : : endl ;
}
else
{
// otherwise switch over the value and return the a stringized version of that value (without leading 'e')
os < < " switch (value) " < < std : : endl
< < " { " < < std : : endl ;
for ( auto const & value : enumData . values )
{
os < < " case " < < enumData . name < < " :: " < < value . name < < " : return \" " < < value . name . substr ( 1 ) < < " \" ; " < < std : : endl ;
}
os < < " default: return \" invalid \" ; " < < std : : endl
< < " } " < < std : : endl ;
}
os < < " } " < < std : : endl ;
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
}
void writeFlagsToString ( std : : ostream & os , std : : string const & flagsName , EnumData const & enumData )
{
// the helper functions to make strings out of flag values
enterProtect ( os , enumData . protect ) ;
os < < " VULKAN_HPP_INLINE std::string to_string( " < < flagsName < < ( enumData . values . empty ( ) ? " ) " : " value) " ) < < std : : endl
< < " { " < < std : : endl ;
if ( enumData . values . empty ( ) )
{
// no flags values in this enum -> return "{}"
os < < " return \" {} \" ; " < < std : : endl ;
}
else
{
os < < " if (!value) return \" {} \" ; " < < std : : endl
< < " std::string result; " < < std : : endl ;
// 'or' together all the bits in the value
for ( auto valuesIt = enumData . values . begin ( ) ; valuesIt ! = enumData . values . end ( ) ; + + valuesIt )
{
os < < " if (value & " < < enumData . name < < " :: " < < valuesIt - > name < < " ) result += \" " < < valuesIt - > name . substr ( 1 ) < < " | \" ; " < < std : : endl ;
}
// cut off the last three characters from the result (being " | ")
os < < " return \" { \" + result.substr(0, result.size() - 3) + \" } \" ; " < < std : : endl ;
}
os < < " } " < < std : : endl ;
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
}
void writeTypeFlags ( std : : ostream & os , std : : string const & flagsName , FlagData const & flagData , EnumData const & enumData )
{
enterProtect ( os , flagData . protect ) ;
// each Flags class is using on the class 'Flags' with the corresponding FlagBits enum as the template parameter
os < < " using " < < flagsName < < " = Flags< " < < enumData . name < < " , Vk " < < flagsName < < " >; " < < std : : endl ;
std : : stringstream allFlags ;
for ( size_t i = 0 ; i < enumData . values . size ( ) ; i + + )
{
if ( i ! = 0 )
{
allFlags < < " | " ;
}
allFlags < < " VkFlags( " < < enumData . name < < " :: " < < enumData . values [ i ] . name < < " ) " ;
}
if ( ! enumData . values . empty ( ) )
{
const std : : string templateString = R " (
VULKAN_HPP_INLINE $ { flagsName } operator | ( $ { enumName } bit0 , $ { enumName } bit1 )
{
return $ { flagsName } ( bit0 ) | bit1 ;
}
VULKAN_HPP_INLINE $ { flagsName } operator ~ ( $ { enumName } bits )
{
return ~ ( $ { flagsName } ( bits ) ) ;
}
template < > struct FlagTraits < $ { enumName } >
{
enum
{
allFlags = $ { allFlags }
} ;
} ;
) " ;
os < < replaceWithMap ( templateString , { { " flagsName " , flagsName } , { " enumName " , enumData . name } , { " allFlags " , allFlags . str ( ) } } ) ;
}
if ( ! flagData . alias . empty ( ) )
{
os < < std : : endl
< < " using " < < flagData . alias < < " = " < < flagsName < < " ; " < < std : : endl ;
}
leaveProtect ( os , flagData . protect ) ;
os < < std : : endl ;
}
void writeTypeHandle ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , HandleData const & handleData , std : : list < DependencyData > const & dependencies )
{
enterProtect ( os , handleData . protect ) ;
// check if there are any forward dependenices for this handle -> list them first
if ( ! dependencyData . forwardDependencies . empty ( ) )
{
os < < " // forward declarations " < < std : : endl ;
for ( std : : set < std : : string > : : const_iterator it = dependencyData . forwardDependencies . begin ( ) ; it ! = dependencyData . forwardDependencies . end ( ) ; + + it )
{
assert ( vkData . structs . find ( * it ) ! = vkData . structs . end ( ) ) ;
os < < " struct " < < * it < < " ; " < < std : : endl ;
}
os < < std : : endl ;
}
// then write any forward declaration of Deleters used by this handle
std : : map < std : : string , std : : set < std : : string > > : : const_iterator deleterTypesIt = vkData . deleterTypes . find ( dependencyData . name ) ;
if ( deleterTypesIt ! = vkData . deleterTypes . end ( ) )
{
writeDeleterForwardDeclarations ( os , * deleterTypesIt , vkData . deleters ) ;
}
const std : : string memberName = startLowerCase ( dependencyData . name ) ;
const std : : string templateString =
R " ( class ${className}
{
public :
$ { className } ( )
: m_ $ { memberName } ( VK_NULL_HANDLE )
{ }
$ { className } ( std : : nullptr_t )
: m_ $ { memberName } ( VK_NULL_HANDLE )
{ }
VULKAN_HPP_TYPESAFE_EXPLICIT $ { className } ( Vk $ { className } $ { memberName } )
: m_ $ { memberName } ( $ { memberName } )
{ }
# if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
$ { className } & operator = ( Vk $ { className } $ { memberName } )
{
m_ $ { memberName } = $ { memberName } ;
return * this ;
}
# endif
$ { className } & operator = ( std : : nullptr_t )
{
m_ $ { memberName } = VK_NULL_HANDLE ;
return * this ;
}
bool operator = = ( $ { className } const & rhs ) const
{
return m_ $ { memberName } = = rhs . m_ $ { memberName } ;
}
bool operator ! = ( $ { className } const & rhs ) const
{
return m_ $ { memberName } ! = rhs . m_ $ { memberName } ;
}
bool operator < ( $ { className } const & rhs ) const
{
return m_ $ { memberName } < rhs . m_ $ { memberName } ;
}
$ { commands }
VULKAN_HPP_TYPESAFE_EXPLICIT operator Vk $ { className } ( ) const
{
return m_ $ { memberName } ;
}
explicit operator bool ( ) const
{
return m_ $ { memberName } ! = VK_NULL_HANDLE ;
}
bool operator ! ( ) const
{
return m_ $ { memberName } = = VK_NULL_HANDLE ;
}
private :
Vk $ { className } m_ $ { memberName } ;
} ;
static_assert ( sizeof ( $ { className } ) = = sizeof ( Vk $ { className } ) , " handle and wrapper have different size! " ) ;
) " ;
std : : ostringstream commands ;
// now list all the commands that are mapped to members of this class
for ( size_t i = 0 ; i < handleData . commands . size ( ) ; i + + )
{
std : : string commandName = handleData . commands [ i ] ;
std : : map < std : : string , CommandData > : : const_iterator cit = vkData . commands . find ( commandName ) ;
assert ( ( cit ! = vkData . commands . end ( ) ) & & ! cit - > second . className . empty ( ) ) ;
writeTypeCommand ( commands , " " , vkData , cit - > second , false ) ;
}
os < < replaceWithMap ( templateString , {
{ " className " , dependencyData . name } ,
{ " memberName " , memberName } ,
{ " commands " , commands . str ( ) }
} ) ;
if ( ! handleData . alias . empty ( ) )
{
os < < std : : endl
< < " using " < < handleData . alias < < " = " < < dependencyData . name < < " ; " < < std : : endl ;
}
// then the actual Deleter classes can be listed
deleterTypesIt = vkData . deleterTypes . find ( dependencyData . name ) ;
if ( deleterTypesIt ! = vkData . deleterTypes . end ( ) )
{
writeDeleterClasses ( os , * deleterTypesIt , vkData . deleters ) ;
}
// and finally the commands, that are member functions of this handle
for ( size_t i = 0 ; i < handleData . commands . size ( ) ; i + + )
{
std : : string commandName = handleData . commands [ i ] ;
std : : map < std : : string , CommandData > : : const_iterator cit = vkData . commands . find ( commandName ) ;
assert ( ( cit ! = vkData . commands . end ( ) ) & & ! cit - > second . className . empty ( ) ) ;
std : : list < DependencyData > : : const_iterator dep = std : : find_if ( dependencies . begin ( ) , dependencies . end ( ) , [ commandName ] ( DependencyData const & dd ) { return dd . name = = commandName ; } ) ;
assert ( dep ! = dependencies . end ( ) & & ( dep - > name = = cit - > second . fullName ) ) ;
writeTypeCommand ( os , " " , vkData , cit - > second , true ) ;
}
leaveProtect ( os , handleData . protect ) ;
}
void writeTypeScalar ( std : : ostream & os , DependencyData const & dependencyData )
{
assert ( dependencyData . dependencies . size ( ) = = 1 ) ;
os < < " using " < < dependencyData . name < < " = " < < * dependencyData . dependencies . begin ( ) < < " ; " < < std : : endl
< < std : : endl ;
}
bool containsUnion ( std : : string const & type , std : : map < std : : string , StructData > const & structs )
{
// a simple recursive check if a type is or contains a union
std : : map < std : : string , StructData > : : const_iterator sit = structs . find ( type ) ;
bool found = ( sit ! = structs . end ( ) ) ;
if ( found )
{
found = sit - > second . isUnion ;
for ( std : : vector < MemberData > : : const_iterator mit = sit - > second . members . begin ( ) ; mit ! = sit - > second . members . end ( ) & & ! found ; + + mit )
{
found = ( mit - > type = = mit - > pureType ) & & containsUnion ( mit - > type , structs ) ;
}
}
return found ;
}
void writeTypeStruct ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , std : : map < std : : string , std : : string > const & defaultValues )
{
std : : map < std : : string , StructData > : : const_iterator it = vkData . structs . find ( dependencyData . name ) ;
assert ( it ! = vkData . structs . end ( ) ) ;
enterProtect ( os , it - > second . protect ) ;
os < < " struct " < < dependencyData . name < < std : : endl
< < " { " < < std : : endl ;
writeStructConstructor ( os , dependencyData . name , it - > second , vkData . vkTypes , vkData . nameMap , defaultValues ) ;
// create the setters
if ( ! it - > second . returnedOnly )
{
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
writeStructSetter ( os , dependencyData . name , it - > second . members [ i ] , vkData . vkTypes ) ;
}
}
// the cast-operator to the wrapped struct
os < < " operator const Vk " < < dependencyData . name < < " &() const " < < std : : endl
< < " { " < < std : : endl
< < " return *reinterpret_cast<const Vk " < < dependencyData . name < < " *>(this); " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
// operator==() and operator!=()
// only structs without a union as a member can have a meaningfull == and != operation; we filter them out
if ( ! containsUnion ( dependencyData . name , vkData . structs ) )
{
// two structs are compared by comparing each of the elements
os < < " bool operator==( " < < dependencyData . name < < " const& rhs ) const " < < std : : endl
< < " { " < < std : : endl
< < " return " ;
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
if ( i ! = 0 )
{
os < < std : : endl < < " && " ;
}
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < " ( memcmp( " < < it - > second . members [ i ] . name < < " , rhs. " < < it - > second . members [ i ] . name < < " , " < < it - > second . members [ i ] . arraySize < < " * sizeof( " < < it - > second . members [ i ] . type < < " ) ) == 0 ) " ;
}
else
{
os < < " ( " < < it - > second . members [ i ] . name < < " == rhs. " < < it - > second . members [ i ] . name < < " ) " ;
}
}
os < < " ; " < < std : : endl
< < " } " < < std : : endl
< < std : : endl
< < " bool operator!=( " < < dependencyData . name < < " const& rhs ) const " < < std : : endl
< < " { " < < std : : endl
< < " return !operator==( rhs ); " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
}
// the member variables
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
if ( it - > second . members [ i ] . type = = " StructureType " )
{
assert ( ( i = = 0 ) & & ( it - > second . members [ i ] . name = = " sType " ) ) ;
os < < " private: " < < std : : endl
< < " StructureType sType; " < < std : : endl
< < std : : endl
< < " public: " < < std : : endl ;
}
else
{
os < < " " < < it - > second . members [ i ] . type < < " " < < it - > second . members [ i ] . name ;
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < " [ " < < it - > second . members [ i ] . arraySize < < " ] " ;
}
os < < " ; " < < std : : endl ;
}
}
os < < " }; " < < std : : endl
< < " static_assert( sizeof( " < < dependencyData . name < < " ) == sizeof( Vk " < < dependencyData . name < < " ), \" struct and wrapper have different size! \" ); " < < std : : endl ;
leaveProtect ( os , it - > second . protect ) ;
os < < std : : endl ;
}
void writeStructureChainValidation ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData )
{
std : : map < std : : string , StructData > : : const_iterator it = vkData . structs . find ( dependencyData . name ) ;
assert ( it ! = vkData . structs . end ( ) ) ;
if ( ! it - > second . structExtends . empty ( ) ) {
enterProtect ( os , it - > second . protect ) ;
// write out allowed structure chains
for ( auto extendName : it - > second . structExtends )
{
// We do not have to generate the templates for aliased structs;
if ( vkData . aliases . find ( extendName ) = = vkData . aliases . end ( ) )
{
std : : map < std : : string , StructData > : : const_iterator itExtend = vkData . structs . find ( extendName ) ;
assert ( itExtend ! = vkData . structs . end ( ) ) ;
enterProtect ( os , itExtend - > second . protect ) ;
os < < " template <> struct isStructureChainValid< " < < extendName < < " , " < < dependencyData . name < < " >{ enum { value = true }; }; " < < std : : endl ;
leaveProtect ( os , itExtend - > second . protect ) ;
}
}
leaveProtect ( os , it - > second . protect ) ;
}
}
void writeTypeUnion ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , std : : map < std : : string , std : : string > const & defaultValues )
{
std : : map < std : : string , StructData > : : const_iterator it = vkData . structs . find ( dependencyData . name ) ;
assert ( it ! = vkData . structs . end ( ) ) ;
std : : ostringstream oss ;
os < < " union " < < dependencyData . name < < std : : endl
< < " { " < < std : : endl ;
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
// one constructor per union element
os < < " " < < dependencyData . name < < " ( " ;
if ( it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < it - > second . members [ i ] . type < < " " ;
}
else
{
os < < " const std::array< " < < it - > second . members [ i ] . type < < " , " < < it - > second . members [ i ] . arraySize < < " >& " ;
}
os < < it - > second . members [ i ] . name < < " _ " ;
// just the very first constructor gets default arguments
if ( i = = 0 )
{
std : : map < std : : string , std : : string > : : const_iterator defaultIt = defaultValues . find ( it - > second . members [ i ] . pureType ) ;
assert ( defaultIt ! = defaultValues . end ( ) ) ;
if ( it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < " = " < < defaultIt - > second ;
}
else
{
os < < " = { { " < < defaultIt - > second < < " } } " ;
}
}
os < < " ) " < < std : : endl
< < " { " < < std : : endl
< < " " ;
if ( it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < it - > second . members [ i ] . name < < " = " < < it - > second . members [ i ] . name < < " _ " ;
}
else
{
os < < " memcpy( & " < < it - > second . members [ i ] . name < < " , " < < it - > second . members [ i ] . name < < " _.data(), " < < it - > second . members [ i ] . arraySize < < " * sizeof( " < < it - > second . members [ i ] . type < < " ) ) " ;
}
os < < " ; " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
}
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
// one setter per union element
assert ( ! it - > second . returnedOnly ) ;
writeStructSetter ( os , dependencyData . name , it - > second . members [ i ] , vkData . vkTypes ) ;
}
// the implicit cast operator to the native type
os < < " operator Vk " < < dependencyData . name < < " const& () const " < < std : : endl
< < " { " < < std : : endl
< < " return *reinterpret_cast<const Vk " < < dependencyData . name < < " *>(this); " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
// the union member variables
// if there's at least one Vk... type in this union, check for unrestricted unions support
bool needsUnrestrictedUnions = false ;
for ( size_t i = 0 ; i < it - > second . members . size ( ) & & ! needsUnrestrictedUnions ; i + + )
{
needsUnrestrictedUnions = ( vkData . vkTypes . find ( it - > second . members [ i ] . type ) ! = vkData . vkTypes . end ( ) ) ;
}
if ( needsUnrestrictedUnions )
{
os < < " #ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS " < < std : : endl ;
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
os < < " " < < it - > second . members [ i ] . type < < " " < < it - > second . members [ i ] . name ;
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < " [ " < < it - > second . members [ i ] . arraySize < < " ] " ;
}
os < < " ; " < < std : : endl ;
}
os < < " #else " < < std : : endl ;
}
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
os < < " " ;
if ( vkData . vkTypes . find ( it - > second . members [ i ] . type ) ! = vkData . vkTypes . end ( ) )
{
os < < " Vk " ;
}
os < < it - > second . members [ i ] . type < < " " < < it - > second . members [ i ] . name ;
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
{
os < < " [ " < < it - > second . members [ i ] . arraySize < < " ] " ;
}
os < < " ; " < < std : : endl ;
}
if ( needsUnrestrictedUnions )
{
os < < " #endif // VULKAN_HPP_HAS_UNRESTRICTED_UNIONS " < < std : : endl ;
}
os < < " }; " < < std : : endl
< < std : : endl ;
}
void writeTypes ( std : : ostream & os , VkData const & vkData , std : : map < std : : string , std : : string > const & defaultValues )
{
for ( std : : list < DependencyData > : : const_iterator it = vkData . dependencies . begin ( ) ; it ! = vkData . dependencies . end ( ) ; + + it )
{
switch ( it - > category )
{
case DependencyData : : Category : : ALIAS :
writeTypeAlias ( os , vkData , * it ) ;
break ;
case DependencyData : : Category : : COMMAND :
writeTypeCommand ( os , vkData , * it ) ;
break ;
case DependencyData : : Category : : ENUM :
assert ( vkData . enums . find ( it - > name ) ! = vkData . enums . end ( ) ) ;
writeTypeEnum ( os , vkData . enums . find ( it - > name ) - > second ) ;
break ;
case DependencyData : : Category : : FLAGS :
assert ( vkData . flags . find ( it - > name ) ! = vkData . flags . end ( ) ) ;
writeTypeFlags ( os , it - > name , vkData . flags . find ( it - > name ) - > second , vkData . enums . find ( generateEnumNameForFlags ( it - > name ) ) - > second ) ;
break ;
case DependencyData : : Category : : FUNC_POINTER :
case DependencyData : : Category : : REQUIRED :
// skip FUNC_POINTER and REQUIRED, they just needed to be in the dependencies list to resolve dependencies
break ;
case DependencyData : : Category : : HANDLE :
assert ( vkData . handles . find ( it - > name ) ! = vkData . handles . end ( ) ) ;
writeTypeHandle ( os , vkData , * it , vkData . handles . find ( it - > name ) - > second , vkData . dependencies ) ;
break ;
case DependencyData : : Category : : SCALAR :
writeTypeScalar ( os , * it ) ;
break ;
case DependencyData : : Category : : STRUCT :
writeTypeStruct ( os , vkData , * it , defaultValues ) ;
break ;
case DependencyData : : Category : : UNION :
assert ( vkData . structs . find ( it - > name ) ! = vkData . structs . end ( ) ) ;
writeTypeUnion ( os , vkData , * it , defaultValues ) ;
break ;
default :
assert ( false ) ;
break ;
}
}
}
void writeVersionCheck ( std : : ostream & os , std : : string const & version )
{
os < < " static_assert( VK_HEADER_VERSION == " < < version < < " , \" Wrong VK_HEADER_VERSION! \" ); " < < std : : endl
< < std : : endl ;
}
void writeTypesafeCheck ( std : : ostream & os , std : : string const & typesafeCheck )
{
os < < " // 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default. " < < std : : endl
< < " // To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION " < < std : : endl
< < typesafeCheck < < std : : endl
< < " # if !defined( VULKAN_HPP_TYPESAFE_CONVERSION ) " < < std : : endl
< < " # define VULKAN_HPP_TYPESAFE_CONVERSION " < < std : : endl
< < " # endif " < < std : : endl
< < " #endif " < < std : : endl ;
}
int main ( int argc , char * * argv )
{
try {
tinyxml2 : : XMLDocument doc ;
std : : string filename = ( argc = = 1 ) ? VK_SPEC : argv [ 1 ] ;
std : : cout < < " Loading vk.xml from " < < filename < < std : : endl ;
std : : cout < < " Writing vulkan.hpp to " < < VULKAN_HPP < < std : : endl ;
tinyxml2 : : XMLError error = doc . LoadFile ( filename . c_str ( ) ) ;
if ( error ! = tinyxml2 : : XML_SUCCESS )
{
std : : cout < < " VkGenerate: failed to load file " < < filename < < " . Error code: " < < error < < std : : endl ;
return - 1 ;
}
tinyxml2 : : XMLElement * registryElement = doc . FirstChildElement ( ) ;
assert ( strcmp ( registryElement - > Value ( ) , " registry " ) = = 0 ) ;
assert ( ! registryElement - > NextSiblingElement ( ) ) ;
VkData vkData ;
vkData . handles [ " " ] ; // insert the default "handle" without class (for createInstance, and such)
vkData . tags . insert ( " KHX " ) ; // insert a non-listed tag
for ( tinyxml2 : : XMLElement * child = registryElement - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
assert ( child - > Value ( ) ) ;
const std : : string value = child - > Value ( ) ;
if ( value = = " commands " )
{
readCommands ( child , vkData ) ;
}
else if ( value = = " comment " )
{
// get the vulkan license header and skip any leading spaces
readComment ( child , vkData . vulkanLicenseHeader ) ;
vkData . vulkanLicenseHeader . erase ( vkData . vulkanLicenseHeader . begin ( ) , std : : find_if ( vkData . vulkanLicenseHeader . begin ( ) , vkData . vulkanLicenseHeader . end ( ) , [ ] ( char c ) { return ! std : : isspace ( c ) ; } ) ) ;
}
else if ( value = = " enums " )
{
readEnums ( child , vkData ) ;
}
else if ( value = = " extensions " )
{
readExtensions ( child , vkData ) ;
}
else if ( value = = " feature " )
{
readFeature ( child , vkData . enums , vkData . nameMap ) ;
}
else if ( value = = " tags " )
{
readTags ( child , vkData . tags ) ;
}
else if ( value = = " types " )
{
readTypes ( child , vkData ) ;
}
else
{
assert ( value = = " vendorids " ) ;
# if !defined(NDEBUG)
skipVendorIDs ( child , vkData . vendorIDs ) ;
# endif
}
}
sortDependencies ( vkData . dependencies ) ;
# if !defined(NDEBUG)
for ( auto const & ext : vkData . extensions )
{
for ( auto const & req : ext . second . requires )
{
auto reqExt = vkData . extensions . find ( req ) ;
assert ( reqExt ! = vkData . extensions . end ( ) ) ;
assert ( reqExt - > second . protect . empty ( ) | | ( reqExt - > second . protect = = ext . second . protect ) ) ;
}
}
# endif
std : : map < std : : string , std : : string > defaultValues ;
createDefaults ( vkData , defaultValues ) ;
std : : ofstream ofs ( VULKAN_HPP ) ;
ofs < < vkData . vulkanLicenseHeader < < std : : endl
< < R " (
# ifndef VULKAN_HPP
# define VULKAN_HPP
# include <algorithm>
# include <array>
# include <cassert>
# include <cstddef>
# include <cstdint>
# include <cstring>
# include <initializer_list>
# include <string>
# include <system_error>
# include <tuple>
# include <type_traits>
# include <vulkan/vulkan.h>
# ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
# include <memory>
# include <vector>
# endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
) " ;
writeVersionCheck ( ofs , vkData . version ) ;
writeTypesafeCheck ( ofs , vkData . typesafeCheck ) ;
ofs < < versionCheckHeader
< < inlineHeader
< < explicitHeader
< < std : : endl
< < vkNamespace
< < flagsHeader
< < optionalClassHeader
< < arrayProxyHeader
< < uniqueHandleHeader
< < structureChainHeader ;
// first of all, write out vk::Result and the exception handling stuff
std : : list < DependencyData > : : const_iterator it = std : : find_if ( vkData . dependencies . begin ( ) , vkData . dependencies . end ( ) , [ ] ( DependencyData const & dp ) { return dp . name = = " Result " ; } ) ;
assert ( it ! = vkData . dependencies . end ( ) ) ;
writeTypeEnum ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
writeEnumsToString ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
ofs < < " #ifndef VULKAN_HPP_NO_EXCEPTIONS " ;
ofs < < exceptionHeader ;
ofs < < exceptionClassesHeader ;
writeExceptionsForEnum ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
writeThrowExceptions ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
ofs < < " #endif " < < std : : endl ;
vkData . dependencies . erase ( it ) ;
ofs < < " } // namespace VULKAN_HPP_NAMESPACE " < < std : : endl
< < std : : endl
< < " namespace std " < < std : : endl
< < " { " < < std : : endl
< < " template <> " < < std : : endl
< < " struct is_error_code_enum<VULKAN_HPP_NAMESPACE::Result> : public true_type " < < std : : endl
< < " {}; " < < std : : endl
< < " } " < < std : : endl
< < std : : endl
< < " namespace VULKAN_HPP_NAMESPACE " < < std : : endl
< < " { " < < std : : endl
< < resultValueHeader
< < createResultValueHeader ;
assert ( vkData . deleterTypes . find ( " " ) ! = vkData . deleterTypes . end ( ) ) ;
writeTypes ( ofs , vkData , defaultValues ) ;
// write all template functions for the structure pointer chain validation
for ( auto it = vkData . dependencies . begin ( ) ; it ! = vkData . dependencies . end ( ) ; + + it )
{
switch ( it - > category )
{
case DependencyData : : Category : : STRUCT :
writeStructureChainValidation ( ofs , vkData , * it ) ;
break ;
}
}
// write all the to_string functions for enums and flags
for ( auto it = vkData . dependencies . begin ( ) ; it ! = vkData . dependencies . end ( ) ; + + it )
{
switch ( it - > category )
{
case DependencyData : : Category : : ENUM :
assert ( vkData . enums . find ( it - > name ) ! = vkData . enums . end ( ) ) ;
writeEnumsToString ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
break ;
case DependencyData : : Category : : FLAGS :
writeFlagsToString ( ofs , it - > name , vkData . enums . find ( * it - > dependencies . begin ( ) ) - > second ) ;
break ;
}
}
ofs < < " } // namespace VULKAN_HPP_NAMESPACE " < < std : : endl
< < std : : endl
< < " #endif " < < std : : endl ;
}
catch ( std : : exception const & e )
{
std : : cout < < " caught exception: " < < e . what ( ) < < std : : endl ;
return - 1 ;
}
catch ( . . . )
{
std : : cout < < " caught unknown exception " < < std : : endl ;
return - 1 ;
}
}
# if !defined(NDEBUG)
void skipTypeEnum ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > const & attributes )
{
assert ( ( attributes . find ( " category " ) ! = attributes . end ( ) ) & & ( attributes . find ( " category " ) - > second = = " enum " ) ) ;
assert ( ( attributes . size ( ) = = 1 ) | | ( ( attributes . size ( ) = = 2 ) & & ( attributes . find ( " name " ) ! = attributes . end ( ) ) ) ) ;
assert ( ! element - > FirstChildElement ( ) ) ;
}
void skipTypeInclude ( tinyxml2 : : XMLElement * element , std : : map < std : : string , std : : string > const & attributes )
{
assert ( ( attributes . find ( " category " ) ! = attributes . end ( ) ) & & ( attributes . find ( " category " ) - > second = = " include " ) ) ;
assert ( ( attributes . size ( ) = = 1 ) | | ( ( attributes . size ( ) = = 2 ) & & ( attributes . find ( " name " ) ! = attributes . end ( ) ) ) ) ;
auto child = element - > FirstChildElement ( ) ;
assert ( ! child | | ! child - > NextSiblingElement ( ) ) ;
if ( child )
{
assert ( ! child - > FirstAttribute ( ) & & ! child - > FirstChildElement ( ) ) ;
std : : string name = child - > Name ( ) ;
assert ( name = = " name " ) ;
}
}
void skipVendorID ( tinyxml2 : : XMLElement * element , std : : vector < VendorIDData > & vendorIDs )
{
VendorIDData vendorID ;
for ( auto attribute = element - > FirstAttribute ( ) ; attribute ; attribute = attribute - > Next ( ) )
{
std : : string name = attribute - > Name ( ) ;
if ( name = = " comment " )
{
vendorID . comment = attribute - > Value ( ) ;
}
else if ( name = = " id " )
{
vendorID . id = attribute - > Value ( ) ;
}
else
{
assert ( name = = " name " ) ;
vendorID . name = attribute - > Value ( ) ;
}
}
vendorIDs . push_back ( vendorID ) ;
}
void skipVendorIDs ( tinyxml2 : : XMLElement * element , std : : vector < VendorIDData > & vendorIDs )
{
assert ( element - > FirstAttribute ( ) & & ! element - > FirstAttribute ( ) - > Next ( ) & & element - > Attribute ( " comment " ) ) ;
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
{
std : : string value = child - > Value ( ) ;
assert ( value = = " vendorid " ) ;
skipVendorID ( child , vendorIDs ) ;
}
}
# endif