diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index dcb540b..8f4e32c 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -2009,6 +2009,27 @@ std::string VulkanHppGenerator::findBaseName( std::string aliasName, std::map::const_iterator enumIt, + std::string const & name ) const +{ + EnumValueData const * evdPtr = nullptr; + auto evdIt = std::find_if( enumIt->second.values.begin(), enumIt->second.values.end(), [&name]( EnumValueData const & evd ) { return evd.name == name; } ); + if ( evdIt == enumIt->second.values.end() ) + { + evdIt = std::find_if( + enumIt->second.unsupportedValues.begin(), enumIt->second.unsupportedValues.end(), [&name]( EnumValueData const & evd ) { return evd.name == name; } ); + if ( evdIt != enumIt->second.unsupportedValues.end() ) + { + evdPtr = &*evdIt; + } + } + else + { + evdPtr = &*evdIt; + } + return evdPtr; +} + std::vector::const_iterator VulkanHppGenerator::findFeature( std::string const & name ) const { return std::find_if( m_features.begin(), m_features.end(), [&name]( FeatureData const & fd ) { return fd.name == name; } ); @@ -12543,6 +12564,7 @@ void VulkanHppGenerator::readRegistry( tinyxml2::XMLElement const * element ) { "platforms", true }, { "spirvcapabilities", true }, { "spirvextensions", true }, + { "sync", true }, { "tags", true }, { "types", true } } ); for ( auto child : children ) @@ -12588,6 +12610,10 @@ void VulkanHppGenerator::readRegistry( tinyxml2::XMLElement const * element ) { readSPIRVExtensions( child ); } + else if ( value == "sync" ) + { + readSync( child ); + } else if ( value == "tags" ) { readTags( child ); @@ -13111,6 +13137,223 @@ void VulkanHppGenerator::readStructMember( tinyxml2::XMLElement const * element, } } +void VulkanHppGenerator::readSync( tinyxml2::XMLElement const * element ) +{ + int line = element->GetLineNum(); + checkAttributes( line, getAttributes( element ), { { "comment", {} } }, {} ); + std::vector children = getChildElements( element ); + checkElements( line, children, { { "syncaccess", false }, { "syncpipeline", false }, { "syncstage", false } }, {} ); + + auto accessFlagBitsIt = m_enums.find( "VkAccessFlagBits" ); + assert( accessFlagBitsIt != m_enums.end() ); + auto accessFlagBits2It = m_enums.find( "VkAccessFlagBits2" ); + assert( accessFlagBits2It != m_enums.end() ); + auto stageFlagBitsIt = m_enums.find( "VkPipelineStageFlagBits" ); + assert( stageFlagBitsIt != m_enums.end() ); + auto stageFlagBits2It = m_enums.find( "VkPipelineStageFlagBits2" ); + assert( stageFlagBits2It != m_enums.end() ); + + for ( auto child : children ) + { + std::string value = child->Value(); + if ( value == "syncaccess" ) + { + readSyncAccess( child, accessFlagBitsIt, accessFlagBits2It, stageFlagBits2It ); + } + else if ( value == "syncpipeline" ) + { + readSyncPipeline( child ); + } + else + { + assert( value == "syncstage" ); + readSyncStage( child, stageFlagBitsIt, stageFlagBits2It ); + } + } +} + +void VulkanHppGenerator::readSyncAccess( tinyxml2::XMLElement const * element, + std::map::const_iterator accessFlagBitsIt, + std::map::const_iterator accessFlagBits2It, + std::map::const_iterator stageFlagBits2It ) +{ + int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} } }, { { "alias", {} } } ); + std::vector children = getChildElements( element ); + checkElements( line, children, {}, { "comment", "syncequivalent", "syncsupport" } ); + + EnumValueData const * aliasPtr = nullptr; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "alias" ) + { + aliasPtr = findEnumValueData( accessFlagBitsIt, attribute.second ); + checkForError( aliasPtr != nullptr, line, "syncaccess alias <" + attribute.second + "> not specified as a VkAccessFlagBits value!" ); + } + else + { + assert( attribute.first == "name" ); + auto namePtr = findEnumValueData( accessFlagBits2It, attribute.second ); + checkForError( namePtr != nullptr, line, "syncaccess name <" + attribute.second + "> not specified as a VkAccessFlagBits value!" ); + if ( aliasPtr != nullptr ) + { + checkForError( ( aliasPtr->value == namePtr->value ) && ( aliasPtr->bitpos == namePtr->bitpos ), + line, + "syncaccess name <" + attribute.second + "> has an alias <" + aliasPtr->name + "> with a different value or bitpos!" ); + } + } + } + + for ( auto child : children ) + { + std::string value = child->Value(); + if ( value == "syncequivalent" ) + { + readSyncAccessEquivalent( child, accessFlagBits2It ); + } + else if ( value == "syncsupport" ) + { + readSyncAccessSupport( child, stageFlagBits2It ); + } + } +} + +void VulkanHppGenerator::readSyncAccessEquivalent( tinyxml2::XMLElement const * element, std::map::const_iterator accessFlagBits2It ) +{ + int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "access", {} } }, {} ); + checkElements( line, getChildElements( element ), {}, {} ); + + for ( auto const & attribute : attributes ) + { + assert( attribute.first == "access" ); + std::vector access = tokenize( attribute.second, "," ); + for ( auto const & a : access ) + { + checkForError( findEnumValueData( accessFlagBits2It, a ) != nullptr, line, "syncequivalent access uses unknown value <" + a + ">!" ); + } + } +} + +void VulkanHppGenerator::readSyncAccessSupport( tinyxml2::XMLElement const * element, std::map::const_iterator stageFlagBits2It ) +{ + int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "stage", {} } }, {} ); + checkElements( line, getChildElements( element ), {}, {} ); + + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "stage" ) + { + std::vector stage = tokenize( attribute.second, "," ); + for ( auto const & s : stage ) + { + checkForError( findEnumValueData( stageFlagBits2It, s ) != nullptr, line, "syncsupport stage uses unknown value <" + s + ">!" ); + } + } + } +} + +void VulkanHppGenerator::readSyncPipeline( tinyxml2::XMLElement const * element ) +{ + int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} } }, { { "depends", {} } } ); + std::vector children = getChildElements( element ); + checkElements( line, children, { { "syncpipelinestage", false } }, {} ); + + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "depends" ) + { + std::vector depends = tokenize( attribute.second, "," ); + for ( auto const & d : depends ) + { + checkForError( + ( std::find_if( m_extensions.begin(), m_extensions.end(), [&d]( ExtensionData const & ed ) { return ed.name == d; } ) != m_extensions.end() ) || + ( m_unsupportedExtensions.find( d ) != m_unsupportedExtensions.end() ), + line, + "syncpipeline depends on unknown extension <" + d + ">" ); + } + } + } +} + +void VulkanHppGenerator::readSyncStage( tinyxml2::XMLElement const * element, + std::map::const_iterator stageFlagBitsIt, + std::map::const_iterator stageFlagBits2It ) +{ + int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} } }, { { "alias", {} } } ); + std::vector children = getChildElements( element ); + checkElements( line, children, {}, { "syncequivalent", "syncsupport" } ); + + EnumValueData const * aliasPtr = nullptr; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "alias" ) + { + aliasPtr = findEnumValueData( stageFlagBitsIt, attribute.second ); + checkForError( aliasPtr != nullptr, line, "syncstage alias <" + attribute.second + "> not specified as a VkPipelineStageFlagBits value!" ); + } + else + { + assert( attribute.first == "name" ); + auto namePtr = findEnumValueData( stageFlagBits2It, attribute.second ); + checkForError( namePtr != nullptr, line, "syncstage name <" + attribute.second + "> not specified as a VkPipelineStageFlagBits2 value!" ); + if ( aliasPtr != nullptr ) + { + checkForError( ( aliasPtr->value == namePtr->value ) && ( aliasPtr->bitpos == namePtr->bitpos ), + line, + "syncstate name <" + attribute.second + "> has an alias <" + aliasPtr->name + "> with a different value or bitpos!" ); + } + } + } + + for ( auto child : children ) + { + std::string value = child->Value(); + if ( value == "syncequivalent" ) + { + readSyncStageEquivalent( child, stageFlagBits2It ); + } + else + { + assert( value == "syncsupport" ); + readSyncStageSupport( child ); + } + } +} + +void VulkanHppGenerator::readSyncStageEquivalent( tinyxml2::XMLElement const * element, std::map::const_iterator stageFlagBits2It ) +{ + int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "stage", {} } }, {} ); + checkElements( line, getChildElements( element ), {}, {} ); + + for ( auto const & attribute : attributes ) + { + assert( attribute.first == "stage" ); + std::vector stage = tokenize( attribute.second, "," ); + for ( auto const & s : stage ) + { + checkForError( findEnumValueData( stageFlagBits2It, s ) != nullptr, line, "syncequivalent stage uses unknown value <" + s + ">!" ); + } + } +} + +void VulkanHppGenerator::readSyncStageSupport( tinyxml2::XMLElement const * element ) +{ + int line = element->GetLineNum(); + checkAttributes( line, getAttributes( element ), { { "queues", { "compute", "decode", "encode", "graphics", "opticalflow", "transfer" } } }, {} ); + checkElements( line, getChildElements( element ), {}, {} ); +} + void VulkanHppGenerator::readTag( tinyxml2::XMLElement const * element ) { int line = element->GetLineNum(); diff --git a/VulkanHppGenerator.hpp b/VulkanHppGenerator.hpp index 4fc95ae..ff651a2 100644 --- a/VulkanHppGenerator.hpp +++ b/VulkanHppGenerator.hpp @@ -473,6 +473,7 @@ private: void filterLenMembers(); std::map::const_iterator findAlias( std::string const & name, std::map const & aliases ) const; std::string findBaseName( std::string aliasName, std::map const & aliases ) const; + EnumValueData const * findEnumValueData( std::map::const_iterator enumIt, std::string const & name ) const; std::vector::const_iterator findFeature( std::string const & name ) const; std::vector::const_iterator findParamIt( std::string const & name, std::vector const & paramData ) const; std::vector::const_iterator findStructMemberIt( std::string const & name, std::vector const & memberData ) const; @@ -974,6 +975,19 @@ private: void readSPIRVExtensionEnable( tinyxml2::XMLElement const * element ); void readSPIRVExtensions( tinyxml2::XMLElement const * element ); void readStructMember( tinyxml2::XMLElement const * element, std::vector & members, bool isUnion ); + void readSync( tinyxml2::XMLElement const * element ); + void readSyncAccess( tinyxml2::XMLElement const * element, + std::map::const_iterator accessFlagBitsIt, + std::map::const_iterator accessFlagBits2It, + std::map::const_iterator stageFlagBits2It ); + void readSyncAccessEquivalent( tinyxml2::XMLElement const * element, std::map::const_iterator accessFlagBits2It ); + void readSyncAccessSupport( tinyxml2::XMLElement const * element, std::map::const_iterator stageFlagBits2It ); + void readSyncPipeline( tinyxml2::XMLElement const * element ); + void readSyncStage( tinyxml2::XMLElement const * element, + std::map::const_iterator stageFlagBitsIt, + std::map::const_iterator stageFlagBits2It ); + void readSyncStageEquivalent( tinyxml2::XMLElement const * element, std::map::const_iterator stageFlagBits2It ); + void readSyncStageSupport( tinyxml2::XMLElement const * element ); void readTag( tinyxml2::XMLElement const * element ); void readTags( tinyxml2::XMLElement const * element ); void readTypeBasetype( tinyxml2::XMLElement const * element, std::map const & attributes );