mirror of
https://github.com/KhronosGroup/Vulkan-Hpp.git
synced 2024-10-14 16:32:17 +00:00
Add extension macros as constexpr (#1710)
* Initial implementation * Reordered prefixes, added SPEC_VERSION macro - And added using statements to module file * Actually add changes to .hpp and .cppm files * Fixes for extension constexpr macros - renamed some vars - simplified logic and control flow * Grouped by extension name rather than macro guards - And added titles to all extension constexprs * Syntax changes - Removed the structured binding and fixed asserts - Used C++20 functions - Added another assert to check that extension and specversion macros exist * Remove `std::ranges` usage
This commit is contained in:
parent
de5821703f
commit
26664a38a4
@ -23,14 +23,6 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
struct MacroData
|
|
||||||
{
|
|
||||||
std::string deprecatedComment = {};
|
|
||||||
std::string calleeMacro = {};
|
|
||||||
std::vector<std::string> params = {};
|
|
||||||
std::string definition = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
void checkAttributes( int line,
|
void checkAttributes( int line,
|
||||||
std::map<std::string, std::string> const & attributes,
|
std::map<std::string, std::string> const & attributes,
|
||||||
std::map<std::string, std::set<std::string>> const & required,
|
std::map<std::string, std::set<std::string>> const & required,
|
||||||
@ -62,7 +54,7 @@ std::string toString( tinyxml2::XMLError er
|
|||||||
std::string trim( std::string const & input );
|
std::string trim( std::string const & input );
|
||||||
std::string trimEnd( std::string const & input );
|
std::string trimEnd( std::string const & input );
|
||||||
std::string trimStars( std::string const & input );
|
std::string trimStars( std::string const & input );
|
||||||
MacroData parseMacro( std::vector<std::string> const & completeMacro );
|
VulkanHppGenerator::MacroData parseMacro( std::vector<std::string> const & completeMacro );
|
||||||
void writeToFile( std::string const & str, std::string const & fileName );
|
void writeToFile( std::string const & str, std::string const & fileName );
|
||||||
|
|
||||||
const std::set<std::string> specialPointerTypes = { "Display", "IDirectFB", "wl_display", "xcb_connection_t", "_screen_window" };
|
const std::set<std::string> specialPointerTypes = { "Display", "IDirectFB", "wl_display", "xcb_connection_t", "_screen_window" };
|
||||||
@ -4989,6 +4981,96 @@ std::string VulkanHppGenerator::generateConstexprDefines() const
|
|||||||
constexprDefines += callerString;
|
constexprDefines += callerString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extension constexprs
|
||||||
|
auto const extensionConstexprDefinesTemplate = std::string{ R"(
|
||||||
|
//=================================
|
||||||
|
//=== CONSTEXPR EXTENSION NAMEs ===
|
||||||
|
//=================================
|
||||||
|
|
||||||
|
${extensionConstexprs}
|
||||||
|
)" };
|
||||||
|
|
||||||
|
auto extensionConstexprs = std::string{};
|
||||||
|
|
||||||
|
static auto const extensionTemplate = std::string{ R"(${deprecated}VULKAN_HPP_CONSTEXPR_INLINE auto ${var} = ${macro};
|
||||||
|
)" };
|
||||||
|
static auto const deprecatedPrefixTemplate = std::string{ R"(VULKAN_HPP_DEPRECATED( ${message} ) )" };
|
||||||
|
static auto const deprecatedByMessageTemplate = std::string{ R"("The ${extensionName} extension has been deprecated by ${deprecatedBy}.")" };
|
||||||
|
static auto const deprecatedMessageTemplate = std::string{ R"("The ${extensionName} extension has been deprecated.")" };
|
||||||
|
static auto const obsoletedMessageTemplate = std::string{ R"("The ${extensionName} extension has been obsoleted by ${obsoletedBy}.")" };
|
||||||
|
static auto const promotedVersionMessageTemplate = std::string{ R"("The ${extensionName} extension has been promoted to core in version ${promotedTo}." )" };
|
||||||
|
static auto const promotedExtensionMessageTemplate = std::string{ R"("The ${extensionName} extension has been promoted to ${promotedTo}.")" };
|
||||||
|
|
||||||
|
// I really, really wish C++ had discards for structured bindings...
|
||||||
|
for ( auto const & extension : m_extensions )
|
||||||
|
{
|
||||||
|
auto const & requireDatas = extension.requireData;
|
||||||
|
|
||||||
|
// assert that requireDatas has at least one require...
|
||||||
|
// and the first require has at least two enumConstants, which we are going to use
|
||||||
|
assert( requireDatas.size() >= 1 );
|
||||||
|
assert( requireDatas.front().enumConstants.size() >= 2 );
|
||||||
|
auto const & enumConstants = requireDatas.front().enumConstants;
|
||||||
|
|
||||||
|
auto const VENDORPascalCaseStripPrefix = []( std::string const & macro )
|
||||||
|
{
|
||||||
|
auto prefixStripped = stripPrefix( macro, "VK_" );
|
||||||
|
auto const vendor = prefixStripped.substr( 0, prefixStripped.find( '_' ) );
|
||||||
|
return vendor + toCamelCase( stripPrefix( prefixStripped, vendor + "_" ) );
|
||||||
|
};
|
||||||
|
|
||||||
|
// add asserts so we don't get a nullptr exception below
|
||||||
|
auto const & extensionMacroPtr =
|
||||||
|
std::find_if( enumConstants.begin(), enumConstants.end(), []( auto const & keyval ) { return keyval.first.ends_with( "_EXTENSION_NAME" ); } );
|
||||||
|
auto const & specVersionMacroPtr =
|
||||||
|
std::find_if( enumConstants.begin(), enumConstants.end(), []( auto const & keyval ) { return keyval.first.ends_with( "_SPEC_VERSION" ); } );
|
||||||
|
assert( extensionMacroPtr != enumConstants.end());
|
||||||
|
assert( specVersionMacroPtr != enumConstants.end() );
|
||||||
|
|
||||||
|
auto const & extensionMacro = extensionMacroPtr->first;
|
||||||
|
auto const & specVersionMacro = specVersionMacroPtr->first;
|
||||||
|
|
||||||
|
auto const extensionVar = VENDORPascalCaseStripPrefix( extensionMacro );
|
||||||
|
auto const specVersionVar = VENDORPascalCaseStripPrefix( specVersionMacro );
|
||||||
|
|
||||||
|
std::string deprecationMessage;
|
||||||
|
if ( extension.isDeprecated )
|
||||||
|
{
|
||||||
|
assert( extension.obsoletedBy.empty() && extension.promotedTo.empty() );
|
||||||
|
deprecationMessage = extension.deprecatedBy.empty()
|
||||||
|
? replaceWithMap( deprecatedMessageTemplate, { { "extensionName", extension.name } } )
|
||||||
|
: replaceWithMap( deprecatedByMessageTemplate, { { "extensionName", extension.name }, { "deprecatedBy", extension.deprecatedBy } } );
|
||||||
|
}
|
||||||
|
else if ( !extension.obsoletedBy.empty() )
|
||||||
|
{
|
||||||
|
assert( extension.promotedTo.empty() );
|
||||||
|
deprecationMessage = replaceWithMap( obsoletedMessageTemplate, { { "extensionName", extension.name }, { "obsoletedBy", extension.obsoletedBy } } );
|
||||||
|
}
|
||||||
|
else if ( !extension.promotedTo.empty() )
|
||||||
|
{
|
||||||
|
if ( extension.promotedTo.starts_with( "VK_VERSION_" ) )
|
||||||
|
{
|
||||||
|
auto version = stripPrefix( extension.promotedTo, "VK_VERSION_" );
|
||||||
|
std::replace( version.begin(), version.end(), '_', '.' );
|
||||||
|
deprecationMessage = replaceWithMap( promotedVersionMessageTemplate, { { "extensionName", extension.name }, { "promotedTo", version } } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deprecationMessage =
|
||||||
|
replaceWithMap( promotedExtensionMessageTemplate, { { "extensionName", extension.name }, { "promotedTo", extension.promotedTo } } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto const deprecatedPrefix = deprecationMessage.empty() ? "" : replaceWithMap( deprecatedPrefixTemplate, { { "message", deprecationMessage } } );
|
||||||
|
|
||||||
|
auto const thisExtensionConstexprs =
|
||||||
|
replaceWithMap( extensionTemplate, { { "deprecated", deprecatedPrefix }, { "macro", extensionMacro }, { "var", extensionVar } } ) +
|
||||||
|
replaceWithMap( extensionTemplate, { { "deprecated", deprecatedPrefix }, { "macro", specVersionMacro }, { "var", specVersionVar } } );
|
||||||
|
|
||||||
|
extensionConstexprs += addTitleAndProtection( extension.name, thisExtensionConstexprs );
|
||||||
|
}
|
||||||
|
|
||||||
|
constexprDefines += replaceWithMap( extensionConstexprDefinesTemplate, { { "extensionConstexprs", extensionConstexprs } } );
|
||||||
|
|
||||||
return constexprDefines;
|
return constexprDefines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5005,11 +5087,17 @@ std::string VulkanHppGenerator::generateConstexprUsings() const
|
|||||||
|
|
||||||
auto const pascalCasePrefixStrip = []( std::string const & macro ) { return stripPrefix( toCamelCase( macro ), "Vk" ); };
|
auto const pascalCasePrefixStrip = []( std::string const & macro ) { return stripPrefix( toCamelCase( macro ), "Vk" ); };
|
||||||
auto const camelCasePrefixStrip = []( std::string const & macro ) { return startLowerCase( stripPrefix( toCamelCase( macro ), "Vk" ) ); };
|
auto const camelCasePrefixStrip = []( std::string const & macro ) { return startLowerCase( stripPrefix( toCamelCase( macro ), "Vk" ) ); };
|
||||||
|
auto const VENDORCasePrefixStrip = []( std::string const & macro )
|
||||||
|
{
|
||||||
|
auto prefixStripped = stripPrefix( macro, "VK_" );
|
||||||
|
auto const vendor = prefixStripped.substr( 0, prefixStripped.find( '_' ) );
|
||||||
|
return vendor + toCamelCase( stripPrefix( prefixStripped, vendor + "_" ) );
|
||||||
|
};
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
{
|
{
|
||||||
auto const generateConstantsAndProtection =
|
auto const generateConstantsAndProtection =
|
||||||
[&constexprUsingTemplate, this]( std::vector<RequireData> const & requireData, std::string const & title, std::set<std::string> & listedConstants )
|
[&]( std::vector<RequireData> const & requireData, std::string const & title, std::set<std::string> & listedConstants )
|
||||||
{
|
{
|
||||||
auto constants = std::string{};
|
auto constants = std::string{};
|
||||||
for ( auto const & require : requireData )
|
for ( auto const & require : requireData )
|
||||||
@ -5031,6 +5119,15 @@ std::string VulkanHppGenerator::generateConstexprUsings() const
|
|||||||
listedConstants.insert( constant );
|
listedConstants.insert( constant );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( auto const & [key, _] : require.enumConstants )
|
||||||
|
{
|
||||||
|
// keys are the constants themselves. Values are their definitions, and don't need them...
|
||||||
|
// Again, recall these constants are all in the form VK_<vendor>_<name>_EXTENSION_NAME and VK_<vendor>_<name>_SPEC_VERSION
|
||||||
|
// strip the Vk, get the vendor, and PascalCase the rest
|
||||||
|
constants += replaceWithMap( constexprUsingTemplate, { { "constName", VENDORCasePrefixStrip( key ) } } );
|
||||||
|
listedConstants.insert( key );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return addTitleAndProtection( title, constants );
|
return addTitleAndProtection( title, constants );
|
||||||
};
|
};
|
||||||
@ -5075,7 +5172,7 @@ std::string VulkanHppGenerator::generateConstexprUsings() const
|
|||||||
// callers
|
// callers
|
||||||
constexprUsings += R"(
|
constexprUsings += R"(
|
||||||
//==========================
|
//==========================
|
||||||
//=== CONSTEXPR CALLERSs ===
|
//=== CONSTEXPR CALLERs ===
|
||||||
//==========================
|
//==========================
|
||||||
)";
|
)";
|
||||||
for ( auto const & macro : m_definesPartition.callers )
|
for ( auto const & macro : m_definesPartition.callers )
|
||||||
@ -12991,6 +13088,7 @@ void VulkanHppGenerator::readEnumsConstants( tinyxml2::XMLElement const * elemen
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// checkAttributes( line, attributes, { { "name", {} }, { "value", {} } }, { { "type", {} }, { "comment", {} } } );
|
||||||
checkAttributes( line, attributes, { { "name", {} }, { "type", {} }, { "value", {} } }, { { "comment", {} } } );
|
checkAttributes( line, attributes, { { "name", {} }, { "type", {} }, { "value", {} } }, { { "comment", {} } } );
|
||||||
|
|
||||||
std::string alias, name, type, value;
|
std::string alias, name, type, value;
|
||||||
@ -13129,7 +13227,7 @@ void VulkanHppGenerator::readExtensionRequire( tinyxml2::XMLElement const * elem
|
|||||||
requireData.types.push_back( readRequireType( child, extensionData.name ) );
|
requireData.types.push_back( readRequireType( child, extensionData.name ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( requireSupported && ( !requireData.commands.empty() || !requireData.types.empty() ) )
|
if ( requireSupported && ( !requireData.commands.empty() || !requireData.types.empty() || !requireData.enumConstants.empty() ) )
|
||||||
{
|
{
|
||||||
extensionData.requireData.push_back( requireData );
|
extensionData.requireData.push_back( requireData );
|
||||||
}
|
}
|
||||||
@ -13957,6 +14055,11 @@ void VulkanHppGenerator::readRequireEnum(
|
|||||||
m_constants[name] = { type, value, line };
|
m_constants[name] = { type, value, line };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkForError(
|
||||||
|
!supported || name.ends_with( "_EXTENSION_NAME" ) || name.ends_with( "_SPEC_VERSION" ), line, "encountered unexpected enum <" + name + ">" );
|
||||||
|
|
||||||
|
requireData.enumConstants.emplace( name, value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -15480,7 +15583,7 @@ std::vector<std::string> tokenizeAny( std::string const & tokenString, std::stri
|
|||||||
|
|
||||||
// function to take three or four-vector of strings containing a macro definition, and return
|
// function to take three or four-vector of strings containing a macro definition, and return
|
||||||
// a tuple with possibly the deprecation reason, possibly the called macro, the macro parameters, and possibly the definition
|
// a tuple with possibly the deprecation reason, possibly the called macro, the macro parameters, and possibly the definition
|
||||||
MacroData parseMacro( std::vector<std::string> const & completeMacro )
|
VulkanHppGenerator::MacroData parseMacro( std::vector<std::string> const & completeMacro )
|
||||||
{
|
{
|
||||||
// #define macro definition
|
// #define macro definition
|
||||||
// #define macro( params ) definition
|
// #define macro( params ) definition
|
||||||
|
@ -105,6 +105,14 @@ public:
|
|||||||
void prepareRAIIHandles();
|
void prepareRAIIHandles();
|
||||||
void prepareVulkanFuncs();
|
void prepareVulkanFuncs();
|
||||||
|
|
||||||
|
struct MacroData
|
||||||
|
{
|
||||||
|
std::string deprecatedComment = {};
|
||||||
|
std::string calleeMacro = {};
|
||||||
|
std::vector<std::string> params = {};
|
||||||
|
std::string definition = {};
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct AliasData
|
struct AliasData
|
||||||
{
|
{
|
||||||
@ -214,6 +222,7 @@ private:
|
|||||||
{
|
{
|
||||||
std::string depends = {};
|
std::string depends = {};
|
||||||
std::vector<std::string> commands = {};
|
std::vector<std::string> commands = {};
|
||||||
|
std::map<std::string, std::string> enumConstants = {};
|
||||||
std::vector<std::string> constants = {};
|
std::vector<std::string> constants = {};
|
||||||
std::vector<std::string> types = {};
|
std::vector<std::string> types = {};
|
||||||
int xmlLine = {};
|
int xmlLine = {};
|
||||||
|
1445
vulkan/vulkan.cppm
1445
vulkan/vulkan.cppm
File diff suppressed because it is too large
Load Diff
1661
vulkan/vulkan.hpp
1661
vulkan/vulkan.hpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user