From a64aeb648b2e25f859f1bab7407011c80a5e1370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20S=C3=BC=C3=9Fenbach?= Date: Wed, 5 Jun 2024 16:44:13 +0200 Subject: [PATCH] Improved alias handling for enum values and structs; extended error checking commands listed as required in features. (#1889) --- VulkanHppGenerator.cpp | 148 ++++++++++++++++++++++------------------- VulkanHppGenerator.hpp | 62 ++++++++--------- 2 files changed, 112 insertions(+), 98 deletions(-) diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index 04ea5e9..04a3ec6 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -884,14 +884,14 @@ void VulkanHppGenerator::addCommandsToHandle( std::vector const & r { for ( auto const & command : require.commands ) { - auto commandIt = findByNameOrAlias( m_commands, command ); + auto commandIt = findByNameOrAlias( m_commands, command.first ); assert( commandIt != m_commands.end() ); auto handleIt = m_handles.find( commandIt->second.handle ); assert( handleIt != m_handles.end() ); - if ( !handleIt->second.commands.contains( command ) ) + if ( !handleIt->second.commands.contains( command.first ) ) { - handleIt->second.commands.insert( command ); - registerDeleter( command, commandIt->second ); + handleIt->second.commands.insert( command.first ); + registerDeleter( command.first, commandIt->second ); } } } @@ -986,23 +986,23 @@ void VulkanHppGenerator::appendDispatchLoaderDynamicCommands( std::vectorsecond.handle.empty() ) { - initial += generateDispatchLoaderDynamicCommandAssignment( command, commandIt->first, "NULL" ); + initial += generateDispatchLoaderDynamicCommandAssignment( command.first, commandIt->first, "NULL" ); } else { - instance += generateDispatchLoaderDynamicCommandAssignment( command, commandIt->first, "instance" ); + instance += generateDispatchLoaderDynamicCommandAssignment( command.first, commandIt->first, "instance" ); if ( isDeviceCommand( commandIt->second ) ) { - device += generateDispatchLoaderDynamicCommandAssignment( command, commandIt->first, "device" ); + device += generateDispatchLoaderDynamicCommandAssignment( command.first, commandIt->first, "device" ); } } } @@ -1048,26 +1048,26 @@ void VulkanHppGenerator::appendRAIIDispatcherCommands( std::vector { for ( auto const & command : require.commands ) { - if ( listedCommands.insert( command ).second ) + if ( listedCommands.insert( command.first ).second ) { - auto commandIt = findByNameOrAlias( m_commands, command ); + auto commandIt = findByNameOrAlias( m_commands, command.first ); if ( commandIt->second.handle.empty() ) { - ci += ", " + command + "( PFN_" + command + "( getProcAddr( NULL, \"" + command + "\" ) ) )"; + ci += ", " + command.first + "( PFN_" + command.first + "( getProcAddr( NULL, \"" + command.first + "\" ) ) )"; - cm += " PFN_" + command + " " + command + " = 0;\n"; + cm += " PFN_" + command.first + " " + command.first + " = 0;\n"; } else if ( ( commandIt->second.handle == "VkDevice" ) || hasParentHandle( commandIt->second.handle, "VkDevice" ) ) { - da += " " + command + " = PFN_" + command + "( vkGetDeviceProcAddr( device, \"" + command + "\" ) );\n"; + da += " " + command.first + " = PFN_" + command.first + "( vkGetDeviceProcAddr( device, \"" + command.first + "\" ) );\n"; // if this is an alias'ed function, use it as a fallback for the original one - if ( command != commandIt->first ) + if ( command.first != commandIt->first ) { - da += " if ( !" + commandIt->first + " ) " + commandIt->first + " = " + command + ";\n"; + da += " if ( !" + commandIt->first + " ) " + commandIt->first + " = " + command.first + ";\n"; } - dm += " PFN_" + command + " " + command + " = 0;\n"; - dmp += " PFN_dummy " + command + "_placeholder = 0;\n"; + dm += " PFN_" + command.first + " " + command.first + " = 0;\n"; + dmp += " PFN_dummy " + command.first + "_placeholder = 0;\n"; } else { @@ -1075,18 +1075,18 @@ void VulkanHppGenerator::appendRAIIDispatcherCommands( std::vector // filter out vkGetInstanceProcAddr, as starting with Vulkan 1.2 it can resolve itself only (!) with an // instance nullptr ! - if ( command != "vkGetInstanceProcAddr" ) + if ( command.first != "vkGetInstanceProcAddr" ) { - ia += " " + command + " = PFN_" + command + "( vkGetInstanceProcAddr( instance, \"" + command + "\" ) );\n"; + ia += " " + command.first + " = PFN_" + command.first + "( vkGetInstanceProcAddr( instance, \"" + command.first + "\" ) );\n"; // if this is an alias'ed function, use it as a fallback for the original one - if ( command != commandIt->first ) + if ( command.first != commandIt->first ) { - ia += " if ( !" + commandIt->first + " ) " + commandIt->first + " = " + command + ";\n"; + ia += " if ( !" + commandIt->first + " ) " + commandIt->first + " = " + command.first + ";\n"; } } - im += +" PFN_" + command + " " + command + " = 0;\n"; - imp += " PFN_dummy " + command + "_placeholder = 0;\n"; + im += +" PFN_" + command.first + " " + command.first + " = 0;\n"; + imp += " PFN_dummy " + command.first + "_placeholder = 0;\n"; } } } @@ -2139,7 +2139,7 @@ void VulkanHppGenerator::distributeStructAliases() { for ( auto const & alias : m_structsAliases ) { - auto structIt = m_structs.find( alias.second.name ); + auto structIt = findByNameOrAlias( m_structs, alias.second.name ); checkForError( structIt != m_structs.end(), alias.second.xmlLine, "struct alias <" + alias.first + "> references an unknown struct <" + alias.second.name + ">" ); checkForError( structIt->second.aliases.insert( { alias.first, alias.second.xmlLine } ).second, @@ -3305,11 +3305,11 @@ std::string VulkanHppGenerator::generateCommandDefinitions( std::vectorsecond.handle ); + str += generateCommandDefinitions( command.first, commandIt->second.handle ); } } } @@ -6517,9 +6517,9 @@ std::string VulkanHppGenerator::generateDispatchLoaderStaticCommands( std::vecto for ( auto const & command : require.commands ) { // some commands are listed for multiple extensions ! - if ( listedCommands.insert( command ).second ) + if ( listedCommands.insert( command.first ).second ) { - auto commandIt = findByNameOrAlias( m_commands, command ); + auto commandIt = findByNameOrAlias( m_commands, command.first ); assert( commandIt != m_commands.end() ); str += "\n"; @@ -6541,9 +6541,11 @@ std::string VulkanHppGenerator::generateDispatchLoaderStaticCommands( std::vecto } )"; - str += replaceWithMap( - commandTemplate, - { { "commandName", command }, { "parameterList", parameterList }, { "parameters", parameters }, { "returnType", commandIt->second.returnType } } ); + str += replaceWithMap( commandTemplate, + { { "commandName", command.first }, + { "parameterList", parameterList }, + { "parameters", parameters }, + { "returnType", commandIt->second.returnType } } ); } } } @@ -6588,9 +6590,8 @@ std::string VulkanHppGenerator::generateEnum( std::pair c for ( auto const & valueAlias : value.aliases ) { std::string enumName = enumData.first; - if ( !enumData.second.aliases.empty() ) + for ( auto aliasIt = enumData.second.aliases.begin(); ( aliasIt != enumData.second.aliases.end() ) && ( enumName == enumData.first ); ++aliasIt ) { - assert( enumData.second.aliases.size() == 1 ); auto enumAliasIt = enumData.second.aliases.begin(); std::string enumTag = findTag( enumData.first ); std::string aliasTag = findTag( enumAliasIt->first ); @@ -8142,9 +8143,9 @@ std::string VulkanHppGenerator::generateRAIICommandDefinitions( std::vector const & handle, std::set const & specialFunctions ) const { - std::string functionDeclarations; - std::set listedCommands; // some commands are listed with more than one extension ! + std::string functionDeclarations; + std::map> listedCommands; // some commands are listed with more than one extension ! for ( auto const & feature : m_features ) { std::vector firstLevelCommands, secondLevelCommands; @@ -8507,20 +8508,27 @@ std::string VulkanHppGenerator::generateRAIIHandleCommandDeclarations( std::pair { for ( auto const & command : require.commands ) { - if ( !specialFunctions.contains( command ) ) + if ( !specialFunctions.contains( command.first ) ) { - if ( handle.second.commands.contains( command ) ) + if ( handle.second.commands.contains( command.first ) ) { - assert( !listedCommands.contains( command ) ); - listedCommands.insert( command ); - firstLevelCommands.push_back( command ); + assert( !listedCommands.contains( command.first ) ); + listedCommands.insert( { command.first, { feature.name, command.second } } ); + firstLevelCommands.push_back( command.first ); } - else if ( handle.second.secondLevelCommands.contains( command ) ) + else if ( handle.second.secondLevelCommands.contains( command.first ) ) { - assert( !listedCommands.contains( command ) ); - listedCommands.insert( command ); + auto listedIt = listedCommands.find( command.first ); + if ( listedIt != listedCommands.end() ) + { + checkForError( false, + command.second, + "command <" + command.first + "> already listed as required for feature <" + listedIt->second.first + "> on line " + + std::to_string( listedIt->second.second ) ); + } + listedCommands.insert( { command.first, { feature.name, command.second } } ); assert( !handle.first.empty() ); - secondLevelCommands.push_back( command ); + secondLevelCommands.push_back( command.first ); } } } @@ -8547,17 +8555,17 @@ std::string VulkanHppGenerator::generateRAIIHandleCommandDeclarations( std::pair { for ( auto const & command : req.commands ) { - if ( !specialFunctions.contains( command ) && !listedCommands.contains( command ) ) + if ( !specialFunctions.contains( command.first ) && !listedCommands.contains( command.first ) ) { - if ( handle.second.commands.contains( command ) ) + if ( handle.second.commands.contains( command.first ) ) { - listedCommands.insert( command ); - firstLevelCommands.push_back( command ); + listedCommands.insert( { command.first, { extension.name, command.second } } ); + firstLevelCommands.push_back( command.first ); } - else if ( handle.second.secondLevelCommands.contains( command ) ) + else if ( handle.second.secondLevelCommands.contains( command.first ) ) { - listedCommands.insert( command ); - secondLevelCommands.push_back( command ); + listedCommands.insert( { command.first, { extension.name, command.second } } ); + secondLevelCommands.push_back( command.first ); } } } @@ -12347,12 +12355,13 @@ bool VulkanHppGenerator::handleRemovalCommand( std::string const & command, std: bool removed = false; for ( auto requireDataIt = requireData.begin(); !removed && ( requireDataIt != requireData.end() ); ++requireDataIt ) { - auto requireCommandIt = std::find( requireDataIt->commands.begin(), requireDataIt->commands.end(), command ); + auto requireCommandIt = std::find_if( + requireDataIt->commands.begin(), requireDataIt->commands.end(), [&command]( std::pair c ) { return c.first == command; } ); if ( requireCommandIt != requireDataIt->commands.end() ) { assert( std::none_of( std::next( requireCommandIt ), requireDataIt->commands.end(), - [&command]( std::string const & requireCommand ) { return requireCommand == command; } ) ); + [&command]( std::pair const & requireCommand ) { return requireCommand.first == command; } ) ); requireDataIt->commands.erase( requireCommandIt ); assert( !requireDataIt->commands.empty() || !requireDataIt->types.empty() ); removed = true; @@ -12360,8 +12369,9 @@ bool VulkanHppGenerator::handleRemovalCommand( std::string const & command, std: #if !defined( NDEBUG ) for ( auto it = std::next( requireDataIt ); it != requireData.end(); ++it ) { - assert( - std::none_of( it->commands.begin(), it->commands.end(), [&command]( std::string const & requireCommand ) { return requireCommand == command; } ) ); + assert( std::none_of( it->commands.begin(), + it->commands.end(), + [&command]( std::pair const & requireCommand ) { return requireCommand.first == command; } ) ); } #endif } @@ -13116,7 +13126,7 @@ void VulkanHppGenerator::readExtensionRequire( tinyxml2::XMLElement const * elem std::string value = child->Value(); if ( value == "command" ) { - requireData.commands.push_back( readRequireCommand( child, extensionData.name ) ); + requireData.commands.push_back( { readRequireCommand( child, extensionData.name ), child->GetLineNum() } ); } else if ( value == "enum" ) { @@ -13406,7 +13416,7 @@ VulkanHppGenerator::RequireData std::string value = child->Value(); if ( value == "command" ) { - requireData.commands.push_back( readRequireCommand( child, featureName ) ); + requireData.commands.push_back( { readRequireCommand( child, featureName ), child->GetLineNum() } ); } else if ( value == "enum" ) { @@ -13958,7 +13968,7 @@ void VulkanHppGenerator::readRequireEnum( checkForError( typeIt != m_types.end(), line, "enum value <" + name + "> extends unknown type <" + extends + ">" ); checkForError( typeIt->second.category == TypeCategory::Enum, line, "enum value <" + name + "> extends non-enum type <" + extends + ">" ); typeIt->second.requiredBy.insert( requiredBy ); - const auto enumIt = m_enums.find( extends ); + auto enumIt = findByNameOrAlias( m_enums, extends ); assert( enumIt != m_enums.end() ); enumIt->second.addEnumValue( @@ -14977,7 +14987,11 @@ void VulkanHppGenerator::readTypeStruct( tinyxml2::XMLElement const * element, b std::string name = attributes.find( "name" )->second; checkForError( m_types.insert( { name, TypeData{ TypeCategory::Struct, {}, line } } ).second, line, "struct <" + name + "> already specified" ); - checkForError( m_structsAliases.insert( { name, { alias, line } } ).second, line, "struct alias <" + name + "> already listed" ); + checkForError( + std::none_of( m_structsAliases.begin(), m_structsAliases.end(), [&name]( std::pair const & ad ) { return ad.first == name; } ), + line, + "struct alias <" + name + "> already listed" ); + m_structsAliases.push_back( { name, { alias, line } } ); } else { @@ -15281,9 +15295,9 @@ std::vector VulkanHppGenerator::selectCommandsByHandle( std::vector { for ( auto const & command : require.commands ) { - if ( handleCommands.contains( command ) && listedCommands.insert( command ).second ) + if ( handleCommands.contains( command.first ) && listedCommands.insert( command.first ).second ) { - selectedCommands.push_back( command ); + selectedCommands.push_back( command.first ); } } } diff --git a/VulkanHppGenerator.hpp b/VulkanHppGenerator.hpp index 072a98d..c56ce20 100644 --- a/VulkanHppGenerator.hpp +++ b/VulkanHppGenerator.hpp @@ -234,12 +234,12 @@ private: struct RequireData { - std::string depends = {}; - std::vector commands = {}; - std::map enumConstants = {}; - std::vector constants = {}; - std::vector types = {}; - int xmlLine = {}; + std::string depends = {}; + std::vector> commands = {}; + std::map enumConstants = {}; + std::vector constants = {}; + std::vector types = {}; + int xmlLine = {}; }; struct ExtensionData @@ -1035,29 +1035,29 @@ private: std::string toString( TypeCategory category ); private: - std::string m_api; - std::map m_baseTypes; - std::map m_bitmasks; - std::map m_commands; - std::map m_constants; - std::map m_defines; - DefinesPartition m_definesPartition; // partition defined macros into mutually-exclusive sets of callees, callers, and values - std::map m_enums; - std::vector m_extensions; - std::map m_externalTypes; - std::vector m_features; - std::map m_formats; - std::map m_funcPointers; - std::map m_handles; - std::map m_includes; - std::map m_platforms; - std::set m_RAIISpecialFunctions; - std::map m_structs; - std::map m_structsAliases; // temporary storage for aliases, as they might be listed before the actual struct is listed - std::map m_tags; - std::map m_types; - std::set m_unsupportedExtensions; - std::set m_unsupportedFeatures; - std::string m_version; - std::string m_vulkanLicenseHeader; + std::string m_api; + std::map m_baseTypes; + std::map m_bitmasks; + std::map m_commands; + std::map m_constants; + std::map m_defines; + DefinesPartition m_definesPartition; // partition defined macros into mutually-exclusive sets of callees, callers, and values + std::map m_enums; + std::vector m_extensions; + std::map m_externalTypes; + std::vector m_features; + std::map m_formats; + std::map m_funcPointers; + std::map m_handles; + std::map m_includes; + std::map m_platforms; + std::set m_RAIISpecialFunctions; + std::map m_structs; + std::vector> m_structsAliases; // temporary storage for aliases, as they might be listed before the actual struct is listed + std::map m_tags; + std::map m_types; + std::set m_unsupportedExtensions; + std::set m_unsupportedFeatures; + std::string m_version; + std::string m_vulkanLicenseHeader; };