From 0262bef5cd8deb647e75f4ac7c8e5943827a96f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20S=C3=BC=C3=9Fenbach?= Date: Tue, 27 Aug 2024 13:33:57 +0200 Subject: [PATCH] Add support for new tags. (#1953) --- VulkanHppGenerator.cpp | 183 +++++++++++++++++++++++++++++++---------- VulkanHppGenerator.hpp | 24 ++++-- 2 files changed, 158 insertions(+), 49 deletions(-) diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index 088f804..beeab2c 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -1196,6 +1196,7 @@ void VulkanHppGenerator::checkCorrectness() const checkDefineCorrectness(); checkEnumCorrectness(); checkExtensionCorrectness(); + checkFeatureCorrectness(); checkFuncPointerCorrectness(); checkHandleCorrectness(); checkStructCorrectness(); @@ -1394,6 +1395,23 @@ void VulkanHppGenerator::checkExtensionCorrectness() const } } +void VulkanHppGenerator::checkFeatureCorrectness() const +{ + // check that each require depends actually is an extension + // remove this check temporarily ! + //for ( auto const & feature : m_features ) + //{ + // for ( auto const & require : feature.requireData ) + // { + // checkForError( + // require.depends.empty() || + // std::any_of( m_extensions.begin(), m_extensions.end(), [&depends = require.depends]( ExtensionData const & ed ) { return ed.name == depends; } ), + // require.xmlLine, + // "feature <" + feature.name + "> depends on an unknown extension <" + require.depends + ">" ); + // } + //} +} + void VulkanHppGenerator::checkFuncPointerCorrectness() const { for ( auto const & funcPointer : m_funcPointers ) @@ -13516,7 +13534,7 @@ void VulkanHppGenerator::readExtensionRequire( tinyxml2::XMLElement const * elem std::map attributes = getAttributes( element ); checkAttributes( line, attributes, {}, { { "api", { "vulkansc" } }, { "comment", {} }, { "depends", {} } } ); std::vector children = getChildElements( element ); - checkElements( line, children, {}, { "command", "comment", "enum", "type" } ); + checkElements( line, children, {}, { "command", "comment", "enum", "feature", "type" } ); RequireData requireData{ .xmlLine = line }; std::string api; @@ -13550,6 +13568,10 @@ void VulkanHppGenerator::readExtensionRequire( tinyxml2::XMLElement const * elem { readRequireEnum( child, extensionData.name, extensionData.platform, extensionSupported && requireSupported, requireData ); } + else if ( value == "feature" ) + { + requireData.features.push_back( readRequireFeature( child ) ); + } else if ( value == "type" ) { requireData.types.push_back( readRequireType( child, extensionData.name ) ); @@ -13596,7 +13618,7 @@ void VulkanHppGenerator::readExtension( tinyxml2::XMLElement const * element ) { "sortorder", { "1" } }, { "specialuse", { "cadsupport", "d3demulation", "debugging", "devtools", "glemulation" } }, { "type", { "device", "instance" } } } ); - checkElements( line, children, { { "require", false } } ); + checkElements( line, children, { { "require", false } }, { "remove" } ); ExtensionData extensionData{ .xmlLine = line }; for ( auto const & attribute : attributes ) @@ -13708,7 +13730,15 @@ void VulkanHppGenerator::readExtension( tinyxml2::XMLElement const * element ) checkForError( !extensionSupported || !extensionData.type.empty(), line, "missing attribute \"type\" for supported extension <" + extensionData.name + ">" ); for ( auto child : children ) { - readExtensionRequire( child, extensionData, extensionSupported ); + std::string value = child->Value(); + if ( value == "remove" ) + { + extensionData.removeData.push_back( readRemoveData( child ) ); + } + else if ( value == "require" ) + { + readExtensionRequire( child, extensionData, extensionSupported ); + } } if ( std::none_of( extensionData.supported.begin(), extensionData.supported.end(), []( std::string const & s ) { return s == "disabled"; } ) ) @@ -13768,11 +13798,11 @@ void VulkanHppGenerator::readFeature( tinyxml2::XMLElement const * element ) std::string value = child->Value(); if ( value == "remove" ) { - featureData.removeData.push_back( readFeatureRemove( child ) ); + featureData.removeData.push_back( readRemoveData( child ) ); } else if ( value == "require" ) { - featureData.requireData.push_back( readFeatureRequire( child, featureData.name, featureSupported ) ); + readFeatureRequire( child, featureData, featureSupported ); } } @@ -13792,60 +13822,53 @@ void VulkanHppGenerator::readFeature( tinyxml2::XMLElement const * element ) } } -VulkanHppGenerator::RemoveData VulkanHppGenerator::readFeatureRemove( tinyxml2::XMLElement const * element ) +void VulkanHppGenerator::readFeatureRequire( tinyxml2::XMLElement const * element, FeatureData & featureData, bool featureSupported ) { - const int line = element->GetLineNum(); - checkAttributes( line, getAttributes( element ), {}, { { "comment", {} } } ); + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, {}, { { "comment", {} }, { "depends", {} } } ); std::vector children = getChildElements( element ); - checkElements( line, children, {}, { "command", "enum", "type" } ); + checkElements( line, children, {}, { "command", "comment", "enum", "feature", "type" } ); + + std::string depends; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "depends" ) + { + assert( depends.empty() ); + depends = attribute.second; + checkForError( + std::none_of( featureData.requireData.begin(), featureData.requireData.end(), [&depends]( RequireData const & rd ) { return rd.depends == depends; } ), + line, + "require depends <" + depends + "> already listed for feature <" + featureData.name + ">" ); + } + } + + featureData.requireData.push_back( {} ); + RequireData & requireData = featureData.requireData.back(); + requireData.depends = depends; + requireData.xmlLine = line; - RemoveData removeData; - removeData.xmlLine = line; for ( auto child : children ) { std::string value = child->Value(); if ( value == "command" ) { - removeData.commands.push_back( readName( child ) ); + requireData.commands.push_back( { readRequireCommand( child, featureData.name ), child->GetLineNum() } ); } else if ( value == "enum" ) { - removeData.enums.push_back( readName( child ) ); + readRequireEnum( child, featureData.name, "", featureSupported, requireData ); + } + else if ( value == "feature" ) + { + requireData.features.push_back( readRequireFeature( child ) ); } else if ( value == "type" ) { - removeData.types.push_back( readName( child ) ); + requireData.types.push_back( readRequireType( child, featureData.name ) ); } } - return removeData; -} - -VulkanHppGenerator::RequireData - VulkanHppGenerator::readFeatureRequire( tinyxml2::XMLElement const * element, std::string const & featureName, bool featureSupported ) -{ - const int line = element->GetLineNum(); - checkAttributes( line, getAttributes( element ), {}, { { "comment", {} } } ); - std::vector children = getChildElements( element ); - checkElements( line, children, {}, { "command", "comment", "enum", "type" } ); - - RequireData requireData{ .xmlLine = line }; - for ( auto child : children ) - { - std::string value = child->Value(); - if ( value == "command" ) - { - requireData.commands.push_back( { readRequireCommand( child, featureName ), child->GetLineNum() } ); - } - else if ( value == "enum" ) - { - readRequireEnum( child, featureName, "", featureSupported, requireData ); - } - else if ( value == "type" ) - { - requireData.types.push_back( readRequireType( child, featureName ) ); - } - } - return requireData; } void VulkanHppGenerator::readFormat( tinyxml2::XMLElement const * element ) @@ -14222,6 +14245,38 @@ void VulkanHppGenerator::readRegistry( tinyxml2::XMLElement const * element ) } } +VulkanHppGenerator::RemoveData VulkanHppGenerator::readRemoveData( tinyxml2::XMLElement const * element ) +{ + const int line = element->GetLineNum(); + checkAttributes( line, getAttributes( element ), {}, { { "comment", {} }, { "reasonlink", {} } } ); + std::vector children = getChildElements( element ); + checkElements( line, children, {}, { "command", "enum", "feature", "type" } ); + + RemoveData removeData; + removeData.xmlLine = line; + for ( auto child : children ) + { + std::string value = child->Value(); + if ( value == "command" ) + { + removeData.commands.push_back( readName( child ) ); + } + else if ( value == "enum" ) + { + removeData.enums.push_back( readName( child ) ); + } + else if ( value == "feature" ) + { + removeData.features.push_back( readRequireFeature( child ) ); + } + else if ( value == "type" ) + { + removeData.types.push_back( readName( child ) ); + } + } + return removeData; +} + std::string VulkanHppGenerator::readRequireCommand( tinyxml2::XMLElement const * element, std::string const & requiredBy ) { const int line = element->GetLineNum(); @@ -14402,6 +14457,47 @@ void VulkanHppGenerator::readRequireEnum( } } +VulkanHppGenerator::RequireFeature VulkanHppGenerator::readRequireFeature( tinyxml2::XMLElement const * element ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} }, { "struct", {} } }, {} ); + checkElements( line, getChildElements( element ), {} ); + + std::string name, structure; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "name" ) + { + name = attribute.second; + } + else if ( attribute.first == "struct" ) + { + structure = attribute.second; + } + } + assert( !name.empty() && !structure.empty() ); + + auto structIt = m_structs.find( structure ); + if ( structIt == m_structs.end() ) + { + auto aliasIt = std::find_if( + m_structsAliases.begin(), m_structsAliases.end(), [&structure]( std::pair const & ad ) { return ad.first == structure; } ); + checkForError( aliasIt != m_structsAliases.end(), line, "encountered unknown required feature struct <" + structure + ">" ); + structIt = m_structs.find( aliasIt->second.name ); + assert( structIt != m_structs.end() ); + } + auto memberIt = + std::find_if( structIt->second.members.begin(), structIt->second.members.end(), [&name]( MemberData const & md ) { return md.name == name; } ); + checkForWarning( + memberIt != structIt->second.members.end(), line, "required feature name <" + name + "> not part of the required feature struct <" + structure + ">" ); + checkForError( ( memberIt == structIt->second.members.end() ) || ( memberIt->type.isValue() && ( memberIt->type.type == "VkBool32" ) ), + line, + "required feature name <" + name + "> is not a VkBool32 member of the required feature struct <" + structure + ">" ); + + return { name, structure, line }; +} + std::string VulkanHppGenerator::readRequireType( tinyxml2::XMLElement const * element, std::string const & requiredBy ) { const int line = element->GetLineNum(); @@ -15503,6 +15599,7 @@ void VulkanHppGenerator::readTypeStruct( tinyxml2::XMLElement const * element, b static std::set multipleLenStructs = { "VkAccelerationStructureTrianglesDisplacementMicromapNV", "VkImageConstraintsInfoFUCHSIA", "VkIndirectCommandsLayoutTokenNV", + "VkPipelineBinaryKeysAndDataKHR", "VkPresentInfoKHR", "VkSemaphoreWaitInfo", "VkSetDescriptorBufferOffsetsInfoEXT", diff --git a/VulkanHppGenerator.hpp b/VulkanHppGenerator.hpp index 7e36c68..c8de96e 100644 --- a/VulkanHppGenerator.hpp +++ b/VulkanHppGenerator.hpp @@ -223,12 +223,20 @@ private: std::map values = {}; }; + struct RequireFeature + { + std::string name = {}; + std::string structure = {}; + int xmlLine = {}; + }; + struct RemoveData { - std::vector commands = {}; - std::vector enums = {}; - std::vector types = {}; - int xmlLine = {}; + std::vector commands = {}; + std::vector enums = {}; + std::vector features = {}; + std::vector types = {}; + int xmlLine = {}; }; struct RequireData @@ -237,6 +245,7 @@ private: std::vector> commands = {}; std::map enumConstants = {}; std::vector constants = {}; + std::vector features = {}; std::vector types = {}; int xmlLine = {}; }; @@ -252,6 +261,7 @@ private: std::string promotedTo = {}; std::map>> depends = {}; std::vector ratified = {}; + std::vector removeData = {}; std::vector requireData = {}; std::vector supported = {}; std::string type = {}; @@ -484,6 +494,7 @@ private: std::map::const_iterator constructorIt, std::vector::const_iterator lenIt ) const; void checkExtensionCorrectness() const; + void checkFeatureCorrectness() const; void checkFuncPointerCorrectness() const; void checkHandleCorrectness() const; void checkStructCorrectness() const; @@ -1034,8 +1045,7 @@ private: void readExtensionRequire( tinyxml2::XMLElement const * element, ExtensionData & extensionData, bool extensionSupported ); void readExtensions( tinyxml2::XMLElement const * element ); void readFeature( tinyxml2::XMLElement const * element ); - RemoveData readFeatureRemove( tinyxml2::XMLElement const * element ); - RequireData readFeatureRequire( tinyxml2::XMLElement const * element, std::string const & featureName, bool featureSupported ); + void readFeatureRequire( tinyxml2::XMLElement const * element, FeatureData & featureData, bool featureSupported ); void readFormat( tinyxml2::XMLElement const * element ); void readFormatComponent( tinyxml2::XMLElement const * element, FormatData & formatData ); void readFormatPlane( tinyxml2::XMLElement const * element, FormatData & formatData ); @@ -1046,9 +1056,11 @@ private: void readPlatform( tinyxml2::XMLElement const * element ); void readPlatforms( tinyxml2::XMLElement const * element ); void readRegistry( tinyxml2::XMLElement const * element ); + RemoveData readRemoveData( tinyxml2::XMLElement const * element ); std::string readRequireCommand( tinyxml2::XMLElement const * element, std::string const & requiredBy ); void readRequireEnum( tinyxml2::XMLElement const * element, std::string const & requiredBy, std::string const & platform, bool supported, RequireData & requireData ); + RequireFeature readRequireFeature( tinyxml2::XMLElement const * element ); std::string readRequireType( tinyxml2::XMLElement const * element, std::string const & requiredBy ); void readSPIRVCapability( tinyxml2::XMLElement const * element ); void readSPIRVCapabilityEnable( tinyxml2::XMLElement const * element );