Add support for new <feature> tags. (#1953)

This commit is contained in:
Andreas Süßenbach 2024-08-27 13:33:57 +02:00 committed by GitHub
parent 98ea600e1f
commit 0262bef5cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 158 additions and 49 deletions

View File

@ -1196,6 +1196,7 @@ void VulkanHppGenerator::checkCorrectness() const
checkDefineCorrectness(); checkDefineCorrectness();
checkEnumCorrectness(); checkEnumCorrectness();
checkExtensionCorrectness(); checkExtensionCorrectness();
checkFeatureCorrectness();
checkFuncPointerCorrectness(); checkFuncPointerCorrectness();
checkHandleCorrectness(); checkHandleCorrectness();
checkStructCorrectness(); 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 void VulkanHppGenerator::checkFuncPointerCorrectness() const
{ {
for ( auto const & funcPointer : m_funcPointers ) for ( auto const & funcPointer : m_funcPointers )
@ -13516,7 +13534,7 @@ void VulkanHppGenerator::readExtensionRequire( tinyxml2::XMLElement const * elem
std::map<std::string, std::string> attributes = getAttributes( element ); std::map<std::string, std::string> attributes = getAttributes( element );
checkAttributes( line, attributes, {}, { { "api", { "vulkansc" } }, { "comment", {} }, { "depends", {} } } ); checkAttributes( line, attributes, {}, { { "api", { "vulkansc" } }, { "comment", {} }, { "depends", {} } } );
std::vector<tinyxml2::XMLElement const *> children = getChildElements( element ); std::vector<tinyxml2::XMLElement const *> children = getChildElements( element );
checkElements( line, children, {}, { "command", "comment", "enum", "type" } ); checkElements( line, children, {}, { "command", "comment", "enum", "feature", "type" } );
RequireData requireData{ .xmlLine = line }; RequireData requireData{ .xmlLine = line };
std::string api; std::string api;
@ -13550,6 +13568,10 @@ void VulkanHppGenerator::readExtensionRequire( tinyxml2::XMLElement const * elem
{ {
readRequireEnum( child, extensionData.name, extensionData.platform, extensionSupported && requireSupported, requireData ); readRequireEnum( child, extensionData.name, extensionData.platform, extensionSupported && requireSupported, requireData );
} }
else if ( value == "feature" )
{
requireData.features.push_back( readRequireFeature( child ) );
}
else if ( value == "type" ) else if ( value == "type" )
{ {
requireData.types.push_back( readRequireType( child, extensionData.name ) ); requireData.types.push_back( readRequireType( child, extensionData.name ) );
@ -13596,7 +13618,7 @@ void VulkanHppGenerator::readExtension( tinyxml2::XMLElement const * element )
{ "sortorder", { "1" } }, { "sortorder", { "1" } },
{ "specialuse", { "cadsupport", "d3demulation", "debugging", "devtools", "glemulation" } }, { "specialuse", { "cadsupport", "d3demulation", "debugging", "devtools", "glemulation" } },
{ "type", { "device", "instance" } } } ); { "type", { "device", "instance" } } } );
checkElements( line, children, { { "require", false } } ); checkElements( line, children, { { "require", false } }, { "remove" } );
ExtensionData extensionData{ .xmlLine = line }; ExtensionData extensionData{ .xmlLine = line };
for ( auto const & attribute : attributes ) for ( auto const & attribute : attributes )
@ -13707,9 +13729,17 @@ void VulkanHppGenerator::readExtension( tinyxml2::XMLElement const * element )
std::any_of( extensionData.supported.begin(), extensionData.supported.end(), [this]( std::string const & s ) { return s == m_api; } ); std::any_of( extensionData.supported.begin(), extensionData.supported.end(), [this]( std::string const & s ) { return s == m_api; } );
checkForError( !extensionSupported || !extensionData.type.empty(), line, "missing attribute \"type\" for supported extension <" + extensionData.name + ">" ); checkForError( !extensionSupported || !extensionData.type.empty(), line, "missing attribute \"type\" for supported extension <" + extensionData.name + ">" );
for ( auto child : children ) for ( auto child : children )
{
std::string value = child->Value();
if ( value == "remove" )
{
extensionData.removeData.push_back( readRemoveData( child ) );
}
else if ( value == "require" )
{ {
readExtensionRequire( child, extensionData, extensionSupported ); readExtensionRequire( child, extensionData, extensionSupported );
} }
}
if ( std::none_of( extensionData.supported.begin(), extensionData.supported.end(), []( std::string const & s ) { return s == "disabled"; } ) ) 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(); std::string value = child->Value();
if ( value == "remove" ) if ( value == "remove" )
{ {
featureData.removeData.push_back( readFeatureRemove( child ) ); featureData.removeData.push_back( readRemoveData( child ) );
} }
else if ( value == "require" ) 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(); const int line = element->GetLineNum();
checkAttributes( line, getAttributes( element ), {}, { { "comment", {} } } ); std::map<std::string, std::string> attributes = getAttributes( element );
checkAttributes( line, attributes, {}, { { "comment", {} }, { "depends", {} } } );
std::vector<tinyxml2::XMLElement const *> children = getChildElements( element ); std::vector<tinyxml2::XMLElement const *> 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 ) for ( auto child : children )
{ {
std::string value = child->Value(); std::string value = child->Value();
if ( value == "command" ) if ( value == "command" )
{ {
removeData.commands.push_back( readName( child ) ); requireData.commands.push_back( { readRequireCommand( child, featureData.name ), child->GetLineNum() } );
} }
else if ( value == "enum" ) 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" ) 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<tinyxml2::XMLElement const *> 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 ) 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<tinyxml2::XMLElement const *> 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 ) std::string VulkanHppGenerator::readRequireCommand( tinyxml2::XMLElement const * element, std::string const & requiredBy )
{ {
const int line = element->GetLineNum(); 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<std::string, std::string> 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<std::string, AliasData> 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 ) std::string VulkanHppGenerator::readRequireType( tinyxml2::XMLElement const * element, std::string const & requiredBy )
{ {
const int line = element->GetLineNum(); const int line = element->GetLineNum();
@ -15503,6 +15599,7 @@ void VulkanHppGenerator::readTypeStruct( tinyxml2::XMLElement const * element, b
static std::set<std::string> multipleLenStructs = { "VkAccelerationStructureTrianglesDisplacementMicromapNV", static std::set<std::string> multipleLenStructs = { "VkAccelerationStructureTrianglesDisplacementMicromapNV",
"VkImageConstraintsInfoFUCHSIA", "VkImageConstraintsInfoFUCHSIA",
"VkIndirectCommandsLayoutTokenNV", "VkIndirectCommandsLayoutTokenNV",
"VkPipelineBinaryKeysAndDataKHR",
"VkPresentInfoKHR", "VkPresentInfoKHR",
"VkSemaphoreWaitInfo", "VkSemaphoreWaitInfo",
"VkSetDescriptorBufferOffsetsInfoEXT", "VkSetDescriptorBufferOffsetsInfoEXT",

View File

@ -223,10 +223,18 @@ private:
std::map<std::string, DefineData> values = {}; std::map<std::string, DefineData> values = {};
}; };
struct RequireFeature
{
std::string name = {};
std::string structure = {};
int xmlLine = {};
};
struct RemoveData struct RemoveData
{ {
std::vector<std::string> commands = {}; std::vector<std::string> commands = {};
std::vector<std::string> enums = {}; std::vector<std::string> enums = {};
std::vector<RequireFeature> features = {};
std::vector<std::string> types = {}; std::vector<std::string> types = {};
int xmlLine = {}; int xmlLine = {};
}; };
@ -237,6 +245,7 @@ private:
std::vector<std::pair<std::string, int>> commands = {}; std::vector<std::pair<std::string, int>> commands = {};
std::map<std::string, std::string> enumConstants = {}; std::map<std::string, std::string> enumConstants = {};
std::vector<std::string> constants = {}; std::vector<std::string> constants = {};
std::vector<RequireFeature> features = {};
std::vector<std::string> types = {}; std::vector<std::string> types = {};
int xmlLine = {}; int xmlLine = {};
}; };
@ -252,6 +261,7 @@ private:
std::string promotedTo = {}; std::string promotedTo = {};
std::map<std::string, std::vector<std::vector<std::string>>> depends = {}; std::map<std::string, std::vector<std::vector<std::string>>> depends = {};
std::vector<std::string> ratified = {}; std::vector<std::string> ratified = {};
std::vector<RemoveData> removeData = {};
std::vector<RequireData> requireData = {}; std::vector<RequireData> requireData = {};
std::vector<std::string> supported = {}; std::vector<std::string> supported = {};
std::string type = {}; std::string type = {};
@ -484,6 +494,7 @@ private:
std::map<std::string, CommandData>::const_iterator constructorIt, std::map<std::string, CommandData>::const_iterator constructorIt,
std::vector<ParamData>::const_iterator lenIt ) const; std::vector<ParamData>::const_iterator lenIt ) const;
void checkExtensionCorrectness() const; void checkExtensionCorrectness() const;
void checkFeatureCorrectness() const;
void checkFuncPointerCorrectness() const; void checkFuncPointerCorrectness() const;
void checkHandleCorrectness() const; void checkHandleCorrectness() const;
void checkStructCorrectness() const; void checkStructCorrectness() const;
@ -1034,8 +1045,7 @@ private:
void readExtensionRequire( tinyxml2::XMLElement const * element, ExtensionData & extensionData, bool extensionSupported ); void readExtensionRequire( tinyxml2::XMLElement const * element, ExtensionData & extensionData, bool extensionSupported );
void readExtensions( tinyxml2::XMLElement const * element ); void readExtensions( tinyxml2::XMLElement const * element );
void readFeature( tinyxml2::XMLElement const * element ); void readFeature( tinyxml2::XMLElement const * element );
RemoveData readFeatureRemove( tinyxml2::XMLElement const * element ); void readFeatureRequire( tinyxml2::XMLElement const * element, FeatureData & featureData, bool featureSupported );
RequireData readFeatureRequire( tinyxml2::XMLElement const * element, std::string const & featureName, bool featureSupported );
void readFormat( tinyxml2::XMLElement const * element ); void readFormat( tinyxml2::XMLElement const * element );
void readFormatComponent( tinyxml2::XMLElement const * element, FormatData & formatData ); void readFormatComponent( tinyxml2::XMLElement const * element, FormatData & formatData );
void readFormatPlane( 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 readPlatform( tinyxml2::XMLElement const * element );
void readPlatforms( tinyxml2::XMLElement const * element ); void readPlatforms( tinyxml2::XMLElement const * element );
void readRegistry( 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 ); std::string readRequireCommand( tinyxml2::XMLElement const * element, std::string const & requiredBy );
void readRequireEnum( void readRequireEnum(
tinyxml2::XMLElement const * element, std::string const & requiredBy, std::string const & platform, bool supported, RequireData & requireData ); 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 ); std::string readRequireType( tinyxml2::XMLElement const * element, std::string const & requiredBy );
void readSPIRVCapability( tinyxml2::XMLElement const * element ); void readSPIRVCapability( tinyxml2::XMLElement const * element );
void readSPIRVCapabilityEnable( tinyxml2::XMLElement const * element ); void readSPIRVCapabilityEnable( tinyxml2::XMLElement const * element );