Reshape alias handling according to new alias usage in vk.xml. (#167)

This commit is contained in:
Andreas Süßenbach 2018-01-04 10:51:17 +01:00 committed by Markus Tavenrath
parent 15ac21442d
commit c4fcc08e95
3 changed files with 430 additions and 465 deletions

View File

@ -1165,7 +1165,7 @@ void writeVersionCheck(std::ostream & os, std::string const& version)
void skipFeatureRequire(tinyxml2::XMLElement const* element)
{
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), { { "name",{} } }, {});
checkAttributes(attributes, element->GetLineNum(), {}, { { "name",{} } });
checkElements(getChildElements(element), {});
}
@ -1179,7 +1179,7 @@ void skipImplicitExternSyncParams(tinyxml2::XMLElement const* element)
void skipTypeEnum(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes)
{
checkAttributes(attributes, element->GetLineNum(), { { "category",{ "enum" } } }, { { "name",{} } });
checkAttributes(attributes, element->GetLineNum(), { { "category",{ "enum" } } }, { { "alias", {} }, { "name",{} } });
checkElements(getChildElements(element), {});
}
@ -1196,25 +1196,17 @@ void skipTypeInclude(tinyxml2::XMLElement const* element, std::map<std::string,
}
#endif
void VulkanHppGenerator::aliasType(DependencyData::Category category, std::string const& aliasName, std::string const& newName, std::string const& protect)
template <typename T>
void VulkanHppGenerator::checkAlias(std::map<std::string, T> const& data, std::string const& name, int line)
{
auto aliasIt = m_aliases.find(newName);
if (aliasIt == m_aliases.end())
if (data.find(name) == data.end())
{
m_aliases.insert(std::make_pair(newName, AliasData(category, aliasName, protect)));
// we have to add the type to the set of vulkan types to ensure that the require type conversion takes place
m_vkTypes.insert(newName);
std::stringstream ss;
ss << line;
std::string lineNumber = ss.str();
assert(std::find_if(m_dependencies.begin(), m_dependencies.end(), [newName](DependencyData const& dd) {return dd.name == newName; }) == m_dependencies.end());
m_dependencies.push_back(DependencyData(DependencyData::Category::ALIAS, newName));
m_dependencies.back().dependencies.insert(aliasName);
}
else
{
assert(aliasIt->second.protect == protect);
auto dependencyIt = std::find_if(m_dependencies.begin(), m_dependencies.end(), [newName](DependencyData const& dd) {return dd.name == newName; });
assert((dependencyIt != m_dependencies.end()) && (dependencyIt->dependencies.size() == 1) && (dependencyIt->dependencies.find(aliasName) != dependencyIt->dependencies.end()));
assert(false);
throw std::runtime_error("Spec error on line " + lineNumber + ": missing alias <" + name + ">");
}
}
@ -1242,36 +1234,18 @@ std::map<std::string, std::string> VulkanHppGenerator::createDefaults()
assert(defaultValues.find(dependency.name) == defaultValues.end());
switch (dependency.category)
{
case DependencyData::Category::ALIAS:
{
auto aliasIt = m_aliases.find(dependency.name);
switch (aliasIt->second.category)
{
case DependencyData::Category::ENUM:
assert((aliasIt != m_aliases.end()) && (m_enums.find(aliasIt->second.value) != m_enums.end()));
setDefault(dependency.name, defaultValues, m_enums.find(aliasIt->second.value)->second);
break;
case DependencyData::Category::BITMASK:
case DependencyData::Category::HANDLE:
case DependencyData::Category::STRUCT:
case DependencyData::Category::UNION: // just call the default constructor for bitmasks, handles, structs, and unions (which are mapped to classes)
defaultValues[dependency.name] = dependency.name + "()";
break;
default:
assert(false);
break;
}
}
break;
case DependencyData::Category::COMMAND: // commands should never be asked for defaults
break;
case DependencyData::Category::ENUM:
assert(m_enums.find(dependency.name) != m_enums.end());
setDefault(dependency.name, defaultValues, m_enums.find(dependency.name)->second);
break;
case DependencyData::Category::FLAGS:
case DependencyData::Category::HANDLE:
case DependencyData::Category::STRUCT:
case DependencyData::Category::UNION: // just call the default constructor for flags, structs, and structs (which are mapped to classes)
defaultValues[dependency.name] = dependency.name + "()";
break;
case DependencyData::Category::FUNC_POINTER: // func_pointers default to nullptr
defaultValues[dependency.name] = "nullptr";
break;
@ -1579,19 +1553,43 @@ void VulkanHppGenerator::readCommandsCommand(tinyxml2::XMLElement const* element
{
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), {},
{ { "cmdbufferlevel",{ "primary", "secondary" } },
{ { "alias", {} },
{ "cmdbufferlevel",{ "primary", "secondary" } },
{ "comment",{} },
{ "errorcodes",{} },
{ "name", {} },
{ "pipeline",{ "compute", "graphics", "transfer" } },
{ "queues",{ "compute", "graphics", "sparse_binding", "transfer" } },
{ "renderpass",{ "both", "inside", "outside" } },
{ "successcodes",{} }
});
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
assert(!children.empty());
checkElements(children, { "implicitexternsyncparams", "param", "proto" });
CommandData commandData;
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
// for command aliases, create a copy of the aliased command
checkAttributes(attributes, element->GetLineNum(), { { "alias",{} },{ "name",{} } }, {}); // re-check on alias type!
checkElements(children, {});
std::string alias = startLowerCase(strip(aliasIt->second, "vk"));
checkAlias(m_commands, alias, element->GetLineNum());
auto commandsIt = m_commands.find(alias);
assert(commandsIt != m_commands.end());
commandData = commandsIt->second;
commandData.fullName = startLowerCase(strip(attributes.find("name")->second, "vk"));
determineReducedName(commandData);
linkCommandToHandle(commandData);
// add a DependencyData to this name
m_dependencies.push_back(DependencyData(DependencyData::Category::COMMAND, commandData.fullName));
m_dependencies.back().dependencies.insert(alias);
}
else
{
checkElements(children, { "implicitexternsyncparams", "param", "proto" });
// read the success codes
auto successcodesAttribute = attributes.find("successcodes");
@ -1634,6 +1632,7 @@ void VulkanHppGenerator::readCommandsCommand(tinyxml2::XMLElement const* element
determineTemplateParam(commandData);
determineEnhancedReturnType(commandData);
determineSkippedParams(commandData);
}
// insert the commandData into the commands-map,
assert(m_commands.find(commandData.fullName) == m_commands.end());
@ -1848,119 +1847,22 @@ void VulkanHppGenerator::readEnumsEnum(tinyxml2::XMLElement const* element, Enum
void VulkanHppGenerator::readEnumsConstant(tinyxml2::XMLElement const* element)
{
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), { { "name",{} },{ "value",{} } }, { { "comment",{} } });
checkAttributes(attributes, element->GetLineNum(), { { "name",{} } }, { { "alias", {}}, { "comment",{} }, { "value",{} } });
checkElements(getChildElements(element), {});
std::string name = attributes.find("name")->second;
assert(m_constants.find(name) == m_constants.end());
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
checkAttributes(attributes, element->GetLineNum(), { {"alias", {}}, { "name", {}} }, {}); // re-check on alias type
checkAlias(m_constants, aliasIt->second, element->GetLineNum());
m_constants[name] = m_constants.find(aliasIt->second)->second;
}
else
{
checkAttributes(attributes, element->GetLineNum(), { { "name",{} }, { "value", {}} }, { {"comment", {} } }); // re-check on non-alias type
m_constants[name] = attributes.find("value")->second;
}
void VulkanHppGenerator::readExtensionAlias(tinyxml2::XMLElement const* element, std::string const& protect, std::string const& tag)
{
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), { { "name",{} },{ "value",{} } }, {});
checkElements(getChildElements(element), {});
std::string name = attributes.find("name")->second;
std::string value = attributes.find("value")->second;
auto commandsIt = m_commands.find(startLowerCase(strip(value, "vk")));
if (commandsIt != m_commands.end())
{
// the alias is on a command -> add a command with that name
CommandData commandData = commandsIt->second;
commandData.fullName = startLowerCase(strip(name, "vk"));
assert(m_commands.find(commandData.fullName) == m_commands.end());
determineReducedName(commandData);
m_commands.insert(std::make_pair(commandData.fullName, commandData));
linkCommandToHandle(commandData);
// add an empty DependencyData to this name
m_dependencies.push_back(DependencyData(DependencyData::Category::COMMAND, commandData.fullName));
}
else
{
auto constantsIt = m_constants.find(value);
if (constantsIt != m_constants.end())
{
// alias on a constant -> just add it to the set of constants... we're doing nothing with them
auto it = m_constants.find(name);
assert((m_constants.find(name) == m_constants.end()) || (m_constants.find(name)->second == constantsIt->second));
m_constants[name] = constantsIt->second;
}
else
{
std::string strippedValue = strip(value, "Vk");
std::string strippedName = strip(name, "Vk");
auto enumsIt = m_enums.find(strippedValue);
if (enumsIt != m_enums.end())
{
// the alias is on an enum -> set the alias, which will map to a using directive
assert(m_enums.find(strippedName) == m_enums.end());
aliasType(DependencyData::Category::ENUM, enumsIt->first, strippedName, protect);
}
else
{
auto flagsIt = m_flags.find(strippedValue);
if (flagsIt != m_flags.end())
{
// the alias is on a flags -> set the alias, which will map to a using directive
assert(m_flags.find(strippedName) == m_flags.end());
assert(flagsIt->second.alias.empty());
flagsIt->second.alias = strippedName;
// adjust the generated enum name as well, if it's empty (and therefore auto-generated)
std::string enumName = generateEnumNameForFlags(strippedValue);
std::map<std::string, EnumData>::iterator enumsIt = m_enums.find(enumName);
assert(enumsIt != m_enums.end());
if (enumsIt->second.values.empty())
{
aliasType(DependencyData::Category::ENUM, enumsIt->first, generateEnumNameForFlags(flagsIt->second.alias), protect);
}
}
else
{
auto handlesIt = m_handles.find(strippedValue);
if (handlesIt != m_handles.end())
{
assert(m_handles.find(strippedName) == m_handles.end());
assert(handlesIt->second.protect == protect);
assert(handlesIt->second.alias.empty());
handlesIt->second.alias = strippedName;
}
else
{
auto structsIt = m_structs.find(strippedValue);
if (structsIt != m_structs.end())
{
// the alias is on a structure -> set the alias, which will map to a using directive
assert(m_structs.find(strippedName) == m_structs.end());
aliasType(DependencyData::Category::STRUCT, structsIt->first, strippedName, protect);
}
else
{
// final catch: it has to be an enum value
bool found = false;
for (auto & e : m_enums)
{
auto valueIt = std::find_if(e.second.values.begin(), e.second.values.end(), [&value](EnumValueData const& evd) { return evd.value == value; });
if (valueIt != e.second.values.end())
{
assert(std::find_if(e.second.values.begin(), e.second.values.end(), [&name](EnumValueData const& evd) {return evd.value == name; }) == e.second.values.end());
assert(valueIt->alias.empty());
valueIt->alias = createEnumValueName(name, e.second.prefix, e.second.postfix, e.second.bitmask, tag);
found = true;
break;
}
}
assert(found);
}
}
}
}
}
}
}
@ -1983,20 +1885,45 @@ void VulkanHppGenerator::readExtensionCommand(tinyxml2::XMLElement const* elemen
void VulkanHppGenerator::readExtensionEnum(tinyxml2::XMLElement const* element, std::string const& tag)
{
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), { { "name",{} } }, { { "bitpos",{} },{ "comment",{} },{ "dir",{ "-" } },{ "extends",{} },{ "offset",{} },{ "value",{} } });
checkAttributes(attributes, element->GetLineNum(),
{
{ "name", {} }
},
{
{ "alias", {} },
{ "bitpos", {} },
{ "comment", {} },
{ "dir", { "-" } },
{ "extends", {} },
{ "extnumber", {} },
{ "offset", {} },
{ "value", {} }
});
checkElements(getChildElements(element), {});
// TODO process enums which don't extend existing enums
auto extendsAttribute = attributes.find("extends");
if (extendsAttribute != attributes.end())
auto extendsIt = attributes.find("extends");
if (extendsIt != attributes.end())
{
std::string extends = strip(extendsAttribute->second, "Vk");
assert(m_enums.find(extends) != m_enums.end());
assert((attributes.find("bitpos") != attributes.end()) + (attributes.find("offset") != attributes.end()) + (attributes.find("value") != attributes.end()) == 1);
std::string extends = strip(extendsIt->second, "Vk");
auto enumIt = m_enums.find(extends);
assert(enumIt != m_enums.end());
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
checkAttributes(attributes, element->GetLineNum(), { { "alias", {} }, { "extends", {} }, { "name", {} } }, {});
std::string alias = createEnumValueName(aliasIt->second, enumIt->second.prefix, enumIt->second.postfix, enumIt->second.bitmask, tag);
auto evdIt = std::find_if(enumIt->second.values.begin(), enumIt->second.values.end(), [&alias](EnumValueData const& evd) { return evd.name == alias; });
assert(evdIt != enumIt->second.values.end());
evdIt->alias = createEnumValueName(attributes.find("name")->second, enumIt->second.prefix, enumIt->second.postfix, enumIt->second.bitmask, tag);
}
else
{
assert((attributes.find("bitpos") != attributes.end()) + (attributes.find("offset") != attributes.end()) + (attributes.find("value") != attributes.end()) == 1);
enumIt->second.addEnumValue(attributes.find("name")->second, tag, m_nameMap);
}
}
}
void VulkanHppGenerator::readExtensionRequire(tinyxml2::XMLElement const* element, std::string const& protect, std::string const& tag)
@ -2004,17 +1931,13 @@ void VulkanHppGenerator::readExtensionRequire(tinyxml2::XMLElement const* elemen
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), {}, { { "extension",{} },{ "feature",{} } });
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
checkElements(children, { "alias", "command", "comment", "enum", "type" });
checkElements(children, { "command", "comment", "enum", "type" });
for (auto child : children)
{
std::string value = child->Value();
if (value == "alias")
{
readExtensionAlias(child, protect, tag);
}
else if (value == "command")
if (value == "command")
{
readExtensionCommand(child, protect);
}
@ -2060,6 +1983,7 @@ void VulkanHppGenerator::readExtensionsExtension(tinyxml2::XMLElement const* ele
},
{
{ "author",{} },
{ "comment", {} },
{ "contact",{} },
{ "platform",{} },
{ "protect",{} },
@ -2126,28 +2050,28 @@ void VulkanHppGenerator::readExtensionType(tinyxml2::XMLElement const* element,
if (!protect.empty())
{
std::string name = strip(attributes.find("name")->second, "Vk");
std::map<std::string, BitmaskData>::iterator bitmasksIt = m_bitmasks.find(name);
if (bitmasksIt != m_bitmasks.end())
{
bitmasksIt->second.protect = protect;
// if the enum of this flags is auto-generated, protect it as well
std::string enumName = generateEnumNameForFlags(name);
std::map<std::string, EnumData>::iterator enumsIt = m_enums.find(enumName);
assert(enumsIt != m_enums.end());
if (enumsIt->second.values.empty())
{
enumsIt->second.protect = protect;
}
}
else
{
std::map<std::string, EnumData>::iterator eit = m_enums.find(name);
if (eit != m_enums.end())
{
eit->second.protect = protect;
}
else
{
std::map<std::string, FlagData>::iterator fit = m_flags.find(name);
if (fit != m_flags.end())
{
fit->second.protect = protect;
// if the enum of this flags is auto-generated, protect it as well
std::string enumName = generateEnumNameForFlags(name);
std::map<std::string, EnumData>::iterator eit = m_enums.find(enumName);
assert(eit != m_enums.end());
if (eit->second.values.empty())
{
eit->second.protect = protect;
}
}
else
{
std::map<std::string, HandleData>::iterator hait = m_handles.find(name);
if (hait != m_handles.end())
@ -2197,7 +2121,7 @@ void VulkanHppGenerator::readFeatureRequire(tinyxml2::XMLElement const* element)
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), {}, { { "comment",{} } });
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
checkElements(children, { "command", "enum", "type" });
checkElements(children, { "command", "comment", "enum", "type" });
for (auto child : children)
{
@ -2209,7 +2133,7 @@ void VulkanHppGenerator::readFeatureRequire(tinyxml2::XMLElement const* element)
#if !defined(NDEBUG)
else
{
assert((value == "command") || (value == "type"));
assert((value == "command") || (value == "comment") || (value == "type"));
skipFeatureRequire(child);
}
#endif
@ -2219,7 +2143,19 @@ void VulkanHppGenerator::readFeatureRequire(tinyxml2::XMLElement const* element)
void VulkanHppGenerator::readFeatureRequireEnum(tinyxml2::XMLElement const* element)
{
std::map<std::string, std::string> attributes = getAttributes(element);
checkAttributes(attributes, element->GetLineNum(), { { "name",{} } }, { { "bitpos",{} },{ "comment",{} },{ "extends",{} },{ "value",{} } });
checkAttributes(attributes, element->GetLineNum(),
{
{ "name",{} }
},
{
{ "bitpos",{} },
{ "comment",{} },
{ "dir", { "-" } },
{ "extends",{} },
{ "extnumber", {} },
{ "offset", {} },
{ "value",{} }
});
checkElements(getChildElements(element), {});
auto extendsAttribute = attributes.find("extends");
@ -2361,8 +2297,26 @@ void VulkanHppGenerator::readTypeBasetype(tinyxml2::XMLElement const* element, s
void VulkanHppGenerator::readTypeBitmask(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes)
{
checkAttributes(attributes, element->GetLineNum(), { { "category",{ "bitmask" } } }, { { "requires",{} } });
checkAttributes(attributes, element->GetLineNum(), { { "category", { "bitmask" } } }, { { "alias", {} }, { "name", {}}, { "requires", {} } });
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
checkAttributes(attributes, element->GetLineNum(), { { "alias", {} }, { "category", {"bitmask"} }, { "name", {} } }, {}); // re-check on alias type!
checkElements(children, {});
std::string alias = strip(aliasIt->second, "Vk");
checkAlias(m_bitmasks, alias, element->GetLineNum());
std::string name = strip(attributes.find("name")->second, "Vk");
auto bitmasksIt = m_bitmasks.find(alias);
assert((bitmasksIt != m_bitmasks.end()) && bitmasksIt->second.alias.empty());
bitmasksIt->second.alias = name;
}
else
{
checkOrderedElements(children, { "type", "name" });
checkEmptyElement(children[0]);
checkEmptyElement(children[1]);
@ -2387,13 +2341,14 @@ void VulkanHppGenerator::readTypeBitmask(tinyxml2::XMLElement const* element, st
}
// add a DependencyData for the bitmask name, with the required type as its first dependency
m_dependencies.push_back(DependencyData(DependencyData::Category::FLAGS, name));
m_dependencies.push_back(DependencyData(DependencyData::Category::BITMASK, name));
m_dependencies.back().dependencies.insert(requires);
m_flags.insert(std::make_pair(name, FlagData()));
m_bitmasks.insert(std::make_pair(name, BitmaskData()));
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
}
}
void VulkanHppGenerator::readTypeDefine(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes)
@ -2454,8 +2409,26 @@ void VulkanHppGenerator::readTypeFuncpointer(tinyxml2::XMLElement const* element
void VulkanHppGenerator::readTypeHandle(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes)
{
checkAttributes(attributes, element->GetLineNum(), { { "category",{ "handle" } } }, { { "parent",{} } });
checkAttributes(attributes, element->GetLineNum(), { { "category",{ "handle" } } }, { { "alias",{} }, { "name",{} }, { "parent",{} } });
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
checkAttributes(attributes, element->GetLineNum(), { { "alias",{} },{ "category",{ "handle" } },{ "name",{} } }, {}); // re-check on alias type!
checkElements(children, {});
std::string alias = strip(aliasIt->second, "Vk");
checkAlias(m_handles, alias, element->GetLineNum());
std::string name = strip(attributes.find("name")->second, "Vk");
auto handlesIt = m_handles.find(alias);
assert((handlesIt != m_handles.end()) && handlesIt->second.alias.empty());
handlesIt->second.alias = name;
}
else
{
checkOrderedElements(children, { "type", "name" });
checkEmptyElement(children[0]);
checkEmptyElement(children[1]);
@ -2468,10 +2441,12 @@ void VulkanHppGenerator::readTypeHandle(tinyxml2::XMLElement const* element, std
std::string name = strip(children[1]->GetText(), "Vk");
m_dependencies.push_back(DependencyData(DependencyData::Category::HANDLE, name));
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
assert(m_handles.find(name) == m_handles.end());
m_handles[name];
m_handles.insert(std::make_pair(name, HandleData()));
}
}
void VulkanHppGenerator::readTypeName(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes)
@ -2515,6 +2490,7 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
{ "name",{} }
},
{
{ "alias", {} },
{ "comment",{} },
{ "returnedonly",{ "true" } },
{ "structextends",{} }
@ -2522,6 +2498,22 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
checkElements(children, { "comment", "member" });
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
checkAttributes(attributes, element->GetLineNum(), { { "alias", {}}, {"category", {"struct"}}, { "name", {}} }, {}); // re-check on alias type!
std::string alias = strip(aliasIt->second, "Vk");
checkAlias(m_structs, alias, element->GetLineNum());
std::string name = strip(attributes.find("name")->second, "Vk");
auto structsIt = m_structs.find(alias);
assert((structsIt != m_structs.end()) && structsIt->second.alias.empty());
structsIt->second.alias = name;
}
else
{
std::string name = strip(attributes.find("name")->second, "Vk");
m_dependencies.push_back(DependencyData(isUnion ? DependencyData::Category::UNION : DependencyData::Category::STRUCT, name));
@ -2564,6 +2556,7 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
}
}
void VulkanHppGenerator::readTypeStructMember(tinyxml2::XMLElement const* element, StructData & structData)
@ -2723,6 +2716,35 @@ void VulkanHppGenerator::sortDependencies()
m_dependencies.swap(sortedDependencies);
}
void VulkanHppGenerator::writeBitmaskToString(std::ostream & os, std::string const& bitmaskName, EnumData const &enumData)
{
// the helper functions to make strings out of flag values
enterProtect(os, enumData.protect);
os << " VULKAN_HPP_INLINE std::string to_string(" << bitmaskName << (enumData.values.empty() ? ")" : " value)") << std::endl
<< " {" << std::endl;
if (enumData.values.empty())
{
// no flags values in this enum -> return "{}"
os << " return \"{}\";" << std::endl;
}
else
{
os << " if (!value) return \"{}\";" << std::endl
<< " std::string result;" << std::endl;
// 'or' together all the bits in the value
for (auto valuesIt = enumData.values.begin(); valuesIt != enumData.values.end(); ++valuesIt)
{
os << " if (value & " << enumData.name << "::" << valuesIt->name << ") result += \"" << valuesIt->name.substr(1) << " | \";" << std::endl;
}
// cut off the last three characters from the result (being " | ")
os << " return \"{\" + result.substr(0, result.size() - 3) + \"}\";" << std::endl;
}
os << " }" << std::endl;
leaveProtect(os, enumData.protect);
os << std::endl;
}
void VulkanHppGenerator::writeCall(std::ostream & os, CommandData const& commandData, bool firstCall, bool singular)
{
// get the parameter indices of the counter for vector parameters
@ -3155,35 +3177,6 @@ void VulkanHppGenerator::writeExceptionsForEnum(std::ostream & os, EnumData cons
os << std::endl;
}
void VulkanHppGenerator::writeFlagsToString(std::ostream & os, std::string const& flagsName, EnumData const &enumData)
{
// the helper functions to make strings out of flag values
enterProtect(os, enumData.protect);
os << " VULKAN_HPP_INLINE std::string to_string(" << flagsName << (enumData.values.empty() ? ")" : " value)") << std::endl
<< " {" << std::endl;
if (enumData.values.empty())
{
// no flags values in this enum -> return "{}"
os << " return \"{}\";" << std::endl;
}
else
{
os << " if (!value) return \"{}\";" << std::endl
<< " std::string result;" << std::endl;
// 'or' together all the bits in the value
for (auto valuesIt = enumData.values.begin(); valuesIt != enumData.values.end(); ++valuesIt)
{
os << " if (value & " << enumData.name << "::" << valuesIt->name << ") result += \"" << valuesIt->name.substr(1) << " | \";" << std::endl;
}
// cut off the last three characters from the result (being " | ")
os << " return \"{\" + result.substr(0, result.size() - 3) + \"}\";" << std::endl;
}
os << " }" << std::endl;
leaveProtect(os, enumData.protect);
os << std::endl;
}
void VulkanHppGenerator::writeFunction(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique, bool isStructureChain)
{
if (enhanced && (!singular || isStructureChain))
@ -3739,11 +3732,11 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsEnhanced(std::ostream & os,
if (withDefaults && (lastArgument == i))
{
// check if the very last argument is a flag without any bits -> provide some empty default for it
std::map<std::string, FlagData>::const_iterator flagIt = m_flags.find(commandData.params[i].pureType);
if (flagIt != m_flags.end())
std::map<std::string, BitmaskData>::const_iterator bitmasksIt = m_bitmasks.find(commandData.params[i].pureType);
if (bitmasksIt != m_bitmasks.end())
{
// get the enum corresponding to this flag, to check if it's empty
std::list<DependencyData>::const_iterator depIt = std::find_if(m_dependencies.begin(), m_dependencies.end(), [&flagIt](DependencyData const& dd) { return(dd.name == flagIt->first); });
std::list<DependencyData>::const_iterator depIt = std::find_if(m_dependencies.begin(), m_dependencies.end(), [&bitmasksIt](DependencyData const& dd) { return(dd.name == bitmasksIt->first); });
assert((depIt != m_dependencies.end()) && (depIt->dependencies.size() == 1));
std::map<std::string, EnumData>::const_iterator enumIt = m_enums.find(*depIt->dependencies.begin());
assert(enumIt != m_enums.end());
@ -4136,9 +4129,6 @@ void VulkanHppGenerator::writeStructureChainValidation(std::ostream & os, Depend
// write out allowed structure chains
for (auto extendName : it->second.structExtends)
{
// We do not have to generate the templates for aliased structs;
if (m_aliases.find(extendName) == m_aliases.end())
{
std::map<std::string, StructData>::const_iterator itExtend = m_structs.find(extendName);
assert(itExtend != m_structs.end());
@ -4148,7 +4138,6 @@ void VulkanHppGenerator::writeStructureChainValidation(std::ostream & os, Depend
leaveProtect(os, itExtend->second.protect);
}
}
leaveProtect(os, it->second.protect);
}
}
@ -4187,27 +4176,65 @@ void VulkanHppGenerator::writeToStringFunctions(std::ostream & os)
{
switch (it->category)
{
case DependencyData::Category::BITMASK:
writeBitmaskToString(os, it->name, m_enums.find(*it->dependencies.begin())->second);
break;
case DependencyData::Category::ENUM:
assert(m_enums.find(it->name) != m_enums.end());
writeEnumsToString(os, m_enums.find(it->name)->second);
break;
case DependencyData::Category::FLAGS:
writeFlagsToString(os, it->name, m_enums.find(*it->dependencies.begin())->second);
break;
}
}
}
void VulkanHppGenerator::writeTypeAlias(std::ostream & os, DependencyData const& dependencyData)
void VulkanHppGenerator::writeTypeBitmask(std::ostream & os, std::string const& bitmaskName, BitmaskData const& bitmaskData, EnumData const& enumData)
{
auto aliasIt = m_aliases.find(dependencyData.name);
assert(aliasIt != m_aliases.end());
assert(((aliasIt->second.category == DependencyData::Category::ENUM) && (m_enums.find(aliasIt->second.value) != m_enums.end()))
|| ((aliasIt->second.category == DependencyData::Category::STRUCT) && (m_structs.find(aliasIt->second.value) != m_structs.end())));
enterProtect(os, bitmaskData.protect);
enterProtect(os, aliasIt->second.protect);
os << " using " << aliasIt->first << " = " << aliasIt->second.value << ";" << std::endl;
leaveProtect(os, aliasIt->second.protect);
// each Flags class is using on the class 'Flags' with the corresponding FlagBits enum as the template parameter
os << " using " << bitmaskName << " = Flags<" << enumData.name << ", Vk" << bitmaskName << ">;" << std::endl;
std::stringstream allFlags;
for (size_t i = 0; i < enumData.values.size(); i++)
{
if (i != 0)
{
allFlags << " | ";
}
allFlags << "VkFlags(" << enumData.name << "::" << enumData.values[i].name << ")";
}
if (!enumData.values.empty())
{
const std::string templateString = R"(
VULKAN_HPP_INLINE ${bitmaskName} operator|( ${enumName} bit0, ${enumName} bit1 )
{
return ${bitmaskName}( bit0 ) | bit1;
}
VULKAN_HPP_INLINE ${bitmaskName} operator~( ${enumName} bits )
{
return ~( ${bitmaskName}( bits ) );
}
template <> struct FlagTraits<${enumName}>
{
enum
{
allFlags = ${allFlags}
};
};
)";
os << replaceWithMap(templateString, { { "bitmaskName", bitmaskName },{ "enumName", enumData.name },{ "allFlags", allFlags.str() } });
}
if (!bitmaskData.alias.empty())
{
os << std::endl
<< " using " << bitmaskData.alias << " = " << bitmaskName << ";" << std::endl;
}
leaveProtect(os, bitmaskData.protect);
os << std::endl;
}
@ -4281,6 +4308,7 @@ void VulkanHppGenerator::writeTypeCommand(std::ostream & os, std::string const&
// and write one or both of them
writeStandardOrEnhanced(os, standard.str(), enhanced.str());
leaveProtect(os, commandData.protect);
os << std::endl;
}
@ -4311,56 +4339,6 @@ void VulkanHppGenerator::writeTypeEnum(std::ostream & os, EnumData const& enumDa
os << std::endl;
}
void VulkanHppGenerator::writeTypeFlags(std::ostream & os, std::string const& flagsName, FlagData const& flagData, EnumData const& enumData)
{
enterProtect(os, flagData.protect);
// each Flags class is using on the class 'Flags' with the corresponding FlagBits enum as the template parameter
os << " using " << flagsName << " = Flags<" << enumData.name << ", Vk" << flagsName << ">;" << std::endl;
std::stringstream allFlags;
for (size_t i = 0; i < enumData.values.size(); i++)
{
if (i != 0)
{
allFlags << " | ";
}
allFlags << "VkFlags(" << enumData.name << "::" << enumData.values[i].name << ")";
}
if (!enumData.values.empty())
{
const std::string templateString = R"(
VULKAN_HPP_INLINE ${flagsName} operator|( ${enumName} bit0, ${enumName} bit1 )
{
return ${flagsName}( bit0 ) | bit1;
}
VULKAN_HPP_INLINE ${flagsName} operator~( ${enumName} bits )
{
return ~( ${flagsName}( bits ) );
}
template <> struct FlagTraits<${enumName}>
{
enum
{
allFlags = ${allFlags}
};
};
)";
os << replaceWithMap(templateString, { { "flagsName", flagsName },{ "enumName", enumData.name },{ "allFlags", allFlags.str() } });
}
if (!flagData.alias.empty())
{
os << std::endl
<< " using " << flagData.alias << " = " << flagsName << ";" << std::endl;
}
leaveProtect(os, flagData.protect);
os << std::endl;
}
void VulkanHppGenerator::writeTypeHandle(std::ostream & os, DependencyData const& dependencyData, HandleData const& handleData)
{
enterProtect(os, handleData.protect);
@ -4471,12 +4449,6 @@ ${commands}
{ "commands", commands.str() }
});
if (!handleData.alias.empty())
{
os << " using " << handleData.alias << " = " << dependencyData.name << ";" << std::endl
<< std::endl;
}
// then the actual Deleter classes can be listed
deleterTypesIt = m_deleterTypes.find(dependencyData.name);
if (deleterTypesIt != m_deleterTypes.end())
@ -4495,6 +4467,12 @@ ${commands}
writeTypeCommand(os, " ", cit->second, true);
}
if (!handleData.alias.empty())
{
os << " using " << handleData.alias << " = " << dependencyData.name << ";" << std::endl
<< std::endl;
}
leaveProtect(os, handleData.protect);
}
@ -4506,8 +4484,9 @@ void VulkanHppGenerator::writeTypes(std::ostream & os, std::map<std::string, std
{
switch (it->category)
{
case DependencyData::Category::ALIAS:
writeTypeAlias(os, *it);
case DependencyData::Category::BITMASK:
assert(m_bitmasks.find(it->name) != m_bitmasks.end());
writeTypeBitmask(os, it->name, m_bitmasks.find(it->name)->second, m_enums.find(generateEnumNameForFlags(it->name))->second);
break;
case DependencyData::Category::COMMAND:
writeTypeCommand(os, *it);
@ -4516,10 +4495,6 @@ void VulkanHppGenerator::writeTypes(std::ostream & os, std::map<std::string, std
assert(m_enums.find(it->name) != m_enums.end());
writeTypeEnum(os, m_enums.find(it->name)->second);
break;
case DependencyData::Category::FLAGS:
assert(m_flags.find(it->name) != m_flags.end());
writeTypeFlags(os, it->name, m_flags.find(it->name)->second, m_enums.find(generateEnumNameForFlags(it->name))->second);
break;
case DependencyData::Category::FUNC_POINTER:
case DependencyData::Category::REQUIRED:
// skip FUNC_POINTER and REQUIRED, they just needed to be in the dependencies list to resolve dependencies
@ -4636,6 +4611,12 @@ void VulkanHppGenerator::writeTypeStruct(std::ostream & os, DependencyData const
os << " };" << std::endl
<< " static_assert( sizeof( " << dependencyData.name << " ) == sizeof( Vk" << dependencyData.name << " ), \"struct and wrapper have different size!\" );" << std::endl;
if (!it->second.alias.empty())
{
os << std::endl
<< " using " << it->second.alias << " = " << dependencyData.name << ";" << std::endl;
}
leaveProtect(os, it->second.protect);
os << std::endl;
}

View File

@ -27,7 +27,7 @@ class VulkanHppGenerator
public:
VulkanHppGenerator()
{
m_handles[""]; // insert the default "handle" without class (for createInstance, and such)
m_handles.insert(std::make_pair("", HandleData())); // insert the default "handle" without class (for createInstance, and such)
}
std::map<std::string, std::string> createDefaults();
@ -52,14 +52,19 @@ class VulkanHppGenerator
#endif
private:
struct BitmaskData
{
std::string protect;
std::string alias;
};
struct DependencyData
{
enum class Category
{
ALIAS,
BITMASK,
COMMAND,
ENUM,
FLAGS,
FUNC_POINTER,
HANDLE,
REQUIRED,
@ -79,19 +84,6 @@ class VulkanHppGenerator
std::set<std::string> forwardDependencies;
};
struct AliasData
{
AliasData(DependencyData::Category c, std::string const& v, std::string const& p)
: category(c)
, value(v)
, protect(p)
{}
DependencyData::Category category;
std::string value;
std::string protect;
};
struct ParamData
{
std::string type;
@ -155,12 +147,6 @@ class VulkanHppGenerator
bool bitmask;
};
struct FlagData
{
std::string protect;
std::string alias;
};
struct HandleData
{
std::vector<std::string> commands;
@ -193,6 +179,7 @@ class VulkanHppGenerator
std::vector<MemberData> members;
std::string protect;
std::vector<std::string> structExtends;
std::string alias;
};
#if !defined(NDEBUG)
@ -211,7 +198,7 @@ class VulkanHppGenerator
#endif
private:
void aliasType(DependencyData::Category category, std::string const& aliasName, std::string const& newName, std::string const& protect);
template <typename T> void checkAlias(std::map<std::string, T> const& data, std::string const& name, int line);
bool containsUnion(std::string const& type, std::map<std::string, StructData> const& structs);
void determineEnhancedReturnType(CommandData & commandData);
void determineReducedName(CommandData & commandData);
@ -228,7 +215,6 @@ class VulkanHppGenerator
void readDisabledExtensionRequire(tinyxml2::XMLElement const* element);
void readEnumsEnum(tinyxml2::XMLElement const* element, EnumData & enumData, std::string const& tag);
void readEnumsConstant(tinyxml2::XMLElement const* element);
void readExtensionAlias(tinyxml2::XMLElement const* element, std::string const& protect, std::string const& tag);
void readExtensionCommand(tinyxml2::XMLElement const* element, std::string const& protect);
void readExtensionEnum(tinyxml2::XMLElement const* element, std::string const& tag);
void readExtensionRequire(tinyxml2::XMLElement const* element, std::string const& protect, std::string const& tag);
@ -248,6 +234,7 @@ class VulkanHppGenerator
void readTypeStructMember(tinyxml2::XMLElement const* element, StructData & structData);
void registerDeleter(CommandData const& commandData);
void setDefault(std::string const& name, std::map<std::string, std::string> & defaultValues, EnumData const& enumData);
void writeBitmaskToString(std::ostream & os, std::string const& flagsName, EnumData const &enumData);
void writeCall(std::ostream & os, CommandData const& commandData, bool firstCall, bool singular);
void writeCallCountParameter(std::ostream & os, CommandData const& commandData, bool singular, std::map<size_t, size_t>::const_iterator it);
void writeCallPlainTypeParameter(std::ostream & os, ParamData const& paramData);
@ -257,7 +244,6 @@ class VulkanHppGenerator
void writeDeleterClasses(std::ostream & os, std::pair<std::string, std::set<std::string>> const& deleterTypes);
void writeDeleterForwardDeclarations(std::ostream &os, std::pair<std::string, std::set<std::string>> const& deleterTypes);
void writeExceptionsForEnum(std::ostream & os, EnumData const& enumData);
void writeFlagsToString(std::ostream & os, std::string const& flagsName, EnumData const &enumData);
void writeFunction(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique, bool isStructureChain);
void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool singular, bool isStructureChain);
void writeFunctionBodyEnhanced(std::ostream & os, std::string const& templateString, std::string const& indentation, CommandData const& commandData, bool singular);
@ -282,11 +268,10 @@ class VulkanHppGenerator
void writeStructSetter(std::ostream & os, std::string const& structureName, MemberData const& memberData);
void writeStructureChainValidation(std::ostream & os, DependencyData const& dependencyData);
void writeThrowExceptions(std::ostream& os, EnumData const& enumData);
void writeTypeAlias(std::ostream & os, DependencyData const& dependencyData);
void writeTypeBitmask(std::ostream & os, std::string const& flagsName, BitmaskData const& bitmaskData, EnumData const& enumData);
void writeTypeCommand(std::ostream & os, DependencyData const& dependencyData);
void writeTypeCommand(std::ostream &os, std::string const& indentation, CommandData const& commandData, bool definition);
void writeTypeEnum(std::ostream & os, EnumData const& enumData);
void writeTypeFlags(std::ostream & os, std::string const& flagsName, FlagData const& flagData, EnumData const& enumData);
void writeTypeHandle(std::ostream & os, DependencyData const& dependencyData, HandleData const& handle);
void writeTypeScalar(std::ostream & os, DependencyData const& dependencyData);
void writeTypeStruct(std::ostream & os, DependencyData const& dependencyData, std::map<std::string, std::string> const& defaultValues);
@ -296,7 +281,7 @@ class VulkanHppGenerator
#endif
private:
std::map<std::string, AliasData> m_aliases;
std::map<std::string, BitmaskData> m_bitmasks;
std::map<std::string, CommandData> m_commands;
std::map<std::string, std::string> m_constants;
std::set<std::string> m_defines;
@ -305,7 +290,6 @@ class VulkanHppGenerator
std::list<DependencyData> m_dependencies;
std::map<std::string, EnumData> m_enums;
std::set<std::string> m_extendedStructs; // structs which are referenced by the structextends tag
std::map<std::string, FlagData> m_flags;
std::map<std::string, HandleData> m_handles;
std::map<std::string, std::string> m_nameMap;
std::map<std::string, ScalarData> m_scalars;