2016-07-25 18:31:10 +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>
2017-02-08 12:56:06 +00:00
# include <iterator>
2016-07-25 18:31:10 +00:00
# include <list>
# include <map>
# include <set>
# include <sstream>
# include <string>
# include <vector>
# include <exception>
2017-05-16 13:32:14 +00:00
# include <regex>
# include <iterator>
2016-07-25 18:31:10 +00:00
# include <tinyxml2.h>
2017-04-28 16:49:59 +00:00
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 " vk::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 )
{
}
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 " (
2016-11-04 08:14:53 +00:00
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 ;
} ;
2017-04-28 16:49:59 +00:00
) " ;
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 ( ) )
{ }
2016-11-04 08:14:53 +00:00
2017-04-28 16:49:59 +00:00
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
2016-11-04 08:14:53 +00:00
) " ;
2016-07-25 18:31:10 +00:00
2017-04-28 16:49:59 +00:00
const std : : string versionCheckHeader = R " (
2017-02-15 16:07:50 +00:00
# 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
2017-04-28 16:49:59 +00:00
) " ;
2016-07-25 18:31:10 +00:00
2017-04-28 16:49:59 +00:00
const std : : string inlineHeader = R " (
2016-10-25 14:51:40 +00:00
# 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
2016-10-17 08:34:14 +00:00
# endif
2017-04-28 16:49:59 +00:00
) " ;
2016-10-17 08:34:14 +00:00
2017-04-28 16:49:59 +00:00
const std : : string explicitHeader = R " (
2017-02-15 16:07:50 +00:00
# if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
# define VULKAN_HPP_TYPESAFE_EXPLICIT
# else
# define VULKAN_HPP_TYPESAFE_EXPLICIT explicit
# endif
2017-04-28 16:49:59 +00:00
) " ;
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
}
2016-10-17 08:34:14 +00:00
2017-04-28 16:49:59 +00:00
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 " (
2017-01-27 14:15:50 +00:00
# if defined(VULKAN_HPP_NO_EXCEPTIONS) && !defined(VULKAN_HPP_NO_SMART_HANDLE)
# define VULKAN_HPP_NO_SMART_HANDLE
# endif
2016-07-26 14:28:30 +00:00
2017-01-27 14:15:50 +00:00
# ifndef VULKAN_HPP_NO_SMART_HANDLE
template < typename Type , typename Deleter >
class UniqueHandle
{
public :
2017-02-06 12:26:43 +00:00
explicit UniqueHandle ( Type const & value = Type ( ) , Deleter const & deleter = Deleter ( ) )
2017-01-27 14:15:50 +00:00
: m_value ( value )
, m_deleter ( deleter )
{ }
UniqueHandle ( UniqueHandle const & ) = delete ;
UniqueHandle ( UniqueHandle & & other )
: m_value ( other . release ( ) )
, m_deleter ( std : : move ( other . m_deleter ) )
{ }
~ UniqueHandle ( )
{
destroy ( ) ;
}
UniqueHandle & operator = ( UniqueHandle const & ) = delete ;
UniqueHandle & operator = ( UniqueHandle & & other )
{
reset ( other . release ( ) ) ;
m_deleter = std : : move ( other . m_deleter ) ;
return * this ;
}
explicit operator bool ( ) const
{
return m_value . operator bool ( ) ;
}
Type const * operator - > ( ) const
{
return & m_value ;
}
Type const & operator * ( ) const
{
return m_value ;
}
Type get ( ) const
{
return m_value ;
}
Deleter & getDeleter ( )
{
return m_deleter ;
}
Deleter const & getDeleter ( ) const
{
return m_deleter ;
}
void reset ( Type const & value = Type ( ) )
{
if ( m_value ! = value )
{
destroy ( ) ;
m_value = value ;
}
}
Type release ( )
{
Type value = m_value ;
m_value = nullptr ;
return value ;
}
void swap ( UniqueHandle < Type , Deleter > & rhs )
{
std : : swap ( m_value , rhs . m_value ) ;
std : : swap ( m_deleter , rhs . m_deleter ) ;
}
private :
void destroy ( )
{
if ( m_value )
{
m_deleter ( m_value ) ;
}
}
private :
Type m_value ;
Deleter m_deleter ;
} ;
template < typename Type , typename Deleter >
VULKAN_HPP_INLINE void swap ( UniqueHandle < Type , Deleter > & lhs , UniqueHandle < Type , Deleter > & rhs )
{
lhs . swap ( rhs ) ;
}
# endif
2017-04-28 16:49:59 +00:00
) " ;
2017-01-27 14:15:50 +00:00
2017-05-16 13:32:14 +00:00
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 ;
}
2017-05-11 16:21:14 +00:00
2017-01-27 14:15:50 +00:00
struct ParamData
2016-07-25 18:31:10 +00:00
{
std : : string type ;
std : : string name ;
std : : string arraySize ;
std : : string pureType ;
std : : string len ;
bool optional ;
} ;
struct CommandData
{
2017-02-08 12:56:06 +00:00
CommandData ( std : : string const & t , std : : string const & fn )
: returnType ( t )
, fullName ( fn )
2017-02-13 08:23:35 +00:00
, returnParam ( ~ 0 )
, templateParam ( ~ 0 )
2016-07-25 18:31:10 +00:00
, twoStep ( false )
{ }
2017-02-13 08:23:35 +00:00
std : : string className ;
std : : string enhancedReturnType ;
2017-02-08 12:56:06 +00:00
std : : string fullName ;
2017-01-27 14:15:50 +00:00
std : : vector < ParamData > params ;
2016-07-25 18:31:10 +00:00
std : : string protect ;
2017-02-13 08:23:35 +00:00
std : : string reducedName ;
size_t returnParam ;
std : : string returnType ;
std : : set < size_t > skippedParams ;
std : : vector < std : : string > successCodes ;
size_t templateParam ;
2016-07-25 18:31:10 +00:00
bool twoStep ;
2017-02-13 08:23:35 +00:00
std : : map < size_t , size_t > vectorParams ;
2016-07-25 18:31:10 +00:00
} ;
struct DependencyData
{
enum class Category
{
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 ;
2016-12-01 21:00:03 +00:00
std : : set < std : : string > forwardDependencies ;
2016-07-25 18:31:10 +00:00
} ;
struct NameValue
{
std : : string name ;
std : : string value ;
} ;
struct EnumData
{
2017-02-08 12:56:06 +00:00
EnumData ( std : : string const & n , bool b = false )
: name ( n )
, bitmask ( b )
{ }
2017-04-06 12:36:03 +00:00
void addEnumMember ( std : : string const & name , std : : string const & tag ) ;
2017-02-08 12:56:06 +00:00
std : : string name ;
2016-07-25 18:31:10 +00:00
std : : string prefix ;
std : : string postfix ;
std : : vector < NameValue > members ;
std : : string protect ;
2017-02-08 12:56:06 +00:00
bool bitmask ;
2016-07-25 18:31:10 +00:00
} ;
struct FlagData
{
std : : string protect ;
} ;
struct HandleData
{
std : : vector < std : : string > commands ;
2016-12-01 21:00:03 +00:00
std : : string protect ;
2016-07-25 18:31:10 +00:00
} ;
struct ScalarData
{
std : : string protect ;
} ;
2017-01-27 14:15:50 +00:00
struct MemberData
{
std : : string type ;
std : : string name ;
std : : string arraySize ;
std : : string pureType ;
} ;
2016-07-25 18:31:10 +00:00
struct StructData
{
StructData ( )
: returnedOnly ( false )
{ }
bool returnedOnly ;
2016-07-26 14:09:41 +00:00
bool isUnion ;
2016-07-25 18:31:10 +00:00
std : : vector < MemberData > members ;
std : : string protect ;
} ;
2017-01-27 14:15:50 +00:00
struct DeleterData
{
std : : string pool ;
std : : string call ;
} ;
2016-07-25 18:31:10 +00:00
struct VkData
{
2017-01-27 14:15:50 +00:00
std : : map < std : : string , CommandData > commands ;
std : : list < DependencyData > dependencies ;
std : : map < std : : string , std : : set < std : : string > > deleterTypes ; // map from parent type to set of child types
std : : map < std : : string , DeleterData > deleterData ; // map from child types to corresponding deleter data
std : : map < std : : string , EnumData > enums ;
std : : map < std : : string , FlagData > flags ;
std : : map < std : : string , HandleData > handles ;
std : : map < std : : string , ScalarData > scalars ;
std : : map < std : : string , StructData > structs ;
std : : set < std : : string > tags ;
std : : string typesafeCheck ;
std : : string version ;
std : : set < std : : string > vkTypes ;
std : : string vulkanLicenseHeader ;
2016-07-25 18:31:10 +00:00
} ;
void createDefaults ( VkData const & vkData , std : : map < std : : string , std : : string > & defaultValues ) ;
2017-02-13 08:23:35 +00:00
void determineEnhancedReturnType ( CommandData & commandData ) ;
void determineReducedName ( CommandData & commandData ) ;
void determineReturnParam ( CommandData & commandData ) ;
void determineSkippedParams ( CommandData & commandData ) ;
void determineTemplateParam ( CommandData & commandData ) ;
void determineVectorParams ( CommandData & commandData ) ;
2017-02-08 12:56:06 +00:00
void enterProtect ( std : : ostream & os , std : : string const & protect ) ;
2016-07-25 18:31:10 +00:00
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 ) ;
2017-02-08 12:56:06 +00:00
bool hasPointerParam ( std : : vector < ParamData > const & params ) ;
void leaveProtect ( std : : ostream & os , std : : string const & protect ) ;
void linkCommandToHandle ( VkData & vkData , CommandData & commandData ) ;
2017-03-08 13:14:01 +00:00
std : : string readArraySize ( tinyxml2 : : XMLNode * node , std : : string & name ) ;
2017-02-08 12:56:06 +00:00
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 ) ;
2016-07-25 18:31:10 +00:00
void readCommands ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readCommandsCommand ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
2017-02-08 12:56:06 +00:00
std : : vector < std : : string > readCommandSuccessCodes ( tinyxml2 : : XMLElement * element , std : : set < std : : string > const & tags ) ;
2016-07-25 18:31:10 +00:00
void readComment ( tinyxml2 : : XMLElement * element , std : : string & header ) ;
void readEnums ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
2017-04-06 12:36:03 +00:00
void readEnumsEnum ( tinyxml2 : : XMLElement * element , EnumData & enumData ) ;
2017-02-14 17:28:05 +00:00
void readDisabledExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
2017-03-08 13:14:01 +00:00
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 ) ;
2016-07-25 18:31:10 +00:00
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 ) ;
2017-03-08 13:14:01 +00:00
void readExtensionType ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect ) ;
tinyxml2 : : XMLNode * readType ( tinyxml2 : : XMLNode * element , std : : string & type , std : : string & pureType ) ;
2016-07-25 18:31:10 +00:00
void readTypeBasetype ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies ) ;
void readTypeBitmask ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readTypeDefine ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
void readTypeFuncpointer ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies ) ;
void readTypeHandle ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
2017-03-08 13:14:01 +00:00
void readTypeStruct ( tinyxml2 : : XMLElement * element , VkData & vkData , bool isUnion ) ;
2016-07-25 18:31:10 +00:00
void readTypeStructMember ( tinyxml2 : : XMLElement * element , std : : vector < MemberData > & members , std : : set < std : : string > & dependencies ) ;
void readTags ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & tags ) ;
void readTypes ( tinyxml2 : : XMLElement * element , VkData & vkData ) ;
std : : string reduceName ( std : : string const & name , bool singular = false ) ;
2017-02-08 12:56:06 +00:00
void registerDeleter ( VkData & vkData , CommandData const & commandData ) ;
2017-04-24 07:30:02 +00:00
std : : string startLowerCase ( std : : string const & input ) ;
std : : string startUpperCase ( std : : string const & input ) ;
2017-01-27 14:15:50 +00:00
void sortDependencies ( std : : list < DependencyData > & dependencies ) ;
2017-04-06 12:36:03 +00:00
std : : string strip ( std : : string const & value , std : : string const & prefix , std : : string const & postfix = std : : string ( ) ) ;
2017-04-24 07:30:02 +00:00
std : : string stripPluralS ( std : : string const & name ) ;
2016-07-25 18:31:10 +00:00
std : : string toCamelCase ( std : : string const & value ) ;
std : : string toUpperCase ( std : : string const & name ) ;
2017-01-27 14:15:50 +00:00
std : : string trimEnd ( std : : string const & input ) ;
2017-02-13 08:23:35 +00:00
void writeCall ( std : : ostream & os , CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular ) ;
2017-05-11 16:21:14 +00:00
std : : string generateCall ( CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular ) ;
2017-04-24 07:30:02 +00:00
void writeCallCountParameter ( std : : ostream & os , CommandData const & commandData , bool singular , std : : map < size_t , size_t > : : const_iterator it ) ;
void writeCallParameter ( std : : ostream & os , ParamData const & paramData , std : : set < std : : string > const & vkTypes ) ;
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 ) ;
2017-05-16 13:32:14 +00:00
void writeDeleterClasses ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleterData ) ;
void writeDeleterForwardDeclarations ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleterData ) ;
void writeEnumsToString ( std : : ostream & os , EnumData const & enumData ) ;
void writeFlagsToString ( std : : ostream & os , std : : string const & flagsName , EnumData const & enumData ) ;
2017-04-24 07:30:02 +00:00
void writeFunction ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition , bool enhanced , bool singular , bool unique ) ;
void writeFunctionBodyEnhanced ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular ) ;
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 ) ;
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 ) ;
2017-02-13 08:23:35 +00:00
void writeFunctionHeaderArguments ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool enhanced , bool singular , bool withDefaults ) ;
2017-04-24 07:30:02 +00:00
void writeFunctionHeaderArgumentsEnhanced ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool singular , bool withDefaults ) ;
void writeFunctionHeaderArgumentsStandard ( std : : ostream & os , CommandData const & commandData ) ;
2017-02-13 08:23:35 +00:00
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 ) ;
2017-04-24 07:30:02 +00:00
void writeFunctionHeaderTemplate ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool withDefault ) ;
void writeReinterpretCast ( std : : ostream & os , bool leadingConst , bool vulkanType , std : : string const & type , bool trailingPointerToConst ) ;
2017-05-16 13:32:14 +00:00
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 & 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 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 ) ;
2017-04-26 07:30:24 +00:00
bool isErrorEnum ( std : : string const & enumName ) ;
std : : string stripErrorEnumPrefix ( std : : string const & enumName ) ;
2017-05-16 13:32:14 +00:00
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 ) ;
2016-07-25 18:31:10 +00:00
2017-04-06 12:36:03 +00:00
void EnumData : : addEnumMember ( std : : string const & name , std : : string const & tag )
2016-07-25 18:31:10 +00:00
{
2017-04-06 12:36:03 +00:00
NameValue nv ;
nv . name = " e " + toCamelCase ( strip ( name , prefix , postfix ) ) ;
nv . value = name ;
if ( bitmask )
2016-07-25 18:31:10 +00:00
{
2017-04-06 12:36:03 +00:00
size_t pos = nv . name . find ( " Bit " ) ;
2016-07-25 18:31:10 +00:00
if ( pos ! = std : : string : : npos )
{
2017-04-06 12:36:03 +00:00
nv . name . erase ( pos , 3 ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-04-06 12:36:03 +00:00
if ( ! tag . empty ( ) & & ( nv . name . substr ( nv . name . length ( ) - tag . length ( ) ) = = toCamelCase ( tag ) ) )
2016-07-25 18:31:10 +00:00
{
2017-04-06 12:36:03 +00:00
nv . name = nv . name . substr ( 0 , nv . name . length ( ) - tag . length ( ) ) + tag ;
2016-07-25 18:31:10 +00:00
}
2017-04-06 12:36:03 +00:00
members . push_back ( nv ) ;
2016-07-25 18:31:10 +00:00
}
void createDefaults ( VkData const & vkData , std : : map < std : : string , std : : string > & defaultValues )
{
2017-03-08 13:14:01 +00:00
for ( auto dependency : vkData . dependencies )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
assert ( defaultValues . find ( dependency . name ) = = defaultValues . end ( ) ) ;
switch ( dependency . category )
2016-07-25 18:31:10 +00:00
{
case DependencyData : : Category : : COMMAND : // commands should never be asked for defaults
break ;
case DependencyData : : Category : : ENUM :
{
2017-03-08 13:14:01 +00:00
assert ( vkData . enums . find ( dependency . name ) ! = vkData . enums . end ( ) ) ;
EnumData const & enumData = vkData . enums . find ( dependency . name ) - > second ;
2016-07-25 18:31:10 +00:00
if ( ! enumData . members . empty ( ) )
{
2017-03-08 13:14:01 +00:00
defaultValues [ dependency . name ] = dependency . name + " :: " + vkData . enums . find ( dependency . name ) - > second . members . front ( ) . name ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-03-08 13:14:01 +00:00
defaultValues [ dependency . name ] = dependency . name + " () " ;
2016-07-25 18:31:10 +00:00
}
}
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)
2017-03-08 13:14:01 +00:00
defaultValues [ dependency . name ] = dependency . name + " () " ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : FUNC_POINTER : // func_pointers default to nullptr
2017-03-08 13:14:01 +00:00
defaultValues [ dependency . name ] = " nullptr " ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : REQUIRED : // all required default to "0"
case DependencyData : : Category : : SCALAR : // all scalars default to "0"
2017-03-08 13:14:01 +00:00
defaultValues [ dependency . name ] = " 0 " ;
2016-07-25 18:31:10 +00:00
break ;
default :
assert ( false ) ;
break ;
}
}
}
2017-02-08 12:56:06 +00:00
void determineReducedName ( CommandData & commandData )
2016-07-25 18:31:10 +00:00
{
2017-02-08 12:56:06 +00:00
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 ] ) )
2016-07-25 18:31:10 +00:00
{
2017-02-08 12:56:06 +00:00
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 ] ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-02-13 08:23:35 +00:00
void determineEnhancedReturnType ( CommandData & commandData )
2016-07-25 18:31:10 +00:00
{
std : : string returnType ;
2017-03-08 13:14:01 +00:00
// 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
2017-02-13 08:23:35 +00:00
if ( ( commandData . returnParam ! = ~ 0 )
& & ( ( commandData . returnType = = " void " )
| | ( ( commandData . returnType = = " Result " )
& & ( ( commandData . successCodes . size ( ) = = 1 )
| | ( ( commandData . successCodes . size ( ) = = 2 )
& & ( commandData . successCodes [ 1 ] = = " eIncomplete " )
& & commandData . twoStep ) ) ) ) )
2016-07-25 18:31:10 +00:00
{
2017-02-13 08:23:35 +00:00
if ( commandData . vectorParams . find ( commandData . returnParam ) ! = commandData . vectorParams . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
// the return parameter is a vector-type parameter
2017-02-13 08:23:35 +00:00
if ( commandData . params [ commandData . returnParam ] . pureType = = " void " )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
// for a vector of void, we use a vector of uint8_t, instead
2017-02-13 08:23:35 +00:00
commandData . enhancedReturnType = " std::vector<uint8_t,Allocator> " ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-03-08 13:14:01 +00:00
// for the other parameters, we use a vector of the pure type
2017-02-13 08:23:35 +00:00
commandData . enhancedReturnType = " std::vector< " + commandData . params [ commandData . returnParam ] . pureType + " ,Allocator> " ;
2016-07-25 18:31:10 +00:00
}
}
else
{
2017-03-08 13:14:01 +00:00
// it's a simple parameter -> get the type and just remove the trailing '*' (originally, it's a pointer)
2017-02-13 08:23:35 +00:00
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 ( ) ;
2016-07-25 18:31:10 +00:00
}
}
else if ( ( commandData . returnType = = " Result " ) & & ( commandData . successCodes . size ( ) = = 1 ) )
{
2017-02-08 12:56:06 +00:00
// an original return of type "Result" with just one successCode is changed to void, errors throw an exception
2017-02-13 08:23:35 +00:00
commandData . enhancedReturnType = " void " ;
2016-07-25 18:31:10 +00:00
}
else
{
// the return type just stays the original return type
2017-02-13 08:23:35 +00:00
commandData . enhancedReturnType = commandData . returnType ;
}
}
void determineReturnParam ( CommandData & commandData )
{
2017-03-08 13:14:01 +00:00
// for return types of type Result or void, we can replace determine a parameter to return
2017-02-13 08:23:35 +00:00
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 )
2017-03-08 13:14:01 +00:00
& & 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 ( )
2017-02-13 08:23:35 +00:00
& & ( ( commandData . vectorParams . find ( i ) = = commandData . vectorParams . end ( ) ) | | commandData . twoStep | | ( commandData . successCodes . size ( ) = = 1 ) ) )
{
2017-03-08 13:14:01 +00:00
// 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
2017-02-13 08:23:35 +00:00
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 ) ;
} ) ;
2017-03-08 13:14:01 +00:00
// 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
2017-02-13 08:23:35 +00:00
commandData . returnParam = paramIt ! = commandData . params . end ( ) ? ~ 0 : i ;
}
}
}
}
void determineSkippedParams ( CommandData & commandData )
{
2017-03-08 13:14:01 +00:00
// 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
2017-02-13 08:23:35 +00:00
if ( commandData . returnParam ! = ~ 0 )
{
commandData . skippedParams . insert ( commandData . returnParam ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-02-13 08:23:35 +00:00
void determineTemplateParam ( CommandData & commandData )
2017-01-27 14:15:50 +00:00
{
2017-02-13 08:23:35 +00:00
for ( size_t i = 0 ; i < commandData . params . size ( ) ; i + + )
2017-01-27 14:15:50 +00:00
{
2017-03-08 13:14:01 +00:00
// 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 " ) )
2017-02-13 08:23:35 +00:00
{
2017-03-08 13:14:01 +00:00
# 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
2017-02-13 08:23:35 +00:00
commandData . templateParam = i ;
2017-03-08 13:14:01 +00:00
break ;
2017-02-13 08:23:35 +00:00
}
}
assert ( ( commandData . templateParam = = ~ 0 ) | | ( commandData . vectorParams . find ( commandData . templateParam ) ! = commandData . vectorParams . end ( ) ) ) ;
}
void determineVectorParams ( CommandData & commandData )
{
2017-03-08 13:14:01 +00:00
// look for the parameters whose len equals the name of an other parameter
2017-02-13 08:23:35 +00:00
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 ; } ;
2017-03-08 13:14:01 +00:00
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)
2017-02-13 08:23:35 +00:00
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 " ) ) ;
}
2017-01-27 14:15:50 +00:00
}
}
2017-02-08 12:56:06 +00:00
void enterProtect ( std : : ostream & os , std : : string const & protect )
2016-07-25 18:31:10 +00:00
{
if ( ! protect . empty ( ) )
{
2017-02-08 12:56:06 +00:00
os < < " #ifdef " < < protect < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
}
std : : string extractTag ( std : : string const & name )
{
// the name is supposed to look like: VK_<tag>_<other>
size_t start = name . find ( ' _ ' ) ;
2017-03-08 13:14:01 +00:00
assert ( ( start ! = std : : string : : npos ) & & ( name . substr ( 0 , start ) = = " VK " ) ) ;
2016-07-25 18:31:10 +00:00
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 )
{
2017-03-08 13:14:01 +00:00
// find the tag in a name, return that tag or an empty string
2017-02-08 12:56:06 +00:00
auto tagIt = std : : find_if ( tags . begin ( ) , tags . end ( ) , [ & name ] ( std : : string const & t )
2016-07-25 18:31:10 +00:00
{
2017-02-08 12:56:06 +00:00
size_t pos = name . find ( t ) ;
return ( pos ! = std : : string : : npos ) & & ( pos = = name . length ( ) - t . length ( ) ) ;
} ) ;
return tagIt ! = tags . end ( ) ? * tagIt : " " ;
2016-07-25 18:31:10 +00:00
}
std : : string generateEnumNameForFlags ( std : : string const & name )
{
2017-03-08 13:14:01 +00:00
// create a string, where the substring "Flags" is replaced by "FlagBits"
2016-07-25 18:31:10 +00:00
std : : string generatedName = name ;
size_t pos = generatedName . rfind ( " Flags " ) ;
assert ( pos ! = std : : string : : npos ) ;
generatedName . replace ( pos , 5 , " FlagBits " ) ;
return generatedName ;
}
2017-02-08 12:56:06 +00:00
bool hasPointerParam ( std : : vector < ParamData > const & params )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
// check if any of the parameters is a pointer
2017-02-08 12:56:06 +00:00
auto it = std : : find_if ( params . begin ( ) , params . end ( ) , [ ] ( ParamData const & pd )
2016-07-25 18:31:10 +00:00
{
2017-02-08 12:56:06 +00:00
return ( pd . type . find ( ' * ' ) ! = std : : string : : npos ) ;
} ) ;
return it ! = params . end ( ) ;
2016-07-25 18:31:10 +00:00
}
2017-02-08 12:56:06 +00:00
void leaveProtect ( std : : ostream & os , std : : string const & protect )
2016-07-25 18:31:10 +00:00
{
if ( ! protect . empty ( ) )
{
2017-02-08 12:56:06 +00:00
os < < " #endif /* " < < protect < < " */ " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
}
2017-02-08 12:56:06 +00:00
void linkCommandToHandle ( VkData & vkData , CommandData & commandData )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
// 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
2017-02-08 12:56:06 +00:00
assert ( ! commandData . params . empty ( ) ) ;
std : : map < std : : string , HandleData > : : iterator hit = vkData . handles . find ( commandData . params [ 0 ] . pureType ) ;
2017-02-13 08:23:35 +00:00
if ( hit = = vkData . handles . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-02-13 08:23:35 +00:00
hit = vkData . handles . find ( " " ) ;
}
assert ( hit ! = vkData . handles . end ( ) ) ;
2017-03-08 13:14:01 +00:00
// put the command into the handle's list of commands, and store the handle in the commands className
2017-02-13 08:23:35 +00:00
hit - > second . commands . push_back ( commandData . fullName ) ;
commandData . className = hit - > first ;
2017-02-08 12:56:06 +00:00
2017-03-08 13:14:01 +00:00
// add the dependencies of the command to the dependencies of the handle
2017-02-13 08:23:35 +00:00
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 ( ) )
{
2017-02-08 12:56:06 +00:00
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 ; } ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-03-08 13:14:01 +00:00
std : : string readArraySize ( tinyxml2 : : XMLNode * node , std : : string & name )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
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 = 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 ( ) ;
2017-07-19 07:35:28 +00:00
assert ( node & & node - > ToText ( ) & & ( strcmp ( node - > Value ( ) , " ] " ) = = 0 ) ) ;
2017-03-08 13:14:01 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
// otherwise, the node holds '[' and ']', so get the stuff in between those as the array size
2017-03-08 13:14:01 +00:00
assert ( ( value . front ( ) = = ' [ ' ) & & ( value . back ( ) = = ' ] ' ) ) ;
arraySize = value . substr ( 1 , value . length ( ) - 2 ) ;
}
2017-07-19 07:35:28 +00:00
assert ( ! node - > NextSibling ( ) | | ( ( strcmp ( node - > NextSibling ( ) - > Value ( ) , " comment " ) = = 0 ) & & ! node - > NextSibling ( ) - > NextSibling ( ) ) ) ;
2017-03-08 13:14:01 +00:00
}
}
return arraySize ;
2017-02-08 12:56:06 +00:00
}
bool readCommandParam ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & dependencies , std : : vector < ParamData > & params )
{
ParamData param ;
2016-07-25 18:31:10 +00:00
if ( element - > Attribute ( " len " ) )
{
2017-01-27 14:15:50 +00:00
param . len = element - > Attribute ( " len " ) ;
2016-07-25 18:31:10 +00:00
}
2017-03-08 13:14:01 +00:00
// get the type of the parameter, and put it into the list of dependencies
2017-02-08 12:56:06 +00:00
tinyxml2 : : XMLNode * child = readCommandParamType ( element - > FirstChild ( ) , param ) ;
dependencies . insert ( param . pureType ) ;
2016-07-25 18:31:10 +00:00
assert ( child - > ToElement ( ) & & ( strcmp ( child - > Value ( ) , " name " ) = = 0 ) ) ;
2017-01-27 14:15:50 +00:00
param . name = child - > ToElement ( ) - > GetText ( ) ;
2016-07-25 18:31:10 +00:00
2017-03-08 13:14:01 +00:00
param . arraySize = readArraySize ( child , param . name ) ;
2017-02-08 12:56:06 +00:00
param . optional = element - > Attribute ( " optional " ) & & ( strcmp ( element - > Attribute ( " optional " ) , " true " ) = = 0 ) ;
params . push_back ( param ) ;
2017-03-08 13:14:01 +00:00
// an optional parameter with "false,true" value is supposed to be part of a two-step algorithm: first get the size, than use it
2017-02-08 12:56:06 +00:00
return element - > Attribute ( " optional " ) & & ( strcmp ( element - > Attribute ( " optional " ) , " false,true " ) = = 0 ) ;
}
void readCommandParams ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & dependencies , CommandData & commandData )
{
2017-03-08 13:14:01 +00:00
// iterate over the siblings of the element and read the command parameters
2017-02-08 12:56:06 +00:00
assert ( element ) ;
while ( element = element - > NextSiblingElement ( ) )
{
std : : string value = element - > Value ( ) ;
if ( value = = " param " )
{
commandData . twoStep | = readCommandParam ( element , dependencies , commandData . params ) ;
}
else
{
2017-03-08 13:14:01 +00:00
// ignore these values!
2017-02-08 12:56:06 +00:00
assert ( ( value = = " implicitexternsyncparams " ) | | ( value = = " validity " ) ) ;
}
}
}
2016-07-25 18:31:10 +00:00
2017-02-08 12:56:06 +00:00
tinyxml2 : : XMLNode * readCommandParamType ( tinyxml2 : : XMLNode * node , ParamData & param )
{
assert ( node ) ;
if ( node - > ToText ( ) )
{
2017-03-08 13:14:01 +00:00
// start type with "const" or "struct", if needed
2017-02-08 12:56:06 +00:00
std : : string value = trimEnd ( node - > Value ( ) ) ;
assert ( ( value = = " const " ) | | ( value = = " struct " ) ) ;
param . type = value + " " ;
node = node - > NextSibling ( ) ;
assert ( node ) ;
}
2017-03-08 13:14:01 +00:00
// get the pure type
2017-02-08 12:56:06 +00:00
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 ;
2017-03-08 13:14:01 +00:00
// end with "*", "**", or "* const*", if needed
2017-02-08 12:56:06 +00:00
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 ;
2016-07-25 18:31:10 +00:00
}
2017-02-08 12:56:06 +00:00
CommandData & readCommandProto ( tinyxml2 : : XMLElement * element , VkData & vkData )
2016-07-25 18:31:10 +00:00
{
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 ( ) ) ;
2017-03-08 13:14:01 +00:00
// get return type and name of the command
2016-07-25 18:31:10 +00:00
std : : string type = strip ( typeElement - > GetText ( ) , " Vk " ) ;
2017-04-24 07:30:02 +00:00
std : : string name = startLowerCase ( strip ( nameElement - > GetText ( ) , " vk " ) ) ;
2016-07-25 18:31:10 +00:00
2017-03-08 13:14:01 +00:00
// add an empty DependencyData to this name
2016-07-25 18:31:10 +00:00
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : COMMAND , name ) ) ;
2017-03-08 13:14:01 +00:00
// 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 ;
2016-07-25 18:31:10 +00:00
}
void readCommands ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
assert ( strcmp ( child - > Value ( ) , " command " ) = = 0 ) ;
readCommandsCommand ( child , vkData ) ;
}
2016-07-25 18:31:10 +00:00
}
void readCommandsCommand ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ( strcmp ( child - > Value ( ) , " proto " ) = = 0 ) ) ;
2017-02-08 12:56:06 +00:00
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 ) ;
2017-02-13 08:23:35 +00:00
determineVectorParams ( commandData ) ;
determineReturnParam ( commandData ) ;
determineTemplateParam ( commandData ) ;
determineEnhancedReturnType ( commandData ) ;
determineSkippedParams ( commandData ) ;
2017-02-08 12:56:06 +00:00
}
2016-07-25 18:31:10 +00:00
2017-02-08 12:56:06 +00:00
std : : vector < std : : string > readCommandSuccessCodes ( tinyxml2 : : XMLElement * element , std : : set < std : : string > const & tags )
{
std : : vector < std : : string > results ;
2016-07-25 18:31:10 +00:00
if ( element - > Attribute ( " successcodes " ) )
{
std : : string successCodes = element - > Attribute ( " successcodes " ) ;
2017-03-08 13:14:01 +00:00
// tokenize the successCodes string, using ',' as the separator
2016-07-25 18:31:10 +00:00
size_t start = 0 , end ;
do
{
end = successCodes . find ( ' , ' , start ) ;
std : : string code = successCodes . substr ( start , end - start ) ;
2017-02-08 12:56:06 +00:00
std : : string tag = findTag ( code , tags ) ;
2017-03-08 13:14:01 +00:00
// on each success code: prepend 'e', strip "VK_" and a tag, convert it to camel case, and add the tag again
2017-02-08 12:56:06 +00:00
results . push_back ( std : : string ( " e " ) + toCamelCase ( strip ( code , " VK_ " , tag ) ) + tag ) ;
2016-07-25 18:31:10 +00:00
start = end + 1 ;
} while ( end ! = std : : string : : npos ) ;
}
2017-02-08 12:56:06 +00:00
return results ;
2016-07-25 18:31:10 +00:00
}
void readComment ( tinyxml2 : : XMLElement * element , std : : string & header )
{
assert ( element - > GetText ( ) ) ;
2017-07-19 07:35:28 +00:00
std : : string text = element - > GetText ( ) ;
if ( text . find ( " \n Copyright " ) = = 0 )
{
assert ( header . empty ( ) ) ;
header = text ;
2016-07-25 18:31:10 +00:00
2017-07-19 07:35:28 +00:00
// erase the part after the Copyright text
size_t pos = header . find ( " \n \n ----- " ) ;
assert ( pos ! = std : : string : : npos ) ;
header . erase ( pos ) ;
2016-07-25 18:31:10 +00:00
2017-07-19 07:35:28 +00:00
// 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 // " ) ;
}
2016-07-25 18:31:10 +00:00
2017-07-19 07:35:28 +00:00
// and add a little message on our own
header + = " \n \n // This header is generated from the Khronos Vulkan XML API Registry. " ;
}
2016-07-25 18:31:10 +00:00
}
void readEnums ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
2016-08-29 08:03:04 +00:00
if ( ! element - > Attribute ( " name " ) )
{
throw std : : runtime_error ( std : : string ( " spec error: enums element is missing the name attribute " ) ) ;
}
2017-02-08 12:56:06 +00:00
std : : string name = strip ( element - > Attribute ( " name " ) , " Vk " ) ;
2017-03-08 13:14:01 +00:00
if ( name ! = " API Constants " ) // skip the "API Constants"
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
// add an empty DependencyData on this name into the dependencies list
2016-07-25 18:31:10 +00:00
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : ENUM , name ) ) ;
2017-03-08 13:14:01 +00:00
// ad an empty EnumData on this name into the enums map
2017-02-08 12:56:06 +00:00
std : : map < std : : string , EnumData > : : iterator it = vkData . enums . insert ( std : : make_pair ( name , EnumData ( name ) ) ) . first ;
2016-07-25 18:31:10 +00:00
if ( name = = " Result " )
{
// special handling for VKResult, as its enums just have VK_ in common
it - > second . prefix = " VK_ " ;
}
else
{
2016-08-29 08:03:04 +00:00
if ( ! element - > Attribute ( " type " ) )
{
throw std : : runtime_error ( std : : string ( " spec error: enums name= \" " + name + " \" is missing the type attribute " ) ) ;
}
2016-07-25 18:31:10 +00:00
std : : string type = element - > Attribute ( " type " ) ;
2016-08-29 08:03:04 +00:00
if ( type ! = " bitmask " & & type ! = " enum " )
{
throw std : : runtime_error ( std : : string ( " spec error: enums name= \" " + name + " \" has unknown type " + type ) ) ;
}
2016-07-25 18:31:10 +00:00
it - > second . bitmask = ( type = = " bitmask " ) ;
if ( it - > second . bitmask )
{
2017-03-08 13:14:01 +00:00
// for a bitmask enum, start with "VK", cut off the trailing "FlagBits", and convert that name to upper case
// end that with "Bit"
2016-07-25 18:31:10 +00:00
size_t pos = name . find ( " FlagBits " ) ;
assert ( pos ! = std : : string : : npos ) ;
it - > second . prefix = " VK " + toUpperCase ( name . substr ( 0 , pos ) ) + " _ " ;
}
else
{
2017-03-08 13:14:01 +00:00
// for a non-bitmask enum, start with "VK", and convert the name to upper case
2016-07-25 18:31:10 +00:00
it - > second . prefix = " VK " + toUpperCase ( name ) + " _ " ;
}
2017-04-06 12:36:03 +00:00
// if the enum name contains a tag move it from the prefix to the postfix to generate correct enum value names.
2016-07-25 18:31:10 +00:00
for ( std : : set < std : : string > : : const_iterator tit = vkData . tags . begin ( ) ; tit ! = vkData . tags . end ( ) ; + + tit )
{
2017-04-06 12:36:03 +00:00
if ( ( tit - > length ( ) < it - > second . prefix . length ( ) ) & & ( it - > second . prefix . substr ( it - > second . prefix . length ( ) - tit - > length ( ) - 1 ) = = ( * tit + " _ " ) ) )
2016-07-25 18:31:10 +00:00
{
2017-04-06 12:36:03 +00:00
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 ;
2016-07-25 18:31:10 +00:00
break ;
}
}
}
2017-04-06 12:36:03 +00:00
readEnumsEnum ( element , it - > second ) ;
2016-07-25 18:31:10 +00:00
2017-03-08 13:14:01 +00:00
// add this enum to the set of Vulkan data types
2016-07-25 18:31:10 +00:00
assert ( vkData . vkTypes . find ( name ) = = vkData . vkTypes . end ( ) ) ;
vkData . vkTypes . insert ( name ) ;
}
}
2017-04-06 12:36:03 +00:00
void readEnumsEnum ( tinyxml2 : : XMLElement * element , EnumData & enumData )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
// read the names of the enum values
2016-07-25 18:31:10 +00:00
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
2017-02-08 12:56:06 +00:00
while ( child )
2016-07-25 18:31:10 +00:00
{
if ( child - > Attribute ( " name " ) )
{
2017-04-06 12:36:03 +00:00
enumData . addEnumMember ( child - > Attribute ( " name " ) , " " ) ;
2016-07-25 18:31:10 +00:00
}
2017-02-08 12:56:06 +00:00
child = child - > NextSiblingElement ( ) ;
}
2016-07-25 18:31:10 +00:00
}
2017-02-14 17:28:05 +00:00
void readDisabledExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2017-02-14 17:28:05 +00:00
{
std : : string value = child - > Value ( ) ;
if ( ( value = = " command " ) | | ( value = = " type " ) )
{
2017-03-08 13:14:01 +00:00
// disable a command or a type !
2017-02-14 17:28:05 +00:00
assert ( child - > Attribute ( " name " ) ) ;
2017-04-24 07:30:02 +00:00
std : : string name = ( value = = " command " ) ? startLowerCase ( strip ( child - > Attribute ( " name " ) , " vk " ) ) : strip ( child - > Attribute ( " name " ) , " Vk " ) ;
2017-03-08 13:14:01 +00:00
// search this name in the dependencies list and remove it
2017-02-14 17:28:05 +00:00
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 ) ;
2017-03-08 13:14:01 +00:00
// erase it from all dependency sets
2017-02-14 17:28:05 +00:00
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
{
2017-03-08 13:14:01 +00:00
// a type simply needs to be removed from the structs and vkTypes sets
2017-02-14 17:28:05 +00:00
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 " ) ;
}
2017-03-08 13:14:01 +00:00
}
}
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 " ) ) ;
2017-04-24 07:30:02 +00:00
std : : string name = startLowerCase ( strip ( element - > Attribute ( " name " ) , " vk " ) ) ;
2017-03-08 13:14:01 +00:00
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 )
{
// TODO process enums which don't extend existing enums
if ( element - > Attribute ( " extends " ) )
{
assert ( element - > Attribute ( " name " ) ) ;
assert ( enums . find ( strip ( element - > Attribute ( " extends " ) , " Vk " ) ) ! = enums . end ( ) ) ;
assert ( ! ! element - > Attribute ( " bitpos " ) + ! ! element - > Attribute ( " offset " ) + ! ! element - > Attribute ( " value " ) = = 1 ) ;
auto enumIt = enums . find ( strip ( element - > Attribute ( " extends " ) , " Vk " ) ) ;
assert ( enumIt ! = enums . end ( ) ) ;
2017-04-06 12:36:03 +00:00
enumIt - > second . addEnumMember ( element - > Attribute ( " name " ) , tag ) ;
2017-03-08 13:14:01 +00:00
}
2017-02-14 17:28:05 +00:00
}
2016-07-25 18:31:10 +00:00
void readExtensionRequire ( tinyxml2 : : XMLElement * element , VkData & vkData , std : : string const & protect , std : : string const & tag )
{
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
std : : string value = child - > Value ( ) ;
if ( value = = " command " )
{
2017-03-08 13:14:01 +00:00
readExtensionCommand ( child , vkData . commands , protect ) ;
2016-07-25 18:31:10 +00:00
}
else if ( value = = " type " )
{
2017-03-08 13:14:01 +00:00
readExtensionType ( child , vkData , protect ) ;
2016-07-25 18:31:10 +00:00
}
else if ( value = = " enum " )
{
2017-03-08 13:14:01 +00:00
readExtensionEnum ( child , vkData . enums , tag ) ;
2016-07-25 18:31:10 +00:00
}
else
{
assert ( value = = " usage " ) ;
}
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
}
void readExtensions ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
assert ( strcmp ( child - > Value ( ) , " extension " ) = = 0 ) ;
readExtensionsExtension ( child , vkData ) ;
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
}
void readExtensionsExtension ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
assert ( element - > Attribute ( " name " ) ) ;
std : : string tag = extractTag ( element - > Attribute ( " name " ) ) ;
2017-04-06 12:36:03 +00:00
assert ( vkData . tags . find ( tag ) ! = vkData . tags . end ( ) ) ;
2016-07-25 18:31:10 +00:00
2017-02-14 17:28:05 +00:00
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ( strcmp ( child - > Value ( ) , " require " ) = = 0 ) & & ! child - > NextSiblingElement ( ) ) ;
2016-07-25 18:31:10 +00:00
if ( strcmp ( element - > Attribute ( " supported " ) , " disabled " ) = = 0 )
{
2017-02-14 17:28:05 +00:00
// kick out all the disabled stuff we've read before !!
readDisabledExtensionRequire ( child , vkData ) ;
2016-07-25 18:31:10 +00:00
}
2017-02-14 17:28:05 +00:00
else
2016-07-25 18:31:10 +00:00
{
2017-02-14 17:28:05 +00:00
std : : string protect ;
if ( element - > Attribute ( " protect " ) )
{
protect = element - > Attribute ( " protect " ) ;
}
2016-07-25 18:31:10 +00:00
2017-02-14 17:28:05 +00:00
readExtensionRequire ( child , vkData , protect , tag ) ;
}
2016-07-25 18:31:10 +00:00
}
2017-03-08 13:14:01 +00:00
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 . members . 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 ) ;
assert ( stit ! = vkData . structs . end ( ) & & stit - > second . protect . empty ( ) ) ;
stit - > second . protect = protect ;
}
}
}
}
}
}
tinyxml2 : : XMLNode * readType ( tinyxml2 : : XMLNode * element , std : : string & type , std : : string & pureType )
{
2017-05-11 16:21:14 +00:00
assert ( element ) ;
if ( element - > ToText ( ) )
{
std : : string value = trimEnd ( 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 ;
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
void readTypeBasetype ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies )
{
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ( 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 & & ( strcmp ( nameElement - > Value ( ) , " name " ) = = 0 ) & & nameElement - > GetText ( ) ) ;
std : : string name = strip ( nameElement - > GetText ( ) , " Vk " ) ;
// 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 )
{
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ( strcmp ( typeElement - > Value ( ) , " type " ) = = 0 ) & & typeElement - > GetText ( ) & & ( strcmp ( typeElement - > GetText ( ) , " VkFlags " ) = = 0 ) ) ;
std : : string type = typeElement - > GetText ( ) ;
tinyxml2 : : XMLElement * nameElement = typeElement - > NextSiblingElement ( ) ;
assert ( nameElement & & ( strcmp ( nameElement - > Value ( ) , " name " ) = = 0 ) & & nameElement - > GetText ( ) ) ;
std : : string name = strip ( nameElement - > GetText ( ) , " Vk " ) ;
assert ( ! nameElement - > NextSiblingElement ( ) ) ;
std : : string requires ;
if ( element - > Attribute ( " requires " ) )
{
requires = strip ( element - > Attribute ( " requires " ) , " Vk " ) ;
}
2017-03-08 13:14:01 +00:00
else
{
// Generate FlagBits name, add a DependencyData for that name, and add it to the list of enums and vulkan types
2016-07-25 18:31:10 +00:00
requires = generateEnumNameForFlags ( name ) ;
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : ENUM , requires ) ) ;
2017-02-08 12:56:06 +00:00
vkData . enums . insert ( std : : make_pair ( requires , EnumData ( requires , true ) ) ) ;
2016-07-25 18:31:10 +00:00
vkData . vkTypes . insert ( requires ) ;
}
2017-03-08 13:14:01 +00:00
// add a DependencyData for the bitmask name, with the required type as its first dependency
2016-07-25 18:31:10 +00:00
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : FLAGS , name ) ) ;
vkData . dependencies . back ( ) . dependencies . insert ( requires ) ;
2017-03-08 13:14:01 +00:00
2016-07-25 18:31:10 +00:00
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 )
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
if ( child & & ( strcmp ( child - > GetText ( ) , " VK_HEADER_VERSION " ) = = 0 ) )
{
vkData . version = element - > LastChild ( ) - > ToText ( ) - > Value ( ) ;
}
else if ( element - > Attribute ( " name " ) & & strcmp ( element - > Attribute ( " name " ) , " VK_DEFINE_NON_DISPATCHABLE_HANDLE " ) = = 0 )
{
2017-03-08 13:14:01 +00:00
// filter out the check for the different types of VK_DEFINE_NON_DISPATCHABLE_HANDLE
2016-07-25 18:31:10 +00:00
std : : string text = element - > LastChild ( ) - > ToText ( ) - > Value ( ) ;
2016-09-05 08:26:43 +00:00
size_t start = text . find ( " #if defined(__LP64__) " ) ;
2016-07-25 18:31:10 +00:00
size_t end = text . find_first_of ( " \r \n " , start + 1 ) ;
vkData . typesafeCheck = text . substr ( start , end - start ) ;
}
2017-03-08 13:14:01 +00:00
// ignore all the other defines
2016-07-25 18:31:10 +00:00
}
void readTypeFuncpointer ( tinyxml2 : : XMLElement * element , std : : list < DependencyData > & dependencies )
{
tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ;
assert ( child & & ( strcmp ( child - > Value ( ) , " name " ) = = 0 ) & & child - > GetText ( ) ) ;
2017-03-08 13:14:01 +00:00
2016-07-25 18:31:10 +00:00
dependencies . push_back ( DependencyData ( DependencyData : : Category : : FUNC_POINTER , child - > GetText ( ) ) ) ;
}
void readTypeHandle ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
tinyxml2 : : XMLElement * typeElement = element - > FirstChildElement ( ) ;
assert ( typeElement & & ( strcmp ( typeElement - > Value ( ) , " type " ) = = 0 ) & & typeElement - > GetText ( ) ) ;
# if !defined(NDEBUG)
std : : string type = typeElement - > GetText ( ) ;
2017-03-08 13:14:01 +00:00
assert ( ( type . find ( " VK_DEFINE_HANDLE " ) = = 0 ) | | ( type . find ( " VK_DEFINE_NON_DISPATCHABLE_HANDLE " ) = = 0 ) ) ;
2016-07-25 18:31:10 +00:00
# endif
tinyxml2 : : XMLElement * nameElement = typeElement - > NextSiblingElement ( ) ;
assert ( nameElement & & ( 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 ( ) ) ;
2017-03-08 13:14:01 +00:00
vkData . handles [ name ] ;
2016-07-25 18:31:10 +00:00
}
2017-03-08 13:14:01 +00:00
void readTypeStruct ( tinyxml2 : : XMLElement * element , VkData & vkData , bool isUnion )
2016-07-25 18:31:10 +00:00
{
assert ( ! element - > Attribute ( " returnedonly " ) | | ( strcmp ( element - > Attribute ( " returnedonly " ) , " true " ) = = 0 ) ) ;
assert ( element - > Attribute ( " name " ) ) ;
std : : string name = strip ( element - > Attribute ( " name " ) , " Vk " ) ;
if ( name = = " Rect3D " )
{
2017-03-08 13:14:01 +00:00
// for whatever reason, VkRect3D is listed in vk.xml, but does not appear in vulkan.h!!
2016-07-25 18:31:10 +00:00
return ;
}
2017-03-08 13:14:01 +00:00
vkData . dependencies . push_back ( DependencyData ( isUnion ? DependencyData : : Category : : UNION : DependencyData : : Category : : STRUCT , name ) ) ;
2016-07-25 18:31:10 +00:00
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 " ) ;
2017-03-08 13:14:01 +00:00
it - > second . isUnion = isUnion ;
2016-07-25 18:31:10 +00:00
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
assert ( child - > Value ( ) ) ;
std : : string value = child - > Value ( ) ;
2017-07-19 07:35:28 +00:00
assert ( ( value = = " comment " ) | | ( value = = " member " ) ) ;
if ( value = = " member " )
{
readTypeStructMember ( child , it - > second . members , vkData . dependencies . back ( ) . dependencies ) ;
}
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
assert ( vkData . vkTypes . find ( name ) = = vkData . vkTypes . end ( ) ) ;
vkData . vkTypes . insert ( name ) ;
}
2017-03-08 13:14:01 +00:00
void readTypeStructMember ( tinyxml2 : : XMLElement * element , std : : vector < MemberData > & members , std : : set < std : : string > & dependencies )
2016-07-25 18:31:10 +00:00
{
2017-03-08 13:14:01 +00:00
members . push_back ( MemberData ( ) ) ;
2016-07-25 18:31:10 +00:00
MemberData & member = members . back ( ) ;
2017-03-08 13:14:01 +00:00
tinyxml2 : : XMLNode * child = readType ( element - > FirstChild ( ) , member . type , member . pureType ) ;
dependencies . insert ( member . pureType ) ;
2016-07-25 18:31:10 +00:00
2017-03-08 13:14:01 +00:00
assert ( ( child - > ToElement ( ) & & strcmp ( child - > Value ( ) , " name " ) = = 0 ) ) ;
2016-07-25 18:31:10 +00:00
member . name = child - > ToElement ( ) - > GetText ( ) ;
2017-03-08 13:14:01 +00:00
member . arraySize = readArraySize ( child , member . name ) ;
2016-07-25 18:31:10 +00:00
}
void readTags ( tinyxml2 : : XMLElement * element , std : : set < std : : string > & tags )
{
tags . insert ( " EXT " ) ;
tags . insert ( " KHR " ) ;
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
assert ( child - > Attribute ( " name " ) ) ;
tags . insert ( child - > Attribute ( " name " ) ) ;
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
}
void readTypes ( tinyxml2 : : XMLElement * element , VkData & vkData )
{
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = element - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
2017-07-19 07:35:28 +00:00
assert ( child - > Value ( ) ) ;
std : : string value = child - > Value ( ) ;
assert ( ( value = = " comment " ) | | ( value = = " type " ) ) ;
if ( value = = " type " )
2016-07-25 18:31:10 +00:00
{
2017-07-19 07:35:28 +00:00
if ( child - > Attribute ( " category " ) )
2016-07-25 18:31:10 +00:00
{
2017-07-19 07:35:28 +00:00
std : : string category = child - > Attribute ( " category " ) ;
if ( category = = " basetype " )
{
readTypeBasetype ( child , vkData . dependencies ) ;
}
else if ( category = = " bitmask " )
{
readTypeBitmask ( child , vkData ) ;
}
else if ( category = = " define " )
{
readTypeDefine ( child , vkData ) ;
}
else if ( category = = " funcpointer " )
{
readTypeFuncpointer ( child , vkData . dependencies ) ;
}
else if ( category = = " handle " )
{
readTypeHandle ( child , vkData ) ;
}
else if ( category = = " struct " )
{
readTypeStruct ( child , vkData , false ) ;
}
else if ( category = = " union " )
{
readTypeStruct ( child , vkData , true ) ;
}
else
{
assert ( ( category = = " enum " ) | | ( category = = " include " ) ) ;
}
2016-07-25 18:31:10 +00:00
}
else
{
2017-07-19 07:35:28 +00:00
assert ( child - > Attribute ( " name " ) ) ;
vkData . dependencies . push_back ( DependencyData ( DependencyData : : Category : : REQUIRED , child - > Attribute ( " name " ) ) ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
}
2017-01-27 14:15:50 +00:00
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 ;
}
2017-02-08 12:56:06 +00:00
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 . deleterData . find ( commandData . params [ valueIndex ] . pureType ) = = vkData . deleterData . end ( ) ) ;
vkData . deleterData [ commandData . params [ valueIndex ] . pureType ] . pool = commandData . params [ 1 ] . pureType ;
break ;
default :
assert ( false ) ;
}
2017-02-13 08:23:35 +00:00
if ( commandData . fullName = = " destroyDevice " )
{
key = " PhysicalDevice " ;
}
2017-02-08 12:56:06 +00:00
assert ( vkData . deleterTypes [ key ] . find ( commandData . params [ valueIndex ] . pureType ) = = vkData . deleterTypes [ key ] . end ( ) ) ;
vkData . deleterTypes [ key ] . insert ( commandData . params [ valueIndex ] . pureType ) ;
vkData . deleterData [ commandData . params [ valueIndex ] . pureType ] . call = commandData . reducedName ;
}
}
2016-07-25 18:31:10 +00:00
void sortDependencies ( std : : list < DependencyData > & dependencies )
{
std : : set < std : : string > listedTypes = { " VkFlags " } ;
std : : list < DependencyData > sortedDependencies ;
while ( ! dependencies . empty ( ) )
{
2016-12-01 21:00:03 +00:00
bool found = false ;
2016-07-25 18:31:10 +00:00
for ( std : : list < DependencyData > : : iterator it = dependencies . begin ( ) ; it ! = dependencies . end ( ) ; + + it )
{
2017-03-08 13:14:01 +00:00
if ( std : : find_if ( it - > dependencies . begin ( ) , it - > dependencies . end ( ) , [ & listedTypes ] ( std : : string const & d ) { return listedTypes . find ( d ) = = listedTypes . end ( ) ; } ) = = it - > dependencies . end ( ) )
2016-07-25 18:31:10 +00:00
{
sortedDependencies . push_back ( * it ) ;
listedTypes . insert ( it - > name ) ;
dependencies . erase ( it ) ;
2016-12-01 21:00:03 +00:00
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 ;
}
}
2016-07-25 18:31:10 +00:00
# if !defined(NDEBUG)
2016-12-01 21:00:03 +00:00
else
{
assert ( std : : find_if ( sortedDependencies . begin ( ) , sortedDependencies . end ( ) , [ & dit ] ( DependencyData const & dd ) { return ( dd . name = = * dit ) ; } ) ! = sortedDependencies . end ( ) ) ;
}
2016-07-25 18:31:10 +00:00
# endif
2016-12-01 21:00:03 +00:00
}
2016-07-25 18:31:10 +00:00
}
}
2016-12-01 21:00:03 +00:00
assert ( found ) ;
2016-07-25 18:31:10 +00:00
}
dependencies . swap ( sortedDependencies ) ;
}
2017-04-24 07:30:02 +00:00
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 ) ;
}
2016-07-25 18:31:10 +00:00
std : : string strip ( std : : string const & value , std : : string const & prefix , std : : string const & postfix )
{
std : : string strippedValue = value ;
2017-03-08 13:14:01 +00:00
if ( strippedValue . substr ( 0 , prefix . length ( ) ) = = prefix )
2016-07-25 18:31:10 +00:00
{
strippedValue . erase ( 0 , prefix . length ( ) ) ;
}
2017-04-06 12:36:03 +00:00
if ( ! postfix . empty ( ) & & ( strippedValue . substr ( strippedValue . length ( ) - postfix . length ( ) ) = = postfix ) )
2016-07-25 18:31:10 +00:00
{
2017-04-06 12:36:03 +00:00
strippedValue . erase ( strippedValue . length ( ) - postfix . length ( ) ) ;
2016-07-25 18:31:10 +00:00
}
return strippedValue ;
}
2017-04-24 07:30:02 +00:00
std : : string stripPluralS ( std : : string const & name )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
std : : string strippedName ( name ) ;
size_t pos = strippedName . rfind ( ' s ' ) ;
assert ( pos ! = std : : string : : npos ) ;
strippedName . erase ( pos , 1 ) ;
return strippedName ;
2016-07-25 18:31:10 +00:00
}
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 : : string toUpperCase ( std : : string const & name )
{
assert ( isupper ( name . front ( ) ) ) ;
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 ;
}
2017-01-27 14:15:50 +00:00
// trim from end
std : : string trimEnd ( std : : string const & input )
{
std : : string result = input ;
2017-03-08 13:14:01 +00:00
result . erase ( std : : find_if ( result . rbegin ( ) , result . rend ( ) , [ ] ( char c ) { return ! std : : isspace ( c ) ; } ) . base ( ) , result . end ( ) ) ;
2017-01-27 14:15:50 +00:00
return result ;
}
2017-05-11 16:21:14 +00:00
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 ( ) ;
}
2017-02-13 08:23:35 +00:00
void writeCall ( std : : ostream & os , CommandData const & commandData , std : : set < std : : string > const & vkTypes , bool firstCall , bool singular )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// get the parameter indices of the counter for vector parameters
2016-07-25 18:31:10 +00:00
std : : map < size_t , size_t > countIndices ;
2017-02-13 08:23:35 +00:00
for ( std : : map < size_t , size_t > : : const_iterator it = commandData . vectorParams . begin ( ) ; it ! = commandData . vectorParams . end ( ) ; + + it )
2016-07-25 18:31:10 +00:00
{
countIndices . insert ( std : : make_pair ( it - > second , it - > first ) ) ;
}
2017-04-24 07:30:02 +00:00
// the original function call
os < < " vk " < < startUpperCase ( commandData . fullName ) < < " ( " ;
2017-02-13 08:23:35 +00:00
if ( ! commandData . className . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// if it's member of a class -> add the first parameter with "m_" as prefix
2017-02-08 12:56:06 +00:00
os < < " m_ " < < commandData . params [ 0 ] . name ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
2016-07-25 18:31:10 +00:00
{
if ( 0 < i )
{
2017-02-08 12:56:06 +00:00
os < < " , " ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
2016-07-25 18:31:10 +00:00
std : : map < size_t , size_t > : : const_iterator it = countIndices . find ( i ) ;
if ( it ! = countIndices . end ( ) )
{
2017-04-24 07:30:02 +00:00
writeCallCountParameter ( os , commandData , singular , it ) ;
}
else if ( ( it = commandData . vectorParams . find ( i ) ) ! = commandData . vectorParams . end ( ) )
{
writeCallVectorParameter ( os , commandData , vkTypes , firstCall , singular , it ) ;
}
2017-04-26 07:30:24 +00:00
else
2017-04-24 07:30:02 +00:00
{
if ( vkTypes . find ( commandData . params [ i ] . pureType ) ! = vkTypes . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeCallVulkanTypeParameter ( os , commandData . params [ i ] ) ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
writeCallPlainTypeParameter ( os , commandData . params [ i ] ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-04-24 07:30:02 +00:00
}
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 " ;
}
2016-07-25 18:31:10 +00:00
else
{
2017-04-24 07:30:02 +00:00
// 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 " )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// it's a const pointer to char -> it's a string -> get the data via c_str()
os < < parameterName ;
if ( paramData . optional )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// it's optional -> might use nullptr
os < < " ? " < < parameterName < < " ->c_str() : nullptr " ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
os < < " .c_str() " ;
2016-07-25 18:31:10 +00:00
}
}
else
{
2017-04-24 07:30:02 +00:00
// it's const pointer to void (only other type that occurs) -> just use the name
assert ( ( paramData . pureType = = " void " ) & & ! paramData . optional ) ;
os < < paramData . name ;
2016-07-25 18:31:10 +00:00
}
}
2017-04-24 07:30:02 +00:00
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 ;
2016-07-25 18:31:10 +00:00
}
}
2017-04-24 07:30:02 +00:00
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 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// this parameter is a vector parameter
assert ( commandData . params [ it - > first ] . type . back ( ) = = ' * ' ) ;
if ( ( commandData . returnParam = = it - > first ) & & commandData . twoStep & & firstCall )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// this parameter is the return parameter, and it's the first call of a two-step algorithm -> just just nullptr
os < < " nullptr " ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
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 " )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// 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() " ;
2016-07-25 18:31:10 +00:00
}
}
}
2017-04-24 07:30:02 +00:00
void writeCallVulkanTypeParameter ( std : : ostream & os , ParamData const & paramData )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// this parameter is a vulkan type
if ( paramData . type . back ( ) = = ' * ' )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 < < " ) " ;
2017-02-13 08:23:35 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// other parameters can just use the pointer
os < < " & " < < parameterName ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
os < < " ) " ;
2017-02-13 08:23:35 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// a non-pointer parameter needs a static_cast from vk::-type to vulkan type
os < < " static_cast<Vk " < < paramData . pureType < < " >( " < < paramData . name < < " ) " ;
2017-02-13 08:23:35 +00:00
}
}
2017-04-24 07:30:02 +00:00
void writeFunction ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition , bool enhanced , bool singular , bool unique )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
if ( enhanced & & ! singular )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeFunctionHeaderTemplate ( os , indentation , commandData , ! definition ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
os < < indentation < < ( definition ? " VULKAN_HPP_INLINE " : " " ) ;
writeFunctionHeaderReturnType ( os , indentation , commandData , enhanced , singular , unique ) ;
if ( definition & & ! commandData . className . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
os < < commandData . className < < " :: " ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
writeFunctionHeaderName ( os , commandData . reducedName , singular , unique ) ;
writeFunctionHeaderArguments ( os , vkData , commandData , enhanced , singular , ! definition ) ;
os < < ( definition ? " " : " ; " ) < < std : : endl ;
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
if ( definition )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// write the function body
os < < indentation < < " { " < < std : : endl ;
if ( enhanced )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
if ( unique )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeFunctionBodyUnique ( os , indentation , vkData , commandData , singular ) ;
}
else
{
writeFunctionBodyEnhanced ( os , indentation , vkData , commandData , singular ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-04-24 07:30:02 +00:00
else
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeFunctionBodyStandard ( os , indentation , vkData , commandData ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
os < < indentation < < " } " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
}
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
void writeFunctionBodyEnhanced ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular )
{
if ( 1 < commandData . vectorParams . size ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeFunctionBodyEnhancedMultiVectorSizeCheck ( os , indentation , commandData ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
std : : string returnName ;
if ( commandData . returnParam ! = ~ 0 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
returnName = writeFunctionBodyEnhancedLocalReturnVariable ( os , indentation , commandData , singular ) ;
2016-07-25 18:31:10 +00:00
}
if ( commandData . twoStep )
{
2017-04-24 07:30:02 +00:00
assert ( ! singular ) ;
writeFunctionBodyEnhancedLocalCountVariable ( os , indentation , commandData ) ;
// we now might have to check the result, resize the returned vector accordingly, and call the function again
2017-02-13 08:23:35 +00:00
std : : map < size_t , size_t > : : const_iterator returnit = commandData . vectorParams . find ( commandData . returnParam ) ;
2017-04-24 07:30:02 +00:00
assert ( returnit ! = commandData . vectorParams . end ( ) & & ( returnit - > second ! = ~ 0 ) ) ;
std : : string sizeName = startLowerCase ( strip ( commandData . params [ returnit - > second ] . name , " p " ) ) ;
2016-07-25 18:31:10 +00:00
if ( commandData . returnType = = " Result " )
{
2017-04-24 07:30:02 +00:00
if ( 1 < commandData . successCodes . size ( ) )
{
writeFunctionBodyEnhancedCallTwoStepIterate ( os , indentation , vkData . vkTypes , returnName , sizeName , commandData ) ;
}
else
{
writeFunctionBodyEnhancedCallTwoStepChecked ( os , indentation , vkData . vkTypes , returnName , sizeName , commandData ) ;
}
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
writeFunctionBodyEnhancedCallTwoStep ( os , indentation , vkData . vkTypes , returnName , sizeName , commandData ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
}
else
{
2016-07-25 18:31:10 +00:00
if ( commandData . returnType = = " Result " )
{
2017-04-24 07:30:02 +00:00
writeFunctionBodyEnhancedCallResult ( os , indentation , vkData . vkTypes , commandData , singular ) ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
writeFunctionBodyEnhancedCall ( os , indentation , vkData . vkTypes , commandData , singular ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
}
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 ;
}
}
2017-05-11 16:21:14 +00:00
void writeFunctionBodyEnhanced ( std : : ostream & os , std : : string const & templateString , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular )
2017-04-24 07:30:02 +00:00
{
2017-05-11 16:21:14 +00:00
os < < replaceWithMap ( templateString , {
{ " call " , generateCall ( commandData , vkTypes , true , singular ) } ,
{ " i " , indentation }
} ) ;
2017-04-24 07:30:02 +00:00
2017-05-11 16:21:14 +00:00
}
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 ) ;
2017-04-24 07:30:02 +00:00
}
void writeFunctionBodyEnhancedCallResult ( std : : ostream & os , std : : string const & indentation , std : : set < std : : string > const & vkTypes , CommandData const & commandData , bool singular )
{
2017-05-11 16:21:14 +00:00
std : : string const templateString = " ${i} Result result = static_cast<Result>( ${call} ); \n " ;
writeFunctionBodyEnhanced ( os , templateString , indentation , vkTypes , commandData , singular ) ;
2017-04-24 07:30:02 +00:00
}
2017-05-11 16:21:14 +00:00
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 )
2017-04-24 07:30:02 +00:00
{
2017-05-11 16:21:14 +00:00
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 }
} ;
2017-04-24 07:30:02 +00:00
2017-05-11 16:21:14 +00:00
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 ) ;
2017-04-24 07:30:02 +00:00
}
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 )
{
2017-05-11 16:21:14 +00:00
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 ) ;
2017-04-24 07:30:02 +00:00
}
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 )
{
2017-05-11 16:21:14 +00:00
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 ) ;
2017-04-24 07:30:02 +00:00
}
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 )
{
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 enanced by us
os < < indentation < < " " ;
if ( singular )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// in singular case, just use the return parameters pure type for the return variable
returnName = stripPluralS ( returnName ) ;
os < < commandData . params [ commandData . returnParam ] . pureType < < " " < < returnName ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
else
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// in non-singular case, use the enhanced type for the return variable (like vector<...>)
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 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 < < " ) " ;
2016-07-25 18:31:10 +00:00
}
}
2017-04-24 07:30:02 +00:00
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 ;
2016-07-25 18:31:10 +00:00
}
2017-02-13 08:23:35 +00:00
2017-04-24 07:30:02 +00:00
return returnName ;
}
void writeFunctionBodyEnhancedMultiVectorSizeCheck ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData )
{
2017-05-11 16:21:14 +00:00
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 ( " vk::${className}::${reducedName}: ${firstVectorName}.size() ! = $ { secondVectorName } . size ( ) " );
$ { i } }
# endif // VULKAN_HPP_NO_EXCEPTIONS
) # " ;
2017-04-24 07:30:02 +00:00
// 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 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
if ( it0 - > first ! = commandData . returnParam )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
for ( std : : map < size_t , size_t > : : const_iterator it1 = std : : next ( it0 ) ; it1 ! = commandData . vectorParams . end ( ) ; + + it1 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
if ( ( it1 - > first ! = commandData . returnParam ) & & ( it0 - > second = = it1 - > second ) )
{
2017-05-11 16:21:14 +00:00
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 }
} ) ) ;
2017-04-24 07:30:02 +00:00
}
2016-07-25 18:31:10 +00:00
}
}
}
2017-04-24 07:30:02 +00:00
}
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 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// if there's a return parameter, list it in the Result/Value constructor
os < < returnName < < " , " ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
// now the function name (with full namespace) as a string
os < < " \" vk:: " < < ( 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 ;
2017-02-13 08:23:35 +00:00
}
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
void writeFunctionBodyStandard ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData )
2017-02-13 08:23:35 +00:00
{
os < < indentation < < " " ;
bool castReturn = false ;
if ( commandData . returnType ! = " void " )
{
2017-04-24 07:30:02 +00:00
// there's something to return...
2017-02-13 08:23:35 +00:00
os < < " return " ;
2017-04-24 07:30:02 +00:00
2017-02-13 08:23:35 +00:00
castReturn = ( vkData . vkTypes . find ( commandData . returnType ) ! = vkData . vkTypes . end ( ) ) ;
if ( castReturn )
{
2017-04-24 07:30:02 +00:00
// the return-type is a vulkan type -> need to cast to vk::-type
2017-02-13 08:23:35 +00:00
os < < " static_cast< " < < commandData . returnType < < " >( " ;
}
}
2017-04-24 07:30:02 +00:00
// call the original function
os < < " vk " < < startUpperCase ( commandData . fullName ) < < " ( " ;
2017-02-13 08:23:35 +00:00
if ( ! commandData . className . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// the command is part of a class -> the first argument is the member variable, starting with "m_"
2017-02-13 08:23:35 +00:00
os < < " m_ " < < commandData . params [ 0 ] . name ;
}
2017-04-24 07:30:02 +00:00
// list all the arguments
2017-02-13 08:23:35 +00:00
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
{
if ( 0 < i )
{
os < < " , " ;
}
2017-04-24 07:30:02 +00:00
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 ;
}
2017-02-13 08:23:35 +00:00
}
os < < " ) " ;
2017-04-24 07:30:02 +00:00
2017-02-13 08:23:35 +00:00
if ( castReturn )
{
2017-04-24 07:30:02 +00:00
// if we cast the return -> close the static_cast
2017-02-13 08:23:35 +00:00
os < < " ) " ;
}
os < < " ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
void writeFunctionBodyUnique ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool singular )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// the unique version needs a Deleter object for destruction of the newly created stuff
2017-02-13 08:23:35 +00:00
std : : string type = commandData . params [ commandData . returnParam ] . pureType ;
2017-04-24 07:30:02 +00:00
std : : string typeValue = startLowerCase ( type ) ;
2017-02-13 08:23:35 +00:00
os < < indentation < < " " < < type < < " Deleter deleter( " ;
if ( vkData . deleterData . find ( commandData . className ) ! = vkData . deleterData . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// if the Deleter is specific to the command's class, add '*this' to the deleter
2017-02-13 08:23:35 +00:00
os < < " *this, " ;
2017-01-27 14:15:50 +00:00
}
2017-04-24 07:30:02 +00:00
// get the DeleterData corresponding to the returned type
2017-02-13 08:23:35 +00:00
std : : map < std : : string , DeleterData > : : const_iterator ddit = vkData . deleterData . find ( type ) ;
assert ( ddit ! = vkData . deleterData . end ( ) ) ;
2017-01-27 14:15:50 +00:00
if ( ddit - > second . pool . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// if this type isn't pooled, use the allocator (provided as a function argument)
2017-02-08 12:56:06 +00:00
os < < " allocator " ;
2017-01-27 14:15:50 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// 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 ) ;
2017-01-27 14:15:50 +00:00
}
2017-02-08 12:56:06 +00:00
os < < " ); " < < std : : endl ;
2017-04-24 07:30:02 +00:00
2017-02-13 08:23:35 +00:00
bool returnsVector = ! singular & & ( commandData . vectorParams . find ( commandData . returnParam ) ! = commandData . vectorParams . end ( ) ) ;
2017-01-27 14:15:50 +00:00
if ( returnsVector )
{
2017-04-24 07:30:02 +00:00
// if a vector of data is returned, use a local variable to hold the returned data from the non-unique function call
2017-02-08 12:56:06 +00:00
os < < indentation < < " std::vector< " < < type < < " ,Allocator> " < < typeValue < < " s = " ;
2017-01-27 14:15:50 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// otherwise create a Unique stuff out of the returned data from the non-unique function call
2017-02-08 12:56:06 +00:00
os < < indentation < < " return Unique " < < type < < " ( " ;
2017-01-27 14:15:50 +00:00
}
2017-04-24 07:30:02 +00:00
// the call to the non-unique function
os < < ( singular ? stripPluralS ( commandData . fullName ) : commandData . fullName ) < < " ( " ;
2017-01-27 14:15:50 +00:00
bool argEncountered = false ;
2017-02-13 08:23:35 +00:00
for ( size_t i = commandData . className . empty ( ) ? 0 : 1 ; i < commandData . params . size ( ) ; i + + )
2017-01-27 14:15:50 +00:00
{
2017-02-13 08:23:35 +00:00
if ( commandData . skippedParams . find ( i ) = = commandData . skippedParams . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-01-27 14:15:50 +00:00
if ( argEncountered )
{
2017-02-08 12:56:06 +00:00
os < < " , " ;
2017-01-27 14:15:50 +00:00
}
argEncountered = true ;
2017-04-24 07:30:02 +00:00
// 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 ;
2016-07-25 18:31:10 +00:00
}
}
2017-02-08 12:56:06 +00:00
os < < " ) " ;
2017-01-27 14:15:50 +00:00
if ( returnsVector )
2016-07-25 18:31:10 +00:00
{
2017-05-11 16:21:14 +00:00
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 }
} ) ;
2016-07-25 18:31:10 +00:00
}
2017-01-27 14:15:50 +00:00
else
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// for non-vector returns, just add the deleter (local variable) to the Unique-stuff constructor
2017-02-08 12:56:06 +00:00
os < < " , deleter ); " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-01-27 14:15:50 +00:00
}
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
void writeFunctionHeaderArguments ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool enhanced , bool singular , bool withDefaults )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " ( " ;
2017-02-13 08:23:35 +00:00
if ( enhanced )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeFunctionHeaderArgumentsEnhanced ( os , vkData , commandData , singular , withDefaults ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
else
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
writeFunctionHeaderArgumentsStandard ( os , commandData ) ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
os < < " ) " ;
2017-02-13 08:23:35 +00:00
if ( ! commandData . className . empty ( ) )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " const " ;
2017-01-27 14:15:50 +00:00
}
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
void writeFunctionHeaderArgumentsEnhanced ( std : : ostream & os , VkData const & vkData , CommandData const & commandData , bool singular , bool withDefaults )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 - - )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
if ( commandData . skippedParams . find ( i ) = = commandData . skippedParams . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
lastArgument = i ;
break ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
}
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
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 ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
if ( argEncountered )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " , " ;
}
std : : string strippedParameterName = startLowerCase ( strip ( commandData . params [ i ] . name , " p " ) ) ;
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
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 )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 < < " ] " ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
if ( withDefaults & & ( lastArgument = = i ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 ( ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 . members . empty ( ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// there are no bits in this flag -> provide the default
os < < " = " < < commandData . params [ i ] . pureType < < " () " ;
2017-02-13 08:23:35 +00:00
}
}
2016-07-25 18:31:10 +00:00
}
}
else
{
2017-04-24 07:30:02 +00:00
// the argument is not a vector, but a pointer
assert ( commandData . params [ i ] . type [ rightStarPos ] = = ' * ' ) ;
if ( commandData . params [ i ] . optional )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// 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 )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " = nullptr " ;
2017-02-13 08:23:35 +00:00
}
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
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 ;
}
2016-07-25 18:31:10 +00:00
else
{
2017-04-24 07:30:02 +00:00
// 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 )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " = nullptr " ;
2017-02-13 08:23:35 +00:00
}
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
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 ;
}
2016-07-25 18:31:10 +00:00
}
}
2017-04-24 07:30:02 +00:00
argEncountered = true ;
2016-07-25 18:31:10 +00:00
}
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
os < < " " ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
}
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 + + )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
if ( argEncountered )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " , " ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
os < < " " < < commandData . params [ i ] . type < < " " < < commandData . params [ i ] . name ;
if ( ! commandData . params [ i ] . arraySize . empty ( ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " [ " < < commandData . params [ i ] . arraySize < < " ] " ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
argEncountered = true ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
if ( argEncountered )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
os < < " " ;
2016-07-25 18:31:10 +00:00
}
2017-02-13 08:23:35 +00:00
}
void writeFunctionHeaderName ( std : : ostream & os , std : : string const & name , bool singular , bool unique )
{
2017-04-24 07:30:02 +00:00
os < < ( singular ? stripPluralS ( name ) : name ) ;
2017-02-13 08:23:35 +00:00
if ( unique )
{
os < < " Unique " ;
}
}
void writeFunctionHeaderReturnType ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool enhanced , bool singular , bool unique )
{
2017-05-16 13:32:14 +00:00
std : : string templateString ;
std : : string returnType ;
2017-02-13 08:23:35 +00:00
if ( enhanced )
{
2017-04-24 07:30:02 +00:00
// the enhanced function might return some pretty complex return stuff
2017-02-13 08:23:35 +00:00
if ( unique )
{
2017-04-24 07:30:02 +00:00
// 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
2017-02-13 08:23:35 +00:00
bool returnsVector = ! singular & & ( commandData . vectorParams . find ( commandData . returnParam ) ! = commandData . vectorParams . end ( ) ) ;
2017-05-16 13:32:14 +00:00
templateString = returnsVector ? " std::vector<Unique${returnType}> " : " Unique${returnType} " ;
returnType = commandData . params [ commandData . returnParam ] . pureType ;
//os << replaceWithMap(, {{"returnType", commandData.params[commandData.returnParam].pureType }});
2017-02-13 08:23:35 +00:00
}
else if ( ( commandData . enhancedReturnType ! = commandData . returnType ) & & ( commandData . returnType ! = " void " ) )
{
2017-04-24 07:30:02 +00:00
// if the enhanced return type differs from the original return type, and it's not void, we return a ResultValueType<...>::type
if ( ! 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
2017-05-16 13:32:14 +00:00
templateString = " typename ResultValueType<${returnType}>::type " ;
}
else
{
templateString = " ResultValueType<${returnType}>::type " ;
2017-04-24 07:30:02 +00:00
}
2017-02-13 08:23:35 +00:00
assert ( commandData . returnType = = " Result " ) ;
2017-04-24 07:30:02 +00:00
// in singular case, we create the ResultValueType from the pure return type, otherwise from the enhanced return type
2017-05-16 13:32:14 +00:00
returnType = singular ? commandData . params [ commandData . returnParam ] . pureType : commandData . enhancedReturnType ;
2017-02-13 08:23:35 +00:00
}
else if ( ( commandData . returnParam ! = ~ 0 ) & & ( 1 < commandData . successCodes . size ( ) ) )
{
2017-04-26 07:30:24 +00:00
// if there is a return parameter at all, and there are multiple success codes, we return a ResultValue<...> with the pure return type
2017-02-13 08:23:35 +00:00
assert ( commandData . returnType = = " Result " ) ;
2017-05-16 13:32:14 +00:00
templateString = " ResultValue<${returnType}> " ;
returnType = commandData . params [ commandData . returnParam ] . pureType ;
2017-02-13 08:23:35 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// and in every other case, we just return the enhanced return type.
2017-05-16 13:32:14 +00:00
templateString = " ${returnType} " ;
returnType = commandData . enhancedReturnType ;
2017-02-13 08:23:35 +00:00
}
}
else
{
2017-04-24 07:30:02 +00:00
// the non-enhanced function just uses the return type
2017-05-16 13:32:14 +00:00
templateString = " ${returnType} " ;
returnType = commandData . returnType ;
2017-02-13 08:23:35 +00:00
}
2017-05-16 13:32:14 +00:00
os < < replaceWithMap ( templateString , { { " returnType " , returnType } } ) ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
void writeFunctionHeaderTemplate ( std : : ostream & os , std : : string const & indentation , CommandData const & commandData , bool withDefault )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
if ( ( commandData . templateParam ! = ~ 0 ) & & ( ( commandData . templateParam ! = commandData . returnParam ) | | ( commandData . enhancedReturnType = = " Result " ) ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// if there's a template parameter, not being the return parameter or where the enhanced return type is 'Result' -> templatize on type 'T'
2017-02-13 08:23:35 +00:00
assert ( commandData . enhancedReturnType . find ( " Allocator " ) = = std : : string : : npos ) ;
os < < indentation < < " template <typename T> " < < std : : endl ;
}
2017-04-24 07:30:02 +00:00
else if ( ( commandData . enhancedReturnType . find ( " Allocator " ) ! = std : : string : : npos ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// otherwise, if there's an Allocator used in the enhanced return type, we templatize on that Allocator
2017-02-13 08:23:35 +00:00
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 )
{
2017-04-24 07:30:02 +00:00
// for the default type get the type from the enhancedReturnType, which is of the form 'std::vector<Type,Allocator>'
2017-02-13 08:23:35 +00:00
os < < " = std::allocator< " < < commandData . enhancedReturnType . substr ( 12 , commandData . enhancedReturnType . find ( ' , ' ) - 12 ) < < " > " ;
}
os < < " > " < < std : : endl ;
}
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
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 < < " *> " ;
}
2017-05-16 13:32:14 +00:00
void writeStandardOrEnhanced ( std : : ostream & os , std : : string const & standard , std : : string const & enhanced )
2017-04-24 07:30:02 +00:00
{
if ( standard = = enhanced )
{
// standard and enhanced string are equal -> just use one of them and we're done
2017-05-16 13:32:14 +00:00
os < < standard ;
2017-04-24 07:30:02 +00:00
}
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 )
{
2017-05-16 13:32:14 +00:00
os < < " #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE " < < std : : endl ;
2017-04-24 07:30:02 +00:00
}
2017-05-16 13:32:14 +00:00
os < < standard
2017-04-24 07:30:02 +00:00
< < ( unchangedInterface ? " #else " : " #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE " ) < < std : : endl
< < enhanced
< < " #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/ " < < std : : endl ;
}
}
2017-05-16 13:32:14 +00:00
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 & defaultValues )
2016-07-25 18:31:10 +00:00
{
// the constructor with all the elements as arguments, with defaults
2017-05-16 13:32:14 +00:00
os < < " " < < name < < " ( " ;
2016-07-25 18:31:10 +00:00
bool listedArgument = false ;
for ( size_t i = 0 ; i < structData . members . size ( ) ; i + + )
{
if ( listedArgument )
{
2017-05-16 13:32:14 +00:00
os < < " , " ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
// skip members 'pNext' and 'sType', as they are never explicitly set
2016-07-25 18:31:10 +00:00
if ( ( structData . members [ i ] . name ! = " pNext " ) & & ( structData . members [ i ] . name ! = " sType " ) )
{
2017-04-24 07:30:02 +00:00
// find a default value for the given pure type
2016-07-25 18:31:10 +00:00
std : : map < std : : string , std : : string > : : const_iterator defaultIt = defaultValues . find ( structData . members [ i ] . pureType ) ;
assert ( defaultIt ! = defaultValues . end ( ) ) ;
2017-04-24 07:30:02 +00:00
2016-07-25 18:31:10 +00:00
if ( structData . members [ i ] . arraySize . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// the arguments name get a trailing '_', to distinguish them from the actual struct members
// pointer arguments get a nullptr as default
2017-05-16 13:32:14 +00:00
os < < structData . members [ i ] . type < < " " < < structData . members [ i ] . name < < " _ = " < < ( structData . members [ i ] . type . back ( ) = = ' * ' ? " nullptr " : defaultIt - > second ) ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// 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
2017-05-16 13:32:14 +00:00
os < < " std::array< " < < structData . members [ i ] . type < < " , " < < structData . members [ i ] . arraySize < < " > const& " < < structData . members [ i ] . name < < " _ = { { " < < defaultIt - > second ;
2016-07-25 18:31:10 +00:00
size_t n = atoi ( structData . members [ i ] . arraySize . c_str ( ) ) ;
assert ( 0 < n ) ;
for ( size_t j = 1 ; j < n ; j + + )
{
2017-05-16 13:32:14 +00:00
os < < " , " < < defaultIt - > second ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " } } " ;
2016-07-25 18:31:10 +00:00
}
listedArgument = true ;
}
}
2017-05-16 13:32:14 +00:00
os < < " ) " < < std : : endl ;
2016-07-25 18:31:10 +00:00
// copy over the simple arguments
bool firstArgument = true ;
for ( size_t i = 0 ; i < structData . members . size ( ) ; i + + )
{
if ( structData . members [ i ] . arraySize . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// here, we can only handle non-array arguments
2017-05-16 13:32:14 +00:00
std : : string templateString = " ${sep} ${member}( ${value} ) \n " ;
std : : string sep = firstArgument ? " : " : " , " ;
std : : string member = structData . members [ i ] . name ;
std : : string value ;
2017-04-24 07:30:02 +00:00
// 'pNext' and 'sType' don't get an argument, use nullptr and the correct StructureType enum value to initialize them
2016-07-25 18:31:10 +00:00
if ( structData . members [ i ] . name = = " pNext " )
{
2017-05-16 13:32:14 +00:00
value = " nullptr " ;
2016-07-25 18:31:10 +00:00
}
else if ( structData . members [ i ] . name = = " sType " )
{
2017-05-16 13:32:14 +00:00
value = std : : string ( " StructureType::e " ) + name ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// the other elements are initialized by the corresponding argument (with trailing '_', as mentioned above)
2017-05-16 13:32:14 +00:00
value = structData . members [ i ] . name + " _ " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < replaceWithMap ( templateString , { { " sep " , sep } , { " member " , member } , { " value " , value } } ) ;
2016-07-25 18:31:10 +00:00
firstArgument = false ;
}
}
// the body of the constructor, copying over data from argument list into wrapped struct
2017-05-16 13:32:14 +00:00
os < < " { " < < std : : endl ;
2016-07-25 18:31:10 +00:00
for ( size_t i = 0 ; i < structData . members . size ( ) ; i + + )
{
2017-05-16 13:32:14 +00:00
if ( ! structData . members [ i ] . arraySize . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// here we can handle the arrays, copying over from argument (with trailing '_') to member
// size is arraySize times sizeof type
2017-05-16 13:32:14 +00:00
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 } } ) ;
2016-07-25 18:31:10 +00:00
}
}
2017-05-16 13:32:14 +00:00
os < < " } " < < std : : endl
2016-07-25 18:31:10 +00:00
< < std : : endl ;
2017-05-16 13:32:14 +00:00
std : : string templateString =
R " ( ${name}( Vk${name} const & rhs )
{
memcpy ( this , & rhs , sizeof ( $ { name } ) ) ;
}
2016-07-25 18:31:10 +00:00
2017-05-16 13:32:14 +00:00
$ { name } & operator = ( Vk $ { name } const & rhs )
{
memcpy ( this , & rhs , sizeof ( $ { name } ) ) ;
return * this ;
}
) " ;
os < < replaceWithMap ( templateString , { { " name " , name } } ) ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeStructSetter ( std : : ostream & os , std : : string const & structureName , MemberData const & memberData , std : : set < std : : string > const & vkTypes )
2016-07-25 18:31:10 +00:00
{
2017-01-30 16:08:49 +00:00
if ( memberData . type ! = " StructureType " ) // filter out StructureType, which is supposed to be immutable !
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// the setters return a reference to the structure
2017-05-16 13:32:14 +00:00
os < < " " < < structureName < < " & set " < < startUpperCase ( memberData . name ) < < " ( " ;
2017-01-30 16:08:49 +00:00
if ( memberData . arraySize . empty ( ) )
{
2017-05-16 13:32:14 +00:00
os < < memberData . type < < " " ;
2017-01-30 16:08:49 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " std::array< " < < memberData . type < < " , " < < memberData . arraySize < < " > " ;
2017-01-30 16:08:49 +00:00
}
2017-04-24 07:30:02 +00:00
// add a trailing '_' to the argument to distinguish it from the structure member
2017-05-16 13:32:14 +00:00
os < < memberData . name < < " _ ) " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
2017-04-24 07:30:02 +00:00
// copy over the argument, either by assigning simple data, or by memcpy array data
if ( memberData . arraySize . empty ( ) )
2017-01-30 16:08:49 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " " < < memberData . name < < " = " < < memberData . name < < " _ " ;
2017-01-30 16:08:49 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " memcpy( & " < < memberData . name < < " , " < < memberData . name < < " _.data(), " < < memberData . arraySize < < " * sizeof( " < < memberData . type < < " ) ) " ;
2017-01-30 16:08:49 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " ; " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " return *this; " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
2017-01-30 16:08:49 +00:00
}
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeTypeCommand ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData )
2016-07-25 18:31:10 +00:00
{
assert ( vkData . commands . find ( dependencyData . name ) ! = vkData . commands . end ( ) ) ;
CommandData const & commandData = vkData . commands . find ( dependencyData . name ) - > second ;
2017-02-13 08:23:35 +00:00
if ( commandData . className . empty ( ) )
{
if ( commandData . fullName = = " createInstance " )
{
2017-04-24 07:30:02 +00:00
// special handling for createInstance, as we need to explicitly place the forward declarations and the deleter classes here
2017-02-13 08:23:35 +00:00
auto deleterTypesIt = vkData . deleterTypes . find ( " " ) ;
assert ( ( deleterTypesIt ! = vkData . deleterTypes . end ( ) ) & & ( deleterTypesIt - > second . size ( ) = = 1 ) ) ;
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
writeDeleterForwardDeclarations ( os , * deleterTypesIt , vkData . deleterData ) ;
writeTypeCommand ( os , " " , vkData , commandData , false ) ;
writeDeleterClasses ( os , * deleterTypesIt , vkData . deleterData ) ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
else
2017-02-13 08:23:35 +00:00
{
2017-05-16 13:32:14 +00:00
writeTypeCommand ( os , " " , vkData , commandData , false ) ;
2017-02-13 08:23:35 +00:00
}
2017-05-16 13:32:14 +00:00
writeTypeCommand ( os , " " , vkData , commandData , true ) ;
os < < std : : endl ;
2017-02-13 08:23:35 +00:00
}
}
2017-05-16 13:32:14 +00:00
void writeTypeCommand ( std : : ostream & os , std : : string const & indentation , VkData const & vkData , CommandData const & commandData , bool definition )
2017-02-13 08:23:35 +00:00
{
2017-05-16 13:32:14 +00:00
enterProtect ( os , commandData . protect ) ;
2016-07-25 18:31:10 +00:00
2017-04-24 07:30:02 +00:00
// first create the standard version of the function
std : : ostringstream standard ;
writeFunction ( standard , indentation , vkData , commandData , definition , false , false , false ) ;
// then the enhanced version, composed by up to four parts
std : : ostringstream enhanced ;
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , false , false ) ;
2017-02-13 08:23:35 +00:00
2017-04-24 07:30:02 +00:00
// then a singular version, if a sized vector would be returned
2017-02-13 08:23:35 +00:00
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 )
{
2017-04-24 07:30:02 +00:00
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , true , false ) ;
2017-02-13 08:23:35 +00:00
}
// special handling for createDevice and createInstance !
bool specialWriteUnique = ( commandData . reducedName = = " createDevice " ) | | ( commandData . reducedName = = " createInstance " ) ;
2017-04-24 07:30:02 +00:00
// 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')
2017-02-13 08:23:35 +00:00
if ( ( ( vkData . deleterData . find ( commandData . className ) ! = vkData . deleterData . end ( ) ) | | specialWriteUnique ) & & ( ( commandData . reducedName . substr ( 0 , 8 ) = = " allocate " ) | | ( commandData . reducedName . substr ( 0 , 6 ) = = " create " ) ) )
{
2017-04-24 07:30:02 +00:00
enhanced < < " #ifndef VULKAN_HPP_NO_SMART_HANDLE " < < std : : endl ;
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , false , true ) ;
2017-02-13 08:23:35 +00:00
if ( singular )
{
2017-04-24 07:30:02 +00:00
writeFunction ( enhanced , indentation , vkData , commandData , definition , true , true , true ) ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
enhanced < < " #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
// and write one or both of them
2017-05-16 13:32:14 +00:00
writeStandardOrEnhanced ( os , standard . str ( ) , enhanced . str ( ) ) ;
leaveProtect ( os , commandData . protect ) ;
os < < std : : endl ;
2017-02-13 08:23:35 +00:00
}
2017-05-16 13:32:14 +00:00
void writeTypeEnum ( std : : ostream & os , EnumData const & enumData )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// a named enum per enum, listing all its values by setting them to the original Vulkan names
2017-05-16 13:32:14 +00:00
enterProtect ( os , enumData . protect ) ;
os < < " enum class " < < enumData . name < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
for ( size_t i = 0 ; i < enumData . members . size ( ) ; i + + )
{
2017-05-16 13:32:14 +00:00
os < < " " < < enumData . members [ i ] . name < < " = " < < enumData . members [ i ] . value ;
2016-07-25 18:31:10 +00:00
if ( i < enumData . members . size ( ) - 1 )
{
2017-05-16 13:32:14 +00:00
os < < " , " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " }; " < < std : : endl ;
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-04-26 07:30:24 +00:00
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`!
2017-05-16 13:32:14 +00:00
void writeExceptionsForEnum ( std : : ostream & os , EnumData const & enumData )
2017-04-26 07:30:24 +00:00
{
2017-05-16 13:32:14 +00:00
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 . members . size ( ) ; i + + )
{
if ( ! isErrorEnum ( enumData . members [ i ] . name ) )
2017-04-26 07:30:24 +00:00
{
2017-05-16 13:32:14 +00:00
continue ;
}
os < < replaceWithMap ( templateString ,
{ { " className " , stripErrorEnumPrefix ( enumData . members [ i ] . name ) + " Error " } ,
{ " enumName " , enumData . name } ,
{ " enumMemberName " , enumData . members [ i ] . name }
} ) ;
}
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
2017-04-26 07:30:24 +00:00
}
2017-05-16 13:32:14 +00:00
void writeThrowExceptions ( std : : ostream & os , EnumData const & enumData )
2017-04-26 07:30:24 +00:00
{
2017-05-16 13:32:14 +00:00
enterProtect ( os , enumData . protect ) ;
os < <
R " ( VULKAN_HPP_INLINE void throwResultException( Result result, char const * message )
{
assert ( static_cast < long long int > ( result ) < 0 ) ;
switch ( result )
{
) " ;
2017-04-26 07:30:24 +00:00
for ( size_t i = 0 ; i < enumData . members . size ( ) ; i + + )
{
if ( ! isErrorEnum ( enumData . members [ i ] . name ) )
{
continue ;
}
const std : : string strippedExceptionName = stripErrorEnumPrefix ( enumData . members [ i ] . name ) ;
2017-05-16 13:32:14 +00:00
os < < " case " < < enumData . name < < " :: " < < enumData . members [ i ] . name < < " : "
2017-04-26 07:30:24 +00:00
< < " throw " < < strippedExceptionName < < " Error ( message ); " < < std : : endl ;
}
2017-05-16 13:32:14 +00:00
os < <
R " ( default: throw SystemError( make_error_code( result ) );
}
}
) " ;
leaveProtect ( os , enumData . protect ) ;
2017-04-26 07:30:24 +00:00
}
2017-05-16 13:32:14 +00:00
void writeDeleterClasses ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleterData )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
// A Deleter class for each of the Unique* classes... but only if smart handles are not switched off
2017-05-16 13:32:14 +00:00
os < < " #ifndef VULKAN_HPP_NO_SMART_HANDLE " < < std : : endl ;
2017-01-27 14:15:50 +00:00
bool first = true ;
2017-04-24 07:30:02 +00:00
// 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 )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
std : : string deleterName = startLowerCase ( deleterType ) ;
bool standardDeleter = ! parentType . empty ( ) & & ( deleterType ! = " Device " ) ; // this detects the 'standard' case for a deleter
2017-02-13 08:23:35 +00:00
2017-01-27 14:15:50 +00:00
if ( ! first )
{
2017-05-16 13:32:14 +00:00
os < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
first = false ;
2017-05-16 13:32:14 +00:00
os < < " class " < < deleterType < < " Deleter " < < std : : endl
2017-01-27 14:15:50 +00:00
< < " { " < < std : : endl
< < " public: " < < std : : endl
2017-04-24 07:30:02 +00:00
< < " " < < deleterType < < " Deleter( " ;
if ( standardDeleter )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
// the standard deleter gets a parent type in the constructor
2017-05-16 13:32:14 +00:00
os < < parentType < < " " < < parentName < < " = " < < parentType < < " (), " ;
2017-01-27 14:15:50 +00:00
}
2017-04-24 07:30:02 +00:00
// if this Deleter is pooled, make such a pool the last argument, otherwise an Optional allocator
auto const & dd = deleterData . find ( deleterType ) ;
2017-01-27 14:15:50 +00:00
assert ( dd ! = deleterData . end ( ) ) ;
2017-04-24 07:30:02 +00:00
std : : string poolName = ( dd - > second . pool . empty ( ) ? " " : startLowerCase ( dd - > second . pool ) ) ;
2017-01-27 14:15:50 +00:00
if ( poolName . empty ( ) )
{
2017-05-16 13:32:14 +00:00
os < < " Optional<const AllocationCallbacks> allocator = nullptr ) " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
else
{
assert ( ! dd - > second . pool . empty ( ) ) ;
2017-05-16 13:32:14 +00:00
os < < dd - > second . pool < < " " < < poolName < < " = " < < dd - > second . pool < < " () ) " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
2017-04-24 07:30:02 +00:00
// now the initializer list of the Deleter constructor
2017-05-16 13:32:14 +00:00
os < < " : " ;
2017-04-24 07:30:02 +00:00
if ( standardDeleter )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
// the standard deleter has a parent type as a member
2017-05-16 13:32:14 +00:00
os < < " m_ " < < parentName < < " ( " < < parentName < < " ) " < < std : : endl
2017-01-27 14:15:50 +00:00
< < " , " ;
}
if ( poolName . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// non-pooled deleter have an allocator as a member
2017-05-16 13:32:14 +00:00
os < < " m_allocator( allocator ) " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// pooled deleter have a pool as a member
2017-05-16 13:32:14 +00:00
os < < " m_ " < < poolName < < " ( " < < poolName < < " ) " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
2017-04-24 07:30:02 +00:00
// besides that, the constructor is empty
2017-05-16 13:32:14 +00:00
os < < " {} " < < std : : endl
2017-04-24 07:30:02 +00:00
< < std : : endl ;
// the operator() calls the delete/destroy function
2017-05-16 13:32:14 +00:00
os < < " void operator()( " < < deleterType < < " " < < deleterName < < " ) " < < std : : endl
2017-02-13 08:23:35 +00:00
< < " { " < < std : : endl ;
2017-04-24 07:30:02 +00:00
// the delete/destroy function is either part of the parent member of the deleter argument
if ( standardDeleter )
2017-02-13 08:23:35 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " m_ " < < parentName < < " . " ;
2017-02-13 08:23:35 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " " < < deleterName < < " . " ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
os < < dd - > second . call < < " ( " ;
2017-04-24 07:30:02 +00:00
if ( ! poolName . empty ( ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// pooled Deleter gets the pool as the first argument
2017-05-16 13:32:14 +00:00
os < < " m_ " < < poolName < < " , " ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
if ( standardDeleter )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
// the standard deleter gets the deleter argument as an argument
2017-05-16 13:32:14 +00:00
os < < deleterName ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
// the non-pooled deleter get the allocate as an argument (potentially after the deleterName
if ( poolName . empty ( ) )
2017-02-13 08:23:35 +00:00
{
2017-04-24 07:30:02 +00:00
if ( standardDeleter )
2017-02-13 08:23:35 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " , " ;
2017-02-13 08:23:35 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " m_allocator " ;
2017-02-13 08:23:35 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " ); " < < std : : endl
2017-02-13 08:23:35 +00:00
< < " } " < < std : : endl
2017-04-24 07:30:02 +00:00
< < std : : endl ;
// now the members of the Deleter class
2017-05-16 13:32:14 +00:00
os < < " private: " < < std : : endl ;
2017-04-24 07:30:02 +00:00
if ( standardDeleter )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
// the parentType for the standard deleter
2017-05-16 13:32:14 +00:00
os < < " " < < parentType < < " m_ " < < parentName < < " ; " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
2017-04-24 07:30:02 +00:00
// the allocator for the non-pooled deleters, the pool for the pooled ones
2017-01-27 14:15:50 +00:00
if ( poolName . empty ( ) )
{
2017-05-16 13:32:14 +00:00
os < < " Optional<const AllocationCallbacks> m_allocator; " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " " < < dd - > second . pool < < " m_ " < < poolName < < " ; " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " }; " < < std : : endl ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
os < < " #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ " < < std : : endl
2017-01-27 14:15:50 +00:00
< < std : : endl ;
}
2017-05-16 13:32:14 +00:00
void writeDeleterForwardDeclarations ( std : : ostream & os , std : : pair < std : : string , std : : set < std : : string > > const & deleterTypes , std : : map < std : : string , DeleterData > const & deleterData )
2017-01-27 14:15:50 +00:00
{
2017-04-24 07:30:02 +00:00
// if smart handles are supported, all the Deleter classes need to be forward declared
2017-05-16 13:32:14 +00:00
os < < " #ifndef VULKAN_HPP_NO_SMART_HANDLE " < < std : : endl ;
2017-01-27 14:15:50 +00:00
bool first = true ;
2017-04-24 07:30:02 +00:00
std : : string firstName = deleterTypes . first . empty ( ) ? " " : startLowerCase ( deleterTypes . first ) ;
2017-02-13 08:23:35 +00:00
for ( auto const & dt : deleterTypes . second )
2017-01-27 14:15:50 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " class " < < dt < < " Deleter; " < < std : : endl ;
os < < " using Unique " < < dt < < " = UniqueHandle< " < < dt < < " , " < < dt < < " Deleter>; " < < std : : endl ;
2017-01-27 14:15:50 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " #endif /*VULKAN_HPP_NO_SMART_HANDLE*/ " < < std : : endl
2017-01-27 14:15:50 +00:00
< < std : : endl ;
}
2017-05-16 13:32:14 +00:00
void writeEnumsToString ( std : : ostream & os , EnumData const & enumData )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// the helper functions to make strings out of enum values
2017-05-16 13:32:14 +00:00
enterProtect ( os , enumData . protect ) ;
os < < " VULKAN_HPP_INLINE std::string to_string( " < < enumData . name < < ( enumData . members . empty ( ) ? " ) " : " value) " ) < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
if ( enumData . members . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// no enum values in this enum -> return "(void)"
2017-05-16 13:32:14 +00:00
os < < " return \" (void) \" ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-04-24 07:30:02 +00:00
// otherwise switch over the value and return the a stringized version of that value (without leading 'e')
2017-05-16 13:32:14 +00:00
os < < " switch (value) " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
2017-04-24 07:30:02 +00:00
for ( auto const & member : enumData . members )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " case " < < enumData . name < < " :: " < < member . name < < " : return \" " < < member . name . substr ( 1 ) < < " \" ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " default: return \" invalid \" ; " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " } " < < std : : endl ;
}
2017-05-16 13:32:14 +00:00
os < < " } " < < std : : endl ;
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeFlagsToString ( std : : ostream & os , std : : string const & flagsName , EnumData const & enumData )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
// the helper functions to make strings out of flag values
2017-05-16 13:32:14 +00:00
enterProtect ( os , enumData . protect ) ;
os < < " VULKAN_HPP_INLINE std::string to_string( " < < flagsName < < ( enumData . members . empty ( ) ? " ) " : " value) " ) < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
if ( enumData . members . empty ( ) )
{
2017-04-24 07:30:02 +00:00
// no flags values in this enum -> return "{}"
2017-05-16 13:32:14 +00:00
os < < " return \" {} \" ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " if (!value) return \" {} \" ; " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " std::string result; " < < std : : endl ;
2017-04-24 07:30:02 +00:00
// 'or' together all the bits in the value
2016-07-25 18:31:10 +00:00
for ( auto itMember = enumData . members . begin ( ) ; itMember ! = enumData . members . end ( ) ; + + itMember )
{
2017-05-16 13:32:14 +00:00
os < < " if (value & " < < enumData . name < < " :: " < < itMember - > name < < " ) result += \" " < < itMember - > name . substr ( 1 ) < < " | \" ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
// cut off the last three characters from the result (being " | ")
2017-05-16 13:32:14 +00:00
os < < " return \" { \" + result.substr(0, result.size() - 3) + \" } \" ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " } " < < std : : endl ;
leaveProtect ( os , enumData . protect ) ;
os < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeTypeFlags ( std : : ostream & os , std : : string const & flagsName , FlagData const & flagData , EnumData const & enumData )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
enterProtect ( os , flagData . protect ) ;
2017-04-24 07:30:02 +00:00
// each Flags class is using on the class 'Flags' with the corresponding FlagBits enum as the template parameter
2017-05-16 13:32:14 +00:00
os < < " using " < < flagsName < < " = Flags< " < < enumData . name < < " , Vk " < < flagsName < < " >; " < < std : : endl ;
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
std : : stringstream allFlags ;
for ( size_t i = 0 ; i < enumData . members . size ( ) ; i + + )
2016-10-26 08:49:58 +00:00
{
2017-05-16 13:32:14 +00:00
if ( i ! = 0 )
{
allFlags < < " | " ;
}
allFlags < < " VkFlags( " < < enumData . name < < " :: " < < enumData . members [ i ] . name < < " ) " ;
}
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
if ( ! enumData . members . empty ( ) )
{
const std : : string templateString = R " (
VULKAN_HPP_INLINE $ { flagsName } operator | ( $ { enumName } bit0 , $ { enumName } bit1 )
{
return $ { flagsName } ( bit0 ) | bit1 ;
}
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
VULKAN_HPP_INLINE $ { flagsName } operator ~ ( $ { enumName } bits )
{
return ~ ( $ { flagsName } ( bits ) ) ;
}
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
template < > struct FlagTraits < $ { enumName } >
{
enum
2016-11-04 08:14:53 +00:00
{
2017-05-16 13:32:14 +00:00
allFlags = $ { allFlags }
} ;
} ;
) " ;
os < < replaceWithMap ( templateString , { { " flagsName " , flagsName } , { " enumName " , enumData . name } , { " allFlags " , allFlags . str ( ) } } ) ;
2016-10-26 08:49:58 +00:00
}
2017-05-16 13:32:14 +00:00
leaveProtect ( os , flagData . protect ) ;
os < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeTypeHandle ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , HandleData const & handleData , std : : list < DependencyData > const & dependencies )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
enterProtect ( os , handleData . protect ) ;
2016-12-01 21:00:03 +00:00
2017-04-24 07:30:02 +00:00
// check if there are any forward dependenices for this handle -> list them first
2016-12-01 21:00:03 +00:00
if ( ! dependencyData . forwardDependencies . empty ( ) )
{
2017-05-16 13:32:14 +00:00
os < < " // forward declarations " < < std : : endl ;
2016-12-01 21:00:03 +00:00
for ( std : : set < std : : string > : : const_iterator it = dependencyData . forwardDependencies . begin ( ) ; it ! = dependencyData . forwardDependencies . end ( ) ; + + it )
{
assert ( vkData . structs . find ( * it ) ! = vkData . structs . end ( ) ) ;
2017-05-16 13:32:14 +00:00
os < < " struct " < < * it < < " ; " < < std : : endl ;
2016-12-01 21:00:03 +00:00
}
2017-05-16 13:32:14 +00:00
os < < std : : endl ;
2016-12-01 21:00:03 +00:00
}
2017-04-24 07:30:02 +00:00
// then write any forward declaration of Deleters used by this handle
2017-01-27 14:15:50 +00:00
std : : map < std : : string , std : : set < std : : string > > : : const_iterator deleterTypesIt = vkData . deleterTypes . find ( dependencyData . name ) ;
if ( deleterTypesIt ! = vkData . deleterTypes . end ( ) )
{
2017-05-16 13:32:14 +00:00
writeDeleterForwardDeclarations ( os , * deleterTypesIt , vkData . deleterData ) ;
2017-01-27 14:15:50 +00:00
}
2017-02-13 08:23:35 +00:00
2017-05-16 13:32:14 +00:00
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 } ;
} ;
2016-07-25 18:31:10 +00:00
2017-05-16 13:32:14 +00:00
static_assert ( sizeof ( $ { className } ) = = sizeof ( Vk $ { className } ) , " handle and wrapper have different size! " ) ;
) " ;
std : : ostringstream commands ;
2017-04-24 07:30:02 +00:00
// now list all the commands that are mapped to members of this class
2017-02-13 08:23:35 +00:00
for ( size_t i = 0 ; i < handleData . commands . size ( ) ; i + + )
2016-07-25 18:31:10 +00:00
{
2017-02-13 08:23:35 +00:00
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 ( ) ) ;
2017-05-16 13:32:14 +00:00
writeTypeCommand ( commands , " " , vkData , cit - > second , false ) ;
}
2017-02-13 08:23:35 +00:00
2017-05-16 13:32:14 +00:00
os < < replaceWithMap ( templateString , {
{ " className " , dependencyData . name } ,
{ " memberName " , memberName } ,
{ " commands " , commands . str ( ) }
} ) ;
2017-04-24 07:30:02 +00:00
2017-05-16 13:32:14 +00:00
// then the actual Deleter classes can be listed
2017-02-13 08:23:35 +00:00
deleterTypesIt = vkData . deleterTypes . find ( dependencyData . name ) ;
2017-01-27 14:15:50 +00:00
if ( deleterTypesIt ! = vkData . deleterTypes . end ( ) )
{
2017-05-16 13:32:14 +00:00
writeDeleterClasses ( os , * deleterTypesIt , vkData . deleterData ) ;
2017-02-13 08:23:35 +00:00
}
2017-04-24 07:30:02 +00:00
// and finally the commands, that are member functions of this handle
2017-02-13 08:23:35 +00:00
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 ) ) ;
2017-05-16 13:32:14 +00:00
writeTypeCommand ( os , " " , vkData , cit - > second , true ) ;
2017-01-27 14:15:50 +00:00
}
2017-02-13 08:23:35 +00:00
2017-05-16 13:32:14 +00:00
leaveProtect ( os , handleData . protect ) ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeTypeScalar ( std : : ostream & os , DependencyData const & dependencyData )
2016-07-25 18:31:10 +00:00
{
assert ( dependencyData . dependencies . size ( ) = = 1 ) ;
2017-05-16 13:32:14 +00:00
os < < " using " < < dependencyData . name < < " = " < < * dependencyData . dependencies . begin ( ) < < " ; " < < std : : endl
2016-07-25 18:31:10 +00:00
< < std : : endl ;
}
2016-07-26 14:09:41 +00:00
bool containsUnion ( std : : string const & type , std : : map < std : : string , StructData > const & structs )
{
2017-04-24 07:30:02 +00:00
// a simple recursive check if a type is or contains a union
2016-07-26 14:09:41 +00:00
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 ;
}
2017-05-16 13:32:14 +00:00
void writeTypeStruct ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , std : : map < std : : string , std : : string > const & defaultValues )
2016-07-25 18:31:10 +00:00
{
std : : map < std : : string , StructData > : : const_iterator it = vkData . structs . find ( dependencyData . name ) ;
assert ( it ! = vkData . structs . end ( ) ) ;
2017-05-16 13:32:14 +00:00
enterProtect ( os , it - > second . protect ) ;
os < < " struct " < < dependencyData . name < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
// only structs that are not returnedOnly get a constructor!
if ( ! it - > second . returnedOnly )
{
2017-05-16 13:32:14 +00:00
writeStructConstructor ( os , dependencyData . name , it - > second , vkData . vkTypes , defaultValues ) ;
2016-07-25 18:31:10 +00:00
}
// create the setters
if ( ! it - > second . returnedOnly )
{
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
2017-05-16 13:32:14 +00:00
writeStructSetter ( os , dependencyData . name , it - > second . members [ i ] , vkData . vkTypes ) ;
2016-07-25 18:31:10 +00:00
}
}
// the cast-operator to the wrapped struct
2017-05-16 13:32:14 +00:00
os < < " operator const Vk " < < dependencyData . name < < " &() const " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl
< < " return *reinterpret_cast<const Vk " < < dependencyData . name < < " *>(this); " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
2016-07-26 14:09:41 +00:00
// 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 ) )
{
2017-04-24 07:30:02 +00:00
// two structs are compared by comparing each of the elements
2017-05-16 13:32:14 +00:00
os < < " bool operator==( " < < dependencyData . name < < " const& rhs ) const " < < std : : endl
2016-07-26 14:09:41 +00:00
< < " { " < < std : : endl
< < " return " ;
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
{
if ( i ! = 0 )
{
2017-05-16 13:32:14 +00:00
os < < std : : endl < < " && " ;
2016-07-26 14:09:41 +00:00
}
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
{
2017-05-16 13:32:14 +00:00
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 ) " ;
2016-07-26 14:09:41 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " ( " < < it - > second . members [ i ] . name < < " == rhs. " < < it - > second . members [ i ] . name < < " ) " ;
2016-07-26 14:09:41 +00:00
}
}
2017-05-16 13:32:14 +00:00
os < < " ; " < < std : : endl
2016-07-26 14:09:41 +00:00
< < " } " < < std : : endl
< < std : : endl
< < " bool operator!=( " < < dependencyData . name < < " const& rhs ) const " < < std : : endl
< < " { " < < std : : endl
< < " return !operator==( rhs ); " < < std : : endl
< < " } " < < std : : endl
< < std : : endl ;
}
2016-07-25 18:31:10 +00:00
// 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 " ) ) ;
2017-05-16 13:32:14 +00:00
os < < " private: " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " StructureType sType; " < < std : : endl
< < std : : endl
< < " public: " < < std : : endl ;
}
else
{
2017-05-16 13:32:14 +00:00
os < < " " < < it - > second . members [ i ] . type < < " " < < it - > second . members [ i ] . name ;
2016-07-25 18:31:10 +00:00
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
{
2017-05-16 13:32:14 +00:00
os < < " [ " < < it - > second . members [ i ] . arraySize < < " ] " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
}
2017-05-16 13:32:14 +00:00
os < < " }; " < < std : : endl
2016-07-26 14:09:41 +00:00
< < " static_assert( sizeof( " < < dependencyData . name < < " ) == sizeof( Vk " < < dependencyData . name < < " ), \" struct and wrapper have different size! \" ); " < < std : : endl ;
2017-05-16 13:32:14 +00:00
leaveProtect ( os , it - > second . protect ) ;
os < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
void writeTypeUnion ( std : : ostream & os , VkData const & vkData , DependencyData const & dependencyData , std : : map < std : : string , std : : string > const & defaultValues )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
std : : map < std : : string , StructData > : : const_iterator it = vkData . structs . find ( dependencyData . name ) ;
assert ( it ! = vkData . structs . end ( ) ) ;
2016-07-25 18:31:10 +00:00
std : : ostringstream oss ;
2017-05-16 13:32:14 +00:00
os < < " union " < < dependencyData . name < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl ;
2017-04-24 07:30:02 +00:00
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
2016-07-25 18:31:10 +00:00
{
// one constructor per union element
2017-05-16 13:32:14 +00:00
os < < " " < < dependencyData . name < < " ( " ;
2017-04-24 07:30:02 +00:00
if ( it - > second . members [ i ] . arraySize . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < it - > second . members [ i ] . type < < " " ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " const std::array< " < < it - > second . members [ i ] . type < < " , " < < it - > second . members [ i ] . arraySize < < " >& " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < it - > second . members [ i ] . name < < " _ " ;
2016-07-25 18:31:10 +00:00
// just the very first constructor gets default arguments
if ( i = = 0 )
{
2017-04-24 07:30:02 +00:00
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 ( ) )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " = " < < defaultIt - > second ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " = { { " < < defaultIt - > second < < " } } " ;
2016-07-25 18:31:10 +00:00
}
}
2017-05-16 13:32:14 +00:00
os < < " ) " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < std : : endl
< < " " ;
2017-04-24 07:30:02 +00:00
if ( it - > second . members [ i ] . arraySize . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < it - > second . members [ i ] . name < < " = " < < it - > second . members [ i ] . name < < " _ " ;
2016-07-25 18:31:10 +00:00
}
else
{
2017-05-16 13:32:14 +00:00
os < < " memcpy( & " < < it - > second . members [ i ] . name < < " , " < < it - > second . members [ i ] . name < < " _.data(), " < < it - > second . members [ i ] . arraySize < < " * sizeof( " < < it - > second . members [ i ] . type < < " ) ) " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " ; " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " } " < < std : : endl
< < std : : endl ;
}
2017-04-24 07:30:02 +00:00
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
2016-07-25 18:31:10 +00:00
{
// one setter per union element
2017-04-24 07:30:02 +00:00
assert ( ! it - > second . returnedOnly ) ;
2017-05-16 13:32:14 +00:00
writeStructSetter ( os , dependencyData . name , it - > second . members [ i ] , vkData . vkTypes ) ;
2016-07-25 18:31:10 +00:00
}
// the implicit cast operator to the native type
2017-05-16 13:32:14 +00:00
os < < " operator Vk " < < dependencyData . name < < " const& () const " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " { " < < 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 ;
2017-04-24 07:30:02 +00:00
for ( size_t i = 0 ; i < it - > second . members . size ( ) & & ! needsUnrestrictedUnions ; i + + )
2016-07-25 18:31:10 +00:00
{
2017-04-24 07:30:02 +00:00
needsUnrestrictedUnions = ( vkData . vkTypes . find ( it - > second . members [ i ] . type ) ! = vkData . vkTypes . end ( ) ) ;
2016-07-25 18:31:10 +00:00
}
if ( needsUnrestrictedUnions )
{
2017-05-16 13:32:14 +00:00
os < < " #ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS " < < std : : endl ;
2017-04-24 07:30:02 +00:00
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " " < < it - > second . members [ i ] . type < < " " < < it - > second . members [ i ] . name ;
2017-04-24 07:30:02 +00:00
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " [ " < < it - > second . members [ i ] . arraySize < < " ] " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " #else " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-04-24 07:30:02 +00:00
for ( size_t i = 0 ; i < it - > second . members . size ( ) ; i + + )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " " ;
2017-04-24 07:30:02 +00:00
if ( vkData . vkTypes . find ( it - > second . members [ i ] . type ) ! = vkData . vkTypes . end ( ) )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " Vk " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < it - > second . members [ i ] . type < < " " < < it - > second . members [ i ] . name ;
2017-04-24 07:30:02 +00:00
if ( ! it - > second . members [ i ] . arraySize . empty ( ) )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " [ " < < it - > second . members [ i ] . arraySize < < " ] " ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " ; " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
if ( needsUnrestrictedUnions )
{
2017-05-16 13:32:14 +00:00
os < < " #endif // VULKAN_HPP_HAS_UNRESTRICTED_UNIONS " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
2017-05-16 13:32:14 +00:00
os < < " }; " < < std : : endl
2016-07-25 18:31:10 +00:00
< < std : : endl ;
}
2017-05-16 13:32:14 +00:00
void writeTypes ( std : : ostream & os , VkData const & vkData , std : : map < std : : string , std : : string > const & defaultValues )
2016-07-25 18:31:10 +00:00
{
for ( std : : list < DependencyData > : : const_iterator it = vkData . dependencies . begin ( ) ; it ! = vkData . dependencies . end ( ) ; + + it )
{
switch ( it - > category )
{
case DependencyData : : Category : : COMMAND :
2017-05-16 13:32:14 +00:00
writeTypeCommand ( os , vkData , * it ) ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : ENUM :
assert ( vkData . enums . find ( it - > name ) ! = vkData . enums . end ( ) ) ;
2017-05-16 13:32:14 +00:00
writeTypeEnum ( os , vkData . enums . find ( it - > name ) - > second ) ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : FLAGS :
assert ( vkData . flags . find ( it - > name ) ! = vkData . flags . end ( ) ) ;
2017-05-16 13:32:14 +00:00
writeTypeFlags ( os , it - > name , vkData . flags . find ( it - > name ) - > second , vkData . enums . find ( generateEnumNameForFlags ( it - > name ) ) - > second ) ;
2016-07-25 18:31:10 +00:00
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 ( ) ) ;
2017-05-16 13:32:14 +00:00
writeTypeHandle ( os , vkData , * it , vkData . handles . find ( it - > name ) - > second , vkData . dependencies ) ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : SCALAR :
2017-05-16 13:32:14 +00:00
writeTypeScalar ( os , * it ) ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : STRUCT :
2017-05-16 13:32:14 +00:00
writeTypeStruct ( os , vkData , * it , defaultValues ) ;
2016-07-25 18:31:10 +00:00
break ;
case DependencyData : : Category : : UNION :
assert ( vkData . structs . find ( it - > name ) ! = vkData . structs . end ( ) ) ;
2017-05-16 13:32:14 +00:00
writeTypeUnion ( os , vkData , * it , defaultValues ) ;
2016-07-25 18:31:10 +00:00
break ;
default :
assert ( false ) ;
break ;
}
}
}
2017-05-16 13:32:14 +00:00
void writeVersionCheck ( std : : ostream & os , std : : string const & version )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " static_assert( VK_HEADER_VERSION == " < < version < < " , \" Wrong VK_HEADER_VERSION! \" ); " < < std : : endl
2016-07-25 18:31:10 +00:00
< < std : : endl ;
}
2017-05-16 13:32:14 +00:00
void writeTypesafeCheck ( std : : ostream & os , std : : string const & typesafeCheck )
2016-07-25 18:31:10 +00:00
{
2017-05-16 13:32:14 +00:00
os < < " // 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default. " < < std : : endl
2016-07-25 18:31:10 +00:00
< < " // To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION " < < std : : endl
< < typesafeCheck < < std : : endl
2017-02-01 18:15:52 +00:00
< < " # if !defined( VULKAN_HPP_TYPESAFE_CONVERSION ) " < < std : : endl
< < " # define VULKAN_HPP_TYPESAFE_CONVERSION " < < std : : endl
< < " # endif " < < std : : endl
2017-02-15 16:07:50 +00:00
< < " #endif " < < std : : endl ;
2016-07-25 18:31:10 +00:00
}
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 " < < argv [ 1 ] < < " . Error code: " < < error < < std : : endl ;
return - 1 ;
}
tinyxml2 : : XMLElement * registryElement = doc . FirstChildElement ( ) ;
assert ( strcmp ( registryElement - > Value ( ) , " registry " ) = = 0 ) ;
assert ( ! registryElement - > NextSiblingElement ( ) ) ;
VkData vkData ;
2017-04-06 12:36:03 +00:00
vkData . handles [ " " ] ; // insert the default "handle" without class (for createInstance, and such)
vkData . tags . insert ( " KHX " ) ; // insert a non-listed tag
2016-07-25 18:31:10 +00:00
2017-03-08 13:14:01 +00:00
for ( tinyxml2 : : XMLElement * child = registryElement - > FirstChildElement ( ) ; child ; child = child - > NextSiblingElement ( ) )
2016-07-25 18:31:10 +00:00
{
assert ( child - > Value ( ) ) ;
const std : : string value = child - > Value ( ) ;
if ( value = = " commands " )
{
readCommands ( child , vkData ) ;
}
else if ( value = = " comment " )
{
2017-03-08 13:14:01 +00:00
// get the vulkan license header and skip any leading spaces
2016-07-25 18:31:10 +00:00
readComment ( child , vkData . vulkanLicenseHeader ) ;
2017-03-08 13:14:01 +00:00
vkData . vulkanLicenseHeader . erase ( vkData . vulkanLicenseHeader . begin ( ) , std : : find_if ( vkData . vulkanLicenseHeader . begin ( ) , vkData . vulkanLicenseHeader . end ( ) , [ ] ( char c ) { return ! std : : isspace ( c ) ; } ) ) ;
2016-07-25 18:31:10 +00:00
}
else if ( value = = " enums " )
{
readEnums ( child , vkData ) ;
}
else if ( value = = " extensions " )
{
readExtensions ( child , vkData ) ;
}
else if ( value = = " tags " )
{
readTags ( child , vkData . tags ) ;
}
else if ( value = = " types " )
{
readTypes ( child , vkData ) ;
}
else
{
assert ( ( value = = " feature " ) | | ( value = = " vendorids " ) ) ;
}
2017-03-08 13:14:01 +00:00
}
2016-07-25 18:31:10 +00:00
sortDependencies ( vkData . dependencies ) ;
std : : map < std : : string , std : : string > defaultValues ;
createDefaults ( vkData , defaultValues ) ;
std : : ofstream ofs ( VULKAN_HPP ) ;
2016-07-26 14:28:30 +00:00
ofs < < vkData . vulkanLicenseHeader < < std : : endl
2017-05-16 13:32:14 +00:00
< < 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*/
) " ;
2016-07-25 18:31:10 +00:00
writeVersionCheck ( ofs , vkData . version ) ;
writeTypesafeCheck ( ofs , vkData . typesafeCheck ) ;
ofs < < versionCheckHeader
2017-01-27 14:15:50 +00:00
< < inlineHeader
2017-02-15 16:07:50 +00:00
< < explicitHeader
< < std : : endl
2017-01-27 14:15:50 +00:00
< < " namespace vk " < < std : : endl
< < " { " < < std : : endl
< < flagsHeader
< < optionalClassHeader
< < arrayProxyHeader
< < uniqueHandleHeader ;
2016-07-25 18:31:10 +00:00
// 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 ( ) ) ;
2017-02-08 12:56:06 +00:00
writeTypeEnum ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
writeEnumsToString ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
2017-06-26 13:25:53 +00:00
ofs < < " #ifndef VULKAN_HPP_NO_EXCEPTIONS " ;
2016-07-25 18:31:10 +00:00
ofs < < exceptionHeader ;
2017-04-26 07:30:24 +00:00
ofs < < exceptionClassesHeader ;
writeExceptionsForEnum ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
writeThrowExceptions ( ofs , vkData . enums . find ( it - > name ) - > second ) ;
2017-06-26 13:25:53 +00:00
ofs < < " #endif " < < std : : endl ;
2017-04-26 07:30:24 +00:00
vkData . dependencies . erase ( it ) ;
2016-07-25 18:31:10 +00:00
ofs < < " } // namespace vk " < < std : : endl
< < std : : endl
< < " namespace std " < < std : : endl
< < " { " < < std : : endl
< < " template <> " < < std : : endl
< < " struct is_error_code_enum<vk::Result> : public true_type " < < std : : endl
< < " {}; " < < std : : endl
< < " } " < < std : : endl
< < std : : endl
< < " namespace vk " < < std : : endl
< < " { " < < std : : endl
< < resultValueHeader
< < createResultValueHeader ;
2017-01-27 14:15:50 +00:00
assert ( vkData . deleterTypes . find ( " " ) ! = vkData . deleterTypes . end ( ) ) ;
2016-07-25 18:31:10 +00:00
writeTypes ( ofs , vkData , defaultValues ) ;
2017-04-24 07:30:02 +00:00
// 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 ;
}
}
2016-07-25 18:31:10 +00:00
ofs < < " } // namespace vk " < < std : : endl
< < std : : endl
< < " #endif " < < std : : endl ;
}
2016-07-26 14:09:41 +00:00
catch ( std : : exception const & e )
2016-07-25 18:31:10 +00:00
{
std : : cout < < " caught exception: " < < e . what ( ) < < std : : endl ;
2016-07-26 14:09:41 +00:00
return - 1 ;
2016-07-25 18:31:10 +00:00
}
catch ( . . . )
{
std : : cout < < " caught unknown exception " < < std : : endl ;
2016-07-26 14:09:41 +00:00
return - 1 ;
2016-07-25 18:31:10 +00:00
}
}