diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index 906972d..132a2a9 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -8148,7 +8148,7 @@ std::string VulkanHppGenerator::generateIndexTypeTraits( std::pair encountered" ); std::string::size_type pos = type.find_first_of( "0123456789" ); assert( pos != std::string::npos ); - std::string::size_type end = type.find_first_not_of( "0123456789", pos ); + std::string::size_type end = type.find_first_not_of( "0123456789", pos ); std::string::size_type count = ( end != std::string::npos ) ? ( end - pos ) : end; std::string valueName = generateEnumValueName( "VkIndexType", value.name, false ); @@ -14225,7 +14225,8 @@ void VulkanHppGenerator::readRegistry( tinyxml2::XMLElement const * element ) { "spirvextensions", true }, { "sync", true }, { "tags", true }, - { "types", true } } ); + { "types", true } }, + { "videocodecs" } ); // make this optional for now, make it required around October 2024 for ( auto child : children ) { const std::string value = child->Value(); @@ -14284,6 +14285,10 @@ void VulkanHppGenerator::readRegistry( tinyxml2::XMLElement const * element ) readTypes( child ); markExtendedStructs(); } + else if ( value == "videocodecs" ) + { + readVideoCodecs( child ); + } } } @@ -15700,6 +15705,279 @@ TypeInfo VulkanHppGenerator::readTypeInfo( tinyxml2::XMLElement const * element return typeInfo; } +void VulkanHppGenerator::readVideoCapabilities( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "struct", {} } }, {} ); + checkElements( line, getChildElements( element ), {} ); + + videoCodec.capabilities = attributes.find( "struct" )->second; + checkForError( m_structs.contains( videoCodec.capabilities ), + line, + "videocodec <" + videoCodec.name + "> lists unknown capabilities struct <" + videoCodec.capabilities + ">" ); +} + +void VulkanHppGenerator::readVideoCodec( tinyxml2::XMLElement const * element ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} } }, { { "extend", {} }, { "value", {} } } ); + + std::vector children = getChildElements( element ); + checkElements( line, children, { { "videocapabilities", true } }, { "videoformat", "videoprofiles" } ); + + VideoCodec videoCodec; + videoCodec.xmlLine = line; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "extend" ) + { + videoCodec.extend = attribute.second; + } + else if ( attribute.first == "name" ) + { + videoCodec.name = attribute.second; + } + else if ( attribute.first == "value" ) + { + videoCodec.value = attribute.second; + } + } + + checkForError( findByName( m_videoCodecs, videoCodec.name ) == m_videoCodecs.end(), line, "Video Codec <" + videoCodec.name + "> already listed" ); + checkForError( videoCodec.extend.empty() || findByName( m_videoCodecs, videoCodec.extend ) != m_videoCodecs.end(), + line, + "Video Codec <" + videoCodec.name + "> extends unknown <" + videoCodec.extend + ">" ); + if ( !videoCodec.value.empty() ) + { + auto enumIt = m_enums.find( "VkVideoCodecOperationFlagBitsKHR" ); + assert( enumIt != m_enums.end() ); + checkForError( findByName( enumIt->second.values, videoCodec.value ) != enumIt->second.values.end(), + line, + "Video Codec <" + videoCodec.name + "> lists unknown value <" + videoCodec.value + ">" ); + } + + for ( auto child : children ) + { + std::string value = child->Value(); + if ( value == "videocapabilities" ) + { + readVideoCapabilities( child, videoCodec ); + } + else if ( value == "videoformat" ) + { + readVideoFormat( child, videoCodec ); + } + else if ( value == "videoprofiles" ) + { + readVideoProfiles( child, videoCodec ); + } + } + + m_videoCodecs.push_back( videoCodec ); +} + +void VulkanHppGenerator::readVideoCodecs( tinyxml2::XMLElement const * element ) +{ + const int line = element->GetLineNum(); + checkAttributes( line, getAttributes( element ), {}, {} ); + std::vector children = getChildElements( element ); + checkElements( line, children, { { "videocodec", false } } ); + + for ( auto child : children ) + { + std::string value = child->Value(); + assert( value == "videocodec" ); + readVideoCodec( child ); + } +} + +void VulkanHppGenerator::readVideoFormat( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} }, { "usage", {} } }, {} ); + + std::vector children = getChildElements( element ); + checkElements( line, children, {}, { "videorequirecapabilities" } ); + + auto flagBitsIt = m_enums.find( "VkImageUsageFlagBits" ); + assert( flagBitsIt != m_enums.end() ); + + VideoFormat format; + format.xmlLine = line; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "name" ) + { + format.name = attribute.second; + checkForError( findByName( videoCodec.formats, format.name ) == videoCodec.formats.end(), + line, + "Video Format <" + format.name + "> has already been listed for Video Codec <" + videoCodec.name + ">" ); + } + else if ( attribute.first == "usage" ) + { + format.usage = tokenize( attribute.second, "+" ); + for ( auto const & usage : format.usage ) + { + checkForError( findByName( flagBitsIt->second.values, usage ) != flagBitsIt->second.values.end(), + line, + "Unknown Video Format <" + format.name + "> listed for Video Codec <" + videoCodec.name + ">" ); + } + } + } + videoCodec.formats.push_back( format ); + + for ( auto child : children ) + { + std::string value = child->Value(); + assert( value == "videorequirecapabilities" ); + readVideoRequireCapabilities( child, videoCodec ); + } +} + +void VulkanHppGenerator::readVideoProfileMember( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} } }, {} ); + + std::vector children = getChildElements( element ); + checkElements( line, children, {}, { "videoprofile" } ); + + VideoProfileMember profileMember; + profileMember.xmlLine = line; + profileMember.name = attributes.find( "name" )->second; + + checkForError( findByName( videoCodec.profiles.back().members, profileMember.name ) == videoCodec.profiles.back().members.end(), + line, + "Video Profile Member <" + profileMember.name + "> already listed for Video Profiles <" + videoCodec.profiles.back().name ); + + videoCodec.profiles.back().members.push_back( profileMember ); + + for ( auto child : children ) + { + std::string value = child->Value(); + assert( value == "videoprofile" ); + readVideoProfile( child, videoCodec ); + } +} + +void VulkanHppGenerator::readVideoProfile( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "name", {} }, { "value", {} } }, {} ); + checkElements( line, getChildElements( element ), {}, {} ); + + VideoProfile profile; + profile.xmlLine = line; + + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "name" ) + { + profile.name = attribute.second; + } + else if ( attribute.first == "value" ) + { + profile.value = attribute.second; + } + } + + checkForError( findByName( videoCodec.profiles.back().members.back().profiles, profile.name ) == videoCodec.profiles.back().members.back().profiles.end(), + line, + "Video Profile <" + profile.name + "> already listed for VideoProfileMember <" + videoCodec.profiles.back().members.back().name ); + + // value checking would need cross-loading of video.xml !! + + videoCodec.profiles.back().members.back().profiles.push_back( profile ); +} + +void VulkanHppGenerator::readVideoProfiles( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "struct", {} } }, {} ); + + std::vector children = getChildElements( element ); + checkElements( line, children, {}, { "videoprofilemember" } ); + + VideoProfiles profiles; + profiles.xmlLine = line; + profiles.name = attributes.find( "struct" )->second; + + checkForError( findByName( videoCodec.profiles, profiles.name ) == videoCodec.profiles.end(), + line, + "Video Profiles struct <" + profiles.name + "> already listed for Video Codec <" + videoCodec.name + ">" ); + checkForError( m_structs.find( profiles.name ) != m_structs.end(), + line, + "Unknown Video Profiles struct <" + profiles.name + "> used with VideoCodec <" + videoCodec.name + ">" ); + + videoCodec.profiles.push_back( profiles ); + + for ( auto child : children ) + { + std::string value = child->Value(); + assert( value == "videoprofilemember" ); + readVideoProfileMember( child, videoCodec ); + } +} + +void VulkanHppGenerator::readVideoRequireCapabilities( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ) +{ + const int line = element->GetLineNum(); + std::map attributes = getAttributes( element ); + checkAttributes( line, attributes, { { "member", {} }, { "struct", {} }, { "value", {} } }, {} ); + checkElements( line, getChildElements( element ), {} ); + + VideoRequireCapabilities requireCapabilities; + requireCapabilities.xmlLine = line; + for ( auto const & attribute : attributes ) + { + if ( attribute.first == "member" ) + { + requireCapabilities.member = attribute.second; + } + else if ( attribute.first == "struct" ) + { + requireCapabilities.name = attribute.second; + } + else if ( attribute.first == "value" ) + { + requireCapabilities.value = attribute.second; + } + } + + VideoFormat & format = videoCodec.formats.back(); + + auto structIt = m_structs.find( requireCapabilities.name ); + checkForError( structIt != m_structs.end(), + line, + "Unknown Video Require Capablities struct <" + requireCapabilities.name + "> listed for Video Format <" + format.name + "> in VideoCodec <" + + videoCodec.name + ">" ); + + auto memberIt = findByName( structIt->second.members, requireCapabilities.member ); + checkForError( memberIt != structIt->second.members.end(), + line, + "Unknown member <" + requireCapabilities.member + "> used for Video Require Capabilities struct <" + requireCapabilities.name + + "> in VideoFormat <" + format.name + "> in VideoCodec <" + videoCodec.name + ">" ); + + auto bitmaskIt = m_bitmasks.find( memberIt->type.type ); + checkForError( bitmaskIt != m_bitmasks.end(), line, "Video Require Capabilities member <" + requireCapabilities.member + "> is not a bitmask" ); + + auto enumIt = m_enums.find( bitmaskIt->second.require ); + assert( enumIt != m_enums.end() ); + + checkForError( findByName( enumIt->second.values, requireCapabilities.value ) != enumIt->second.values.end(), + line, + "Unknown value <" + requireCapabilities.value + "> listed for Video Require Capabilities <" + requireCapabilities.name + "> in Video Codec <" + + videoCodec.name + ">" ); + + format.requireCapabilities.push_back( requireCapabilities ); +} + void VulkanHppGenerator::registerDeleter( std::string const & commandName, CommandData const & commandData ) { // some special handling for release functions that don't release an object diff --git a/VulkanHppGenerator.hpp b/VulkanHppGenerator.hpp index 90b07d4..fb5c130 100644 --- a/VulkanHppGenerator.hpp +++ b/VulkanHppGenerator.hpp @@ -200,9 +200,9 @@ private: struct ConstantData { - std::string type = {}; - std::string value = {}; - int xmlLine = {}; + std::string type = {}; + std::string value = {}; + int xmlLine = {}; }; struct DefineData @@ -387,6 +387,54 @@ private: bool byStructure = false; }; + struct VideoRequireCapabilities + { + int xmlLine = {}; + std::string name; + std::string member; + std::string value; + }; + + struct VideoFormat + { + int xmlLine = {}; + std::string name; + std::vector usage; + std::vector requireCapabilities; + }; + + struct VideoProfile + { + int xmlLine = {}; + std::string name; + std::string value; + }; + + struct VideoProfileMember + { + int xmlLine = {}; + std::string name; + std::vector profiles; + }; + + struct VideoProfiles + { + int xmlLine = {}; + std::string name; + std::vector members; + }; + + struct VideoCodec + { + int xmlLine = {}; + std::string name; + std::string capabilities; + std::string extend; + std::string value; + std::vector formats; + std::vector profiles; + }; + struct MacroVisitor final : tinyxml2::XMLVisitor { // comments, then name, then parameters and definition together, because that's how they appear in the xml! @@ -1035,6 +1083,14 @@ private: void readTypes( tinyxml2::XMLElement const * element ); void readTypesType( tinyxml2::XMLElement const * element ); TypeInfo readTypeInfo( tinyxml2::XMLElement const * element ) const; + void readVideoCapabilities( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ); + void readVideoCodec( tinyxml2::XMLElement const * element ); + void readVideoCodecs( tinyxml2::XMLElement const * element ); + void readVideoFormat( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ); + void readVideoProfileMember( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ); + void readVideoProfile( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ); + void readVideoProfiles( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ); + void readVideoRequireCapabilities( tinyxml2::XMLElement const * element, VideoCodec & videoCodec ); void registerDeleter( std::string const & commandName, CommandData const & commandData ); void rescheduleRAIIHandle( std::string & str, std::pair const & handle, @@ -1073,5 +1129,6 @@ private: std::set m_unsupportedExtensions; std::set m_unsupportedFeatures; std::string m_version; + std::vector m_videoCodecs; std::string m_vulkanLicenseHeader; };