Added a couple of features: (#480)

+ support for 2D arrays
+ support for bitfield members in a structure (slightly restricted: no default member initializers and for any vk::*FlagBits member Vk*FlagBits would be used)
+ aliases to enums are listed by using declarations
+ for aliases to handle types, an aliased Unique handle type is added by a using declaration
+ a check in determining an enhanced return type is extended
This commit is contained in:
Andreas Süßenbach 2020-01-13 15:00:59 +01:00 committed by Markus Tavenrath
parent 979af1b46e
commit 65450515ee
3 changed files with 2242 additions and 1987 deletions

View File

@ -35,6 +35,8 @@ void checkElements(std::vector<tinyxml2::XMLElement const*> const& elements, std
void checkEmptyElement(tinyxml2::XMLElement const* element); void checkEmptyElement(tinyxml2::XMLElement const* element);
void checkOrderedElements(std::vector<tinyxml2::XMLElement const*> const& elements, std::vector<std::string> const& values); void checkOrderedElements(std::vector<tinyxml2::XMLElement const*> const& elements, std::vector<std::string> const& values);
void cleanup(std::stringstream & ss); void cleanup(std::stringstream & ss);
std::string constructArraySize(std::vector<std::string> const& sizes);
std::string constructStandardArray(std::string const& type, std::vector<std::string> const& sizes);
std::string createEnumValueName(std::string const& name, std::string const& prefix, std::string const& postfix, bool bitmask, std::string const& tag); std::string createEnumValueName(std::string const& name, std::string const& prefix, std::string const& postfix, bool bitmask, std::string const& tag);
std::string determineCommandName(std::string const& vulkanCommandName, std::string const& firstArgumentType); std::string determineCommandName(std::string const& vulkanCommandName, std::string const& firstArgumentType);
std::set<size_t> determineSkippedParams(size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices); std::set<size_t> determineSkippedParams(size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices);
@ -45,7 +47,7 @@ std::map<std::string, std::string> getAttributes(tinyxml2::XMLElement const* ele
std::vector<tinyxml2::XMLElement const*> getChildElements(tinyxml2::XMLElement const* element); std::vector<tinyxml2::XMLElement const*> getChildElements(tinyxml2::XMLElement const* element);
std::string getEnumPostfix(std::string const& name, std::set<std::string> const& tags, std::string & prefix); std::string getEnumPostfix(std::string const& name, std::set<std::string> const& tags, std::string & prefix);
std::string getEnumPrefix(std::string const& name, bool bitmask); std::string getEnumPrefix(std::string const& name, bool bitmask);
std::string readArraySize(tinyxml2::XMLNode const* node); std::pair<std::vector<std::string>, std::string> readModifier(tinyxml2::XMLNode const* node);
void readStructStructExtends(std::map<std::string, std::string> const& attributes, std::vector<std::string> & structExtends, std::set<std::string> & extendedStructs); void readStructStructExtends(std::map<std::string, std::string> const& attributes, std::vector<std::string> & structExtends, std::set<std::string> & extendedStructs);
std::string readTypePostfix(tinyxml2::XMLNode const* node); std::string readTypePostfix(tinyxml2::XMLNode const* node);
std::string readTypePrefix(tinyxml2::XMLNode const* node); std::string readTypePrefix(tinyxml2::XMLNode const* node);
@ -263,6 +265,36 @@ void cleanup(std::string &str)
} }
} }
std::string constructArraySize(std::vector<std::string> const& sizes)
{
std::string arraySize;
for (auto const& s : sizes)
{
arraySize += s + " * ";
}
return arraySize.substr(0, arraySize.length() - 3);
}
std::string constructCArraySizes(std::vector<std::string> const& sizes)
{
std::string arraySizes;
for (auto const& s : sizes)
{
arraySizes += "[" + s + "]";
}
return arraySizes;
}
std::string constructStandardArray(std::string const& type, std::vector<std::string> const& sizes)
{
std::string arrayString = "std::array<" + type + "," + sizes.back() + ">";
for (size_t i = sizes.size() - 2; i < sizes.size(); i--)
{
arrayString = "std::array<" + arrayString + "," + sizes[i] + ">";
}
return arrayString;
}
std::string createEnumValueName(std::string const& name, std::string const& prefix, std::string const& postfix, bool bitmask, std::string const& tag) std::string createEnumValueName(std::string const& name, std::string const& prefix, std::string const& postfix, bool bitmask, std::string const& tag)
{ {
std::string result = "e" + toCamelCase(stripPostfix(stripPrefix(name, prefix), postfix)); std::string result = "e" + toCamelCase(stripPostfix(stripPrefix(name, prefix), postfix));
@ -441,19 +473,36 @@ std::string extractTag(std::string const& name, std::set<std::string> const& tag
return tag; return tag;
} }
std::string readArraySize(tinyxml2::XMLNode const* node) std::pair<std::vector<std::string>, std::string> readModifiers(tinyxml2::XMLNode const* node)
{ {
std::vector<std::string> arraySizes;
std::string bitCount;
if (node && node->ToText()) if (node && node->ToText())
{ {
// following the name there might be some array size // following the name there might be some array size
assert(!node->ToElement()); assert(!node->ToElement());
std::string arraySize = node->Value(); std::string value = node->Value();
if ((arraySize.front() == '[') && (arraySize.back() == ']')) assert(!value.empty());
if (value[0] == '[')
{ {
return arraySize.substr(1, arraySize.length() - 2); std::string::size_type endPos = 0;
while (endPos + 1 != value.length())
{
std::string::size_type startPos = value.find('[', endPos);
assert(startPos != std::string::npos);
endPos = value.find(']', startPos);
assert(endPos != std::string::npos);
assert(startPos + 2 <= endPos);
arraySizes.push_back(value.substr(startPos + 1, endPos - startPos - 1));
}
}
else
{
assert(value[0] == ':');
bitCount = value.substr(1);
} }
} }
return ""; return std::make_pair(arraySizes, bitCount);;
} }
void readStructStructExtends(std::map<std::string, std::string> const& attributes, std::vector<std::string> & structExtends, std::set<std::string> & extendedStructs) void readStructStructExtends(std::map<std::string, std::string> const& attributes, std::vector<std::string> & structExtends, std::set<std::string> & extendedStructs)
@ -802,21 +851,20 @@ void VulkanHppGenerator::appendBitmasks(std::string & str) const
{ {
for (auto const& bitmask : m_bitmasks) for (auto const& bitmask : m_bitmasks)
{ {
auto bitmaskBits = m_bitmaskBits.find(bitmask.second.requirement); auto bitmaskBits = m_enums.find(bitmask.second.requirement);
if (bitmaskBits == m_bitmaskBits.end()) bool hasBits = (bitmaskBits != m_enums.end());
if (!bitmask.second.requirement.empty() && !hasBits)
{ {
throw std::runtime_error( bitmask.first + " references the undefined requirement '" + bitmask.second.requirement + "'"); throw std::runtime_error(bitmask.first + " references the undefined requirement '" + bitmask.second.requirement + "'");
} }
std::string strippedBitmaskName = stripPrefix(bitmask.first, "Vk"); std::string strippedBitmaskName = stripPrefix(bitmask.first, "Vk");
std::string strippedEnumName = stripPrefix(bitmaskBits->first, "Vk"); std::string strippedEnumName = hasBits ? stripPrefix(bitmaskBits->first, "Vk") : "";
str += "\n"; str += "\n";
appendPlatformEnter(str, bitmask.second.platform); appendPlatformEnter(str, bitmask.second.platform);
appendEnum(str, *bitmaskBits); appendBitmask(str, strippedBitmaskName, bitmask.second.alias, strippedEnumName, hasBits ? bitmaskBits->second.values : std::vector<EnumValueData>());
appendEnumToString(str, *bitmaskBits); appendBitmaskToStringFunction(str, strippedBitmaskName, strippedEnumName, hasBits ? bitmaskBits->second.values : std::vector<EnumValueData>());
appendBitmask(str, strippedBitmaskName, bitmask.second.alias, strippedEnumName, bitmaskBits->second.values);
appendBitmaskToStringFunction(str, strippedBitmaskName, strippedEnumName, bitmaskBits->second.values);
appendPlatformLeave(str, bitmask.second.platform); appendPlatformLeave(str, bitmask.second.platform);
} }
} }
@ -824,8 +872,32 @@ void VulkanHppGenerator::appendBitmasks(std::string & str) const
void VulkanHppGenerator::appendBitmask(std::string & str, std::string const& bitmaskName, std::string const& bitmaskAlias, std::string const& enumName, std::vector<EnumValueData> const& enumValues) const void VulkanHppGenerator::appendBitmask(std::string & str, std::string const& bitmaskName, std::string const& bitmaskAlias, std::string const& enumName, std::vector<EnumValueData> const& enumValues) const
{ {
// each Flags class is using the class 'Flags' with the corresponding FlagBits enum as the template parameter // each Flags class is using the class 'Flags' with the corresponding FlagBits enum as the template parameter
// if there's no enum for the FlagBits, introduce an artificial empty one
std::string emptyEnumName;
if (enumName.empty())
{
emptyEnumName = bitmaskName;
size_t pos = emptyEnumName.rfind("Flags");
assert(pos != std::string::npos);
emptyEnumName.replace(pos, 5, "FlagBits");
// if this emptyEnumName is not in the list of enums, list it here
if (m_enums.find("Vk" + emptyEnumName) == m_enums.end())
{
const std::string templateString = R"x( enum class ${enumName}
{};
VULKAN_HPP_INLINE std::string to_string( ${enumName} )
{
return "(void)";
}
)x";
str += replaceWithMap(templateString, { { "enumName", emptyEnumName } });
}
}
str += "\n" str += "\n"
" using " + bitmaskName + " = Flags<" + enumName + ", Vk" + bitmaskName + ">;\n"; " using " + bitmaskName + " = Flags<" + (enumName.empty() ? emptyEnumName : enumName) + ", Vk" + bitmaskName + ">;\n";
if (!enumValues.empty()) if (!enumValues.empty())
{ {
@ -1254,11 +1326,7 @@ void VulkanHppGenerator::appendDispatchLoaderStatic(std::string & str)
parameterList += ", "; parameterList += ", ";
parameters += ", "; parameters += ", ";
} }
parameterList += param.type.prefix + (param.type.prefix.empty() ? "" : " ") + param.type.type + param.type.postfix + " " + param.name; parameterList += param.type.prefix + (param.type.prefix.empty() ? "" : " ") + param.type.type + param.type.postfix + " " + param.name + constructCArraySizes(param.arraySizes);
if (!param.arraySize.empty())
{
parameterList += "[" + param.arraySize + "]";
}
parameters += param.name; parameters += param.name;
firstParam = false; firstParam = false;
} }
@ -1343,6 +1411,11 @@ void VulkanHppGenerator::appendEnum(std::string & str, std::pair<std::string, En
} }
str += "};\n"; str += "};\n";
if (!enumData.second.alias.empty())
{
str += " using " + stripPrefix(enumData.second.alias, "Vk") + " = " + stripPrefix(enumData.first, "Vk") + ";\n";
}
} }
void VulkanHppGenerator::appendEnums(std::string & str) const void VulkanHppGenerator::appendEnums(std::string & str) const
@ -1977,11 +2050,7 @@ void VulkanHppGenerator::appendFunctionHeaderArgumentEnhancedPointer(std::string
void VulkanHppGenerator::appendFunctionHeaderArgumentEnhancedSimple(std::string & str, ParamData const& param, bool lastArgument, bool withDefaults, bool withAllocator) const void VulkanHppGenerator::appendFunctionHeaderArgumentEnhancedSimple(std::string & str, ParamData const& param, bool lastArgument, bool withDefaults, bool withAllocator) const
{ {
str += param.type.compose() + " " + param.name; str += param.type.compose() + " " + param.name + constructCArraySizes(param.arraySizes);
if (!param.arraySize.empty())
{
str += "[" + param.arraySize + "]";
}
if (withDefaults && lastArgument && !withAllocator) if (withDefaults && lastArgument && !withAllocator)
{ {
@ -1991,9 +2060,9 @@ void VulkanHppGenerator::appendFunctionHeaderArgumentEnhancedSimple(std::string
{ {
// get the enum corresponding to this flag, to check if it's empty // get the enum corresponding to this flag, to check if it's empty
std::string strippedBitmaskName = stripPrefix(bitmasksIt->first, "Vk"); std::string strippedBitmaskName = stripPrefix(bitmasksIt->first, "Vk");
std::map<std::string, EnumData>::const_iterator enumIt = m_bitmaskBits.find(bitmasksIt->second.requirement); std::map<std::string, EnumData>::const_iterator enumIt = m_enums.find(bitmasksIt->second.requirement);
assert(enumIt != m_bitmaskBits.end()); assert((enumIt == m_enums.end()) || (enumIt->second.isBitmask));
if (enumIt->second.values.empty()) if ((enumIt == m_enums.end()) || (enumIt->second.values.empty()))
{ {
// there are no bits in this flag -> provide the default // there are no bits in this flag -> provide the default
str += " = " + stripPrefix(param.type.type, "Vk") + "()"; str += " = " + stripPrefix(param.type.type, "Vk") + "()";
@ -2140,11 +2209,7 @@ bool VulkanHppGenerator::appendFunctionHeaderArgumentStandard(std::string & str,
str += ","; str += ",";
} }
str += " " + param.type.compose() + " " + param.name; str += " " + param.type.compose() + " " + param.name + constructCArraySizes(param.arraySizes);
if (!param.arraySize.empty())
{
str += "[" + param.arraySize + "]";
}
if (withDefaults && isLastArgument) if (withDefaults && isLastArgument)
{ {
@ -2154,9 +2219,9 @@ bool VulkanHppGenerator::appendFunctionHeaderArgumentStandard(std::string & str,
{ {
// get the enum corresponding to this flag, to check if it's empty // get the enum corresponding to this flag, to check if it's empty
std::string strippedBitmaskName = stripPrefix(bitmasksIt->first, "Vk"); std::string strippedBitmaskName = stripPrefix(bitmasksIt->first, "Vk");
std::map<std::string, EnumData>::const_iterator enumIt = m_bitmaskBits.find(bitmasksIt->second.requirement); std::map<std::string, EnumData>::const_iterator enumIt = m_enums.find(bitmasksIt->second.requirement);
assert(enumIt != m_bitmaskBits.end()); assert((enumIt == m_enums.end()) || (enumIt->second.isBitmask));
if (enumIt->second.values.empty()) if ((enumIt == m_enums.end()) || (enumIt->second.values.empty()))
{ {
// there are no bits in this flag -> provide the default // there are no bits in this flag -> provide the default
str += " = " + stripPrefix(param.type.type, "Vk") + "()"; str += " = " + stripPrefix(param.type.type, "Vk") + "()";
@ -2538,13 +2603,13 @@ void VulkanHppGenerator::appendStructCompareOperators(std::string & str, std::pa
{ {
MemberData const& member = structData.second.members[i]; MemberData const& member = structData.second.members[i];
compareMembers += intro; compareMembers += intro;
if (member.arraySize.empty()) if (member.arraySizes.empty())
{ {
compareMembers += "( " + member.name + " == rhs." + member.name + " )"; compareMembers += "( " + member.name + " == rhs." + member.name + " )";
} }
else else
{ {
std::string arraySize = member.arraySize; std::string arraySize = constructArraySize(member.arraySizes);
if ((0 < i) && ((stripPostfix(member.name, "s") + "Count") == structData.second.members[i - 1].name)) if ((0 < i) && ((stripPostfix(member.name, "s") + "Count") == structData.second.members[i - 1].name))
{ {
assert(structData.second.members[i - 1].type.type == "uint32_t"); // make sure, it's an unsigned type, so we don't need to clamp here assert(structData.second.members[i - 1].type.type == "uint32_t"); // make sure, it's an unsigned type, so we don't need to clamp here
@ -2590,7 +2655,7 @@ std::string VulkanHppGenerator::appendStructConstructor(std::pair<std::string, S
// gather the initializers; skip members 'pNext' and 'sType', they are directly set by initializers // gather the initializers; skip members 'pNext' and 'sType', they are directly set by initializers
if ((member.name != "pNext") && (member.name != "sType")) if ((member.name != "pNext") && (member.name != "sType"))
{ {
if (member.arraySize.empty()) if (member.arraySizes.empty())
{ {
// here, we can only handle non-array arguments // here, we can only handle non-array arguments
initializers += prefix + " " + (firstArgument ? ":" : ",") + " " + member.name + "( " + member.name + "_ )\n"; initializers += prefix + " " + (firstArgument ? ":" : ",") + " " + member.name + "( " + member.name + "_ )\n";
@ -2603,7 +2668,12 @@ std::string VulkanHppGenerator::appendStructConstructor(std::pair<std::string, S
firstArgument = false; firstArgument = false;
std::string type = (member.type.type.substr(0, 2) == "Vk") ? ("VULKAN_HPP_NAMESPACE::" + stripPrefix(member.type.type, "Vk")) : member.type.type; std::string type = (member.type.type.substr(0, 2) == "Vk") ? ("VULKAN_HPP_NAMESPACE::" + stripPrefix(member.type.type, "Vk")) : member.type.type;
copyOps += prefix + " VULKAN_HPP_NAMESPACE::ConstExpressionArrayCopy<" + type + "," + member.arraySize + "," + member.arraySize + ">::copy( " + member.name + ", " + member.name + "_ );\n"; std::string arraySizes;
for (auto const& as : member.arraySizes)
{
arraySizes += "," + as;
}
copyOps += prefix + " VULKAN_HPP_NAMESPACE::ConstExpression" + std::to_string(member.arraySizes.size()) + "DArrayCopy<" + type + arraySizes + arraySizes + ">::copy( " + member.name + ", " + member.name + "_ );\n";
} }
} }
} }
@ -2632,7 +2702,7 @@ std::string VulkanHppGenerator::appendStructConstructor(std::pair<std::string, S
firstArgument = true; firstArgument = true;
for (size_t i = 0; i < subStruct->second.members.size(); i++) for (size_t i = 0; i < subStruct->second.members.size(); i++)
{ {
assert(structData.second.members[i].arraySize.empty()); assert(structData.second.members[i].arraySizes.empty());
subCopies += prefix + " " + (firstArgument ? ":" : ",") + " " + structData.second.members[i].name + "( " + subStructArgumentName + "." + subStruct->second.members[i].name + " )\n"; subCopies += prefix + " " + (firstArgument ? ":" : ",") + " " + structData.second.members[i].name + "( " + subStructArgumentName + "." + subStruct->second.members[i].name + " )\n";
firstArgument = false; firstArgument = false;
} }
@ -2643,7 +2713,7 @@ std::string VulkanHppGenerator::appendStructConstructor(std::pair<std::string, S
{ {
listedArgument = appendStructConstructorArgument(subArguments, listedArgument, indentation, structData.second.members[i]); listedArgument = appendStructConstructorArgument(subArguments, listedArgument, indentation, structData.second.members[i]);
assert(structData.second.members[i].arraySize.empty()); assert(structData.second.members[i].arraySizes.empty());
subCopies += prefix + " , " + structData.second.members[i].name + "( " + structData.second.members[i].name + "_ )\n"; subCopies += prefix + " , " + structData.second.members[i].name + "( " + structData.second.members[i].name + "_ )\n";
} }
@ -2677,13 +2747,13 @@ bool VulkanHppGenerator::appendStructConstructorArgument(std::string & str, bool
if ((memberData.name != "pNext") && (memberData.name != "sType")) if ((memberData.name != "pNext") && (memberData.name != "sType"))
{ {
str += (listedArgument ? (",\n" + indentation) : ""); str += (listedArgument ? (",\n" + indentation) : "");
if (memberData.arraySize.empty()) if (memberData.arraySizes.empty())
{ {
str += memberData.type.compose() + " "; str += memberData.type.compose() + " ";
} }
else else
{ {
str += "std::array<" + memberData.type.compose() + "," + memberData.arraySize + "> const& "; str += constructStandardArray(memberData.type.compose(), memberData.arraySizes) + " const& ";
} }
str += memberData.name + "_ = {}"; str += memberData.name + "_ = {}";
listedArgument = true; listedArgument = true;
@ -2718,7 +2788,16 @@ void VulkanHppGenerator::appendStructMembers(std::string & str, std::pair<std::s
{ {
str += "const "; str += "const ";
} }
str += member.type.compose() + " " + member.name; if (!member.bitCount.empty() && beginsWith(member.type.type, "Vk"))
{
assert(member.type.prefix.empty() && member.type.postfix.empty()); // never encounterd a different case
str += member.type.type;
}
else
{
str += member.type.compose();
}
str += " " + member.name;
if (member.name == "sType") // special handling for sType if (member.name == "sType") // special handling for sType
{ {
auto enumIt = m_enums.find("VkStructureType"); auto enumIt = m_enums.find("VkStructureType");
@ -2738,12 +2817,16 @@ void VulkanHppGenerator::appendStructMembers(std::string & str, std::pair<std::s
} }
else else
{ {
if (!member.arraySize.empty())
{
str += "[" + member.arraySize + "]";
}
// as we don't have any meaningful default initialization values, everything can be initialized by just '{}' ! // as we don't have any meaningful default initialization values, everything can be initialized by just '{}' !
str += " = {}"; assert(member.arraySizes.empty() || member.bitCount.empty());
if (!member.bitCount.empty())
{
str += " : " + member.bitCount; // except for bitfield members, where no default member initializatin is supported (up to C++20)
}
else
{
str += constructCArraySizes(member.arraySizes) + " = {}";
}
} }
str += ";\n"; str += ";\n";
} }
@ -2762,20 +2845,35 @@ void VulkanHppGenerator::appendStructSetter(std::string & str, std::string const
{ {
if (memberData.type.type != "VkStructureType") // filter out StructureType, which is supposed to be immutable ! if (memberData.type.type != "VkStructureType") // filter out StructureType, which is supposed to be immutable !
{ {
std::string memberType = memberData.arraySize.empty() ? memberData.type.compose() : "std::array<" + memberData.type.compose() + "," + memberData.arraySize + ">"; std::string memberType;
if (memberData.arraySizes.empty())
{
memberType = memberData.type.compose();
}
else
{
memberType = constructStandardArray(memberData.type.compose(), memberData.arraySizes);
}
// copy over the argument, either by assigning simple data, or by memcpy array data // copy over the argument, either by assigning simple data, or by memcpy array data
str += "\n" str += "\n"
" " + structureName + " & set" + startUpperCase(memberData.name) + "( " + memberType + " " + memberData.name + "_ ) VULKAN_HPP_NOEXCEPT\n" " " + structureName + " & set" + startUpperCase(memberData.name) + "( " + memberType + " " + memberData.name + "_ ) VULKAN_HPP_NOEXCEPT\n"
" {\n" " {\n"
" "; " ";
if (memberData.arraySize.empty()) if (memberData.arraySizes.empty())
{ {
str += memberData.name + " = " + memberData.name + "_"; if (!memberData.bitCount.empty() && beginsWith(memberData.type.type, "Vk"))
{
str += memberData.name + " = " + "*reinterpret_cast<" + memberData.type.type + "*>(&" + memberData.name + "_)";
}
else
{
str += memberData.name + " = " + memberData.name + "_";
}
} }
else else
{ {
str += "memcpy( " + memberData.name + ", " + memberData.name + "_.data(), " + memberData.arraySize + " * sizeof( " + memberData.type.compose() + " ) )"; str += "memcpy( " + memberData.name + ", " + memberData.name + "_.data(), " + constructArraySize(memberData.arraySizes) + " * sizeof( " + memberData.type.compose() + " ) )";
} }
str += ";\n" str += ";\n"
" return *this;\n" " return *this;\n"
@ -2919,7 +3017,7 @@ void VulkanHppGenerator::appendUnion(std::string & str, std::pair<std::string, S
if (!structure.second.returnedOnly) if (!structure.second.returnedOnly)
{ {
bool firstTime = true; bool firstMember = true;
for (auto const& member : structure.second.members) for (auto const& member : structure.second.members)
{ {
// VkBool32 is aliased to uint32_t. Don't create a VkBool32 constructor if the union also contains a uint32_t constructor. // VkBool32 is aliased to uint32_t. Don't create a VkBool32 constructor if the union also contains a uint32_t constructor.
@ -2931,20 +3029,34 @@ void VulkanHppGenerator::appendUnion(std::string & str, std::pair<std::string, S
} }
} }
// one constructor per union element static const std::string constructorTemplate = R"(
str += " " + stripPrefix(structure.first, "Vk") + "( " + (member.arraySize.empty() ? (member.type.compose() + " ") : ("const std::array<" + member.type.compose() + "," + member.arraySize + ">& ")) + member.name + "_"; ${unionName}( ${memberType} ${memberName}_${defaultAssignment} )
{
// just the very first constructor gets default arguments ${memberAssignment};
if (firstTime) }
)";
std::string memberAssignment, memberType;
if (member.arraySizes.empty())
{ {
str += " = {}"; memberAssignment = member.name + " = " + member.name + "_";
firstTime = false; memberType = member.type.compose();
} }
str += " )\n" else
" {\n" {
" " + (member.arraySize.empty() ? (member.name + " = " + member.name + "_") : ("memcpy( " + member.name + ", " + member.name + "_.data(), " + member.arraySize + " * sizeof( " + member.type.compose() + " ) )")) + ";\n" std::string arraySize = constructArraySize(member.arraySizes);
" }\n" memberAssignment = "memcpy( " + member.name + ", " + member.name + "_.data(), " + arraySize + " * sizeof( " + member.type.compose() + " ) )";
"\n"; memberType = "const " + constructStandardArray(member.type.compose(), member.arraySizes) + "&";
}
str += replaceWithMap(constructorTemplate,
{
{ "defaultAssignment", firstMember ? " = {}" : "" },
{ "memberAssignment", memberAssignment },
{ "memberName", member.name },
{ "memberType", memberType },
{ "unionName", stripPrefix(structure.first, "Vk") }
});
firstMember = false;
} }
// one setter per union element // one setter per union element
@ -2954,17 +3066,26 @@ void VulkanHppGenerator::appendUnion(std::string & str, std::pair<std::string, S
} }
} }
// the implicit cast operators to the native type // assignment operator
str += " operator " + structure.first + " const&() const\n" static const std::string operatorsTemplate = R"(
" {\n" VULKAN_HPP_NAMESPACE::${unionName} & operator=( VULKAN_HPP_NAMESPACE::${unionName} const & rhs ) VULKAN_HPP_NOEXCEPT
" return *reinterpret_cast<const " + structure.first + "*>(this);\n" {
" }\n" memcpy( this, &rhs, sizeof( VULKAN_HPP_NAMESPACE::${unionName} ) );
"\n" return *this;
" operator " + structure.first + " &()\n" }
" {\n"
" return *reinterpret_cast<" + structure.first + "*>(this);\n" operator Vk${unionName} const&() const
" }\n" {
"\n"; return *reinterpret_cast<const Vk${unionName}*>(this);
}
operator Vk${unionName} &()
{
return *reinterpret_cast<Vk${unionName}*>(this);
}
)";
str += replaceWithMap(operatorsTemplate, { { "unionName", stripPrefix(structure.first, "Vk") } });
// the union member variables // the union member variables
// if there's at least one Vk... type in this union, check for unrestricted unions support // if there's at least one Vk... type in this union, check for unrestricted unions support
@ -2975,14 +3096,14 @@ void VulkanHppGenerator::appendUnion(std::string & str, std::pair<std::string, S
} }
for (auto const& member : structure.second.members) for (auto const& member : structure.second.members)
{ {
str += " " + member.type.compose() + " " + member.name + (member.arraySize.empty() ? "" : ("[" + member.arraySize + "]")) + ";\n"; str += " " + member.type.compose() + " " + member.name + constructCArraySizes(member.arraySizes) + ";\n";
} }
if (needsUnrestrictedUnions) if (needsUnrestrictedUnions)
{ {
str += "#else\n"; str += "#else\n";
for (auto const& member : structure.second.members) for (auto const& member : structure.second.members)
{ {
str += " " + member.type.prefix + (member.type.prefix.empty() ? "" : " ") + member.type.type + member.type.postfix + " " + member.name + (member.arraySize.empty() ? "" : ("[" + member.arraySize + "]")) + ";\n"; str += " " + member.type.prefix + (member.type.prefix.empty() ? "" : " ") + member.type.type + member.type.postfix + " " + member.name + constructCArraySizes(member.arraySizes) + ";\n";
} }
str += "#endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/\n"; str += "#endif /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/\n";
} }
@ -3012,6 +3133,12 @@ void VulkanHppGenerator::appendUniqueTypes(std::string & str, std::string const&
str += "\n" str += "\n"
" template <typename Dispatch> class UniqueHandleTraits<" + type + ", Dispatch> { public: using deleter = " + deleterType + deleterAction + "<" + deleterParent + deleterPool + ", Dispatch>; };\n" " template <typename Dispatch> class UniqueHandleTraits<" + type + ", Dispatch> { public: using deleter = " + deleterType + deleterAction + "<" + deleterParent + deleterPool + ", Dispatch>; };\n"
" using Unique" + type + " = UniqueHandle<" + type + ", VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;"; " using Unique" + type + " = UniqueHandle<" + type + ", VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;";
if (!handleIt->second.alias.empty())
{
str += "\n"
" using Unique" + stripPrefix(handleIt->second.alias, "Vk") + " = UniqueHandle<" + type + ", VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;";
}
} }
str += "\n" str += "\n"
"#endif /*VULKAN_HPP_NO_SMART_HANDLE*/\n"; "#endif /*VULKAN_HPP_NO_SMART_HANDLE*/\n";
@ -3041,7 +3168,7 @@ bool VulkanHppGenerator::containsArray(std::string const& type) const
{ {
for (auto memberIt = structureIt->second.members.begin(); memberIt != structureIt->second.members.end() && !found; ++memberIt) for (auto memberIt = structureIt->second.members.begin(); memberIt != structureIt->second.members.end() && !found; ++memberIt)
{ {
found = !memberIt->arraySize.empty(); found = !memberIt->arraySizes.empty();
} }
} }
return found; return found;
@ -3094,10 +3221,10 @@ std::string VulkanHppGenerator::determineEnhancedReturnType(CommandData const& c
&& ((commandData.returnType == "void") && ((commandData.returnType == "void")
|| ((commandData.returnType == "VkResult") || ((commandData.returnType == "VkResult")
&& ((commandData.successCodes.size() == 1) && ((commandData.successCodes.size() == 1)
|| ((commandData.successCodes.size() == 2) || ((commandData.successCodes.size() == 2) && (commandData.successCodes[1] == "eIncomplete") && twoStep)
&& (commandData.successCodes[1] == "eIncomplete") || ((commandData.successCodes.size() == 3) && (commandData.successCodes[1] == "eOperationDeferredKHR") && (commandData.successCodes[2] == "eOperationNotDeferredKHR"))))))
&& twoStep)))))
{ {
assert(commandData.successCodes.empty() || (commandData.successCodes[0] == "eSuccess"));
if (vectorParamIndices.find(returnParamIndex) != vectorParamIndices.end()) if (vectorParamIndices.find(returnParamIndex) != vectorParamIndices.end())
{ {
enhancedReturnType = (commandData.params[returnParamIndex].type.type == "void") enhancedReturnType = (commandData.params[returnParamIndex].type.type == "void")
@ -3330,17 +3457,6 @@ void VulkanHppGenerator::readBitmask(tinyxml2::XMLElement const* element, std::m
{ {
requirement = requiresIt->second; requirement = requiresIt->second;
} }
else
{
// Generate FlagBits name and add it to the list of enums and vulkan types
requirement = name;
size_t pos = requirement.rfind("Flags");
assert(pos != std::string::npos);
requirement.replace(pos, 5, "FlagBits");
assert(m_bitmaskBits.find(requirement) == m_bitmaskBits.end());
m_bitmaskBits.insert(std::make_pair(requirement, EnumData()));
}
m_bitmasks.insert(std::make_pair(name, BitmaskData(requirement))); m_bitmasks.insert(std::make_pair(name, BitmaskData(requirement)));
} }
@ -3452,7 +3568,9 @@ VulkanHppGenerator::ParamData VulkanHppGenerator::readCommandParam(tinyxml2::XML
if (value == "name") if (value == "name")
{ {
paramData.name = child->GetText(); paramData.name = child->GetText();
paramData.arraySize = readArraySize(child->NextSibling()); std::string bitCount;
std::tie(paramData.arraySizes, bitCount) = readModifiers(child->NextSibling());
assert(bitCount.empty());
} }
else if (value == "type") else if (value == "type")
{ {
@ -3608,12 +3726,19 @@ void VulkanHppGenerator::readEnums(tinyxml2::XMLElement const* element)
{ {
checkAttributes(attributes, element->GetLineNum(), { { "name",{} },{ "type",{ "bitmask", "enum" } } }, { { "comment",{} } }); // re-check with type as required checkAttributes(attributes, element->GetLineNum(), { { "name",{} },{ "type",{ "bitmask", "enum" } } }, { { "comment",{} } }); // re-check with type as required
// ad an empty EnumData on this name into the enums map // get the EnumData entry in enum map
EnumData enumData; std::map<std::string, EnumData>::iterator it = m_enums.find(name);
if (it == m_enums.end())
{
// well, some enums are not listed in the <types> section
it = m_enums.insert(std::make_pair(name, EnumData())).first;
}
assert(it->second.values.empty());
// mark it as a bitmap, if it is one
std::string type = attributes.find("type")->second; std::string type = attributes.find("type")->second;
bool bitmask = (type == "bitmask"); bool bitmask = (type == "bitmask");
std::map<std::string, EnumData>::iterator it = bitmask ? m_bitmaskBits.insert(std::make_pair(name, enumData)).first : m_enums.insert(std::make_pair(name, enumData)).first; it->second.isBitmask = bitmask;
assert(it->second.values.empty());
std::string prefix = getEnumPrefix(name, bitmask); std::string prefix = getEnumPrefix(name, bitmask);
std::string postfix = getEnumPostfix(name, m_tags, prefix); std::string postfix = getEnumPostfix(name, m_tags, prefix);
@ -3728,10 +3853,10 @@ void VulkanHppGenerator::readExtensionDisabledRequire(tinyxml2::XMLElement const
// a type simply needs to be removed from the structs and vkTypes sets // a type simply needs to be removed from the structs and vkTypes sets
assert(m_structures.find(nameAttribute->second) != m_structures.end() || assert(m_structures.find(nameAttribute->second) != m_structures.end() ||
m_bitmasks.find(nameAttribute->second) != m_bitmasks.end() || m_bitmasks.find(nameAttribute->second) != m_bitmasks.end() ||
m_bitmaskBits.find(nameAttribute->second) != m_bitmaskBits.end()); m_enums.find(nameAttribute->second) != m_enums.end());
m_structures.erase(nameAttribute->second); m_structures.erase(nameAttribute->second);
m_bitmasks.erase(nameAttribute->second); m_bitmasks.erase(nameAttribute->second);
m_bitmaskBits.erase(nameAttribute->second); m_enums.erase(nameAttribute->second);
} }
} }
else if (value == "enum") else if (value == "enum")
@ -3828,7 +3953,7 @@ void VulkanHppGenerator::readExtensionRequireType(tinyxml2::XMLElement const* el
{ {
assert(bmit->second.platform.empty()); assert(bmit->second.platform.empty());
bmit->second.platform = platform; bmit->second.platform = platform;
assert(m_bitmaskBits.find(bmit->second.requirement) != m_bitmaskBits.end()); assert((m_enums.find(bmit->second.requirement) == m_enums.end()) || (m_enums.find(bmit->second.requirement)->second.isBitmask));
} }
else else
{ {
@ -4016,17 +4141,11 @@ void VulkanHppGenerator::readRequireEnum(tinyxml2::XMLElement const* element, st
auto extendsIt = attributes.find("extends"); auto extendsIt = attributes.find("extends");
if (extendsIt != attributes.end()) if (extendsIt != attributes.end())
{ {
bool bitmask = false;
std::string extends = extendsIt->second; std::string extends = extendsIt->second;
auto enumIt = m_enums.find(extends); auto enumIt = m_enums.find(extends);
if (enumIt == m_enums.end()) assert(enumIt != m_enums.end());
{
enumIt = m_bitmaskBits.find(extends);
assert(enumIt != m_bitmaskBits.end());
bitmask = true;
}
std::string prefix = getEnumPrefix(enumIt->first, bitmask); std::string prefix = getEnumPrefix(enumIt->first, enumIt->second.isBitmask);
std::string postfix = getEnumPostfix(enumIt->first, m_tags, prefix); std::string postfix = getEnumPostfix(enumIt->first, m_tags, prefix);
auto nameIt = attributes.find("name"); auto nameIt = attributes.find("name");
@ -4037,7 +4156,7 @@ void VulkanHppGenerator::readRequireEnum(tinyxml2::XMLElement const* element, st
{ {
// add this enum name to the list of aliases // add this enum name to the list of aliases
checkAttributes(attributes, element->GetLineNum(), { { "alias",{} },{ "extends",{} },{ "name",{} } }, { { "comment",{} } }); checkAttributes(attributes, element->GetLineNum(), { { "alias",{} },{ "extends",{} },{ "name",{} } }, { { "comment",{} } });
std::string valueName = createEnumValueName(nameIt->second, prefix, postfix, bitmask, tag); std::string valueName = createEnumValueName(nameIt->second, prefix, postfix, enumIt->second.isBitmask, tag);
assert(std::find_if(enumIt->second.aliases.begin(), enumIt->second.aliases.end(), [&valueName](std::pair<std::string, std::string> const& aliasPair) { return valueName == aliasPair.second; }) == enumIt->second.aliases.end()); assert(std::find_if(enumIt->second.aliases.begin(), enumIt->second.aliases.end(), [&valueName](std::pair<std::string, std::string> const& aliasPair) { return valueName == aliasPair.second; }) == enumIt->second.aliases.end());
enumIt->second.aliases.push_back(std::make_pair(nameIt->second, valueName)); enumIt->second.aliases.push_back(std::make_pair(nameIt->second, valueName));
} }
@ -4045,7 +4164,7 @@ void VulkanHppGenerator::readRequireEnum(tinyxml2::XMLElement const* element, st
{ {
// add this enum name to the list of values // add this enum name to the list of values
assert((attributes.find("bitpos") != attributes.end()) + (attributes.find("offset") != attributes.end()) + (attributes.find("value") != attributes.end()) == 1); assert((attributes.find("bitpos") != attributes.end()) + (attributes.find("offset") != attributes.end()) + (attributes.find("value") != attributes.end()) == 1);
enumIt->second.addEnumValue(nameIt->second, bitmask, attributes.find("bitpos") != attributes.end(), prefix, postfix, tag); enumIt->second.addEnumValue(nameIt->second, enumIt->second.isBitmask, attributes.find("bitpos") != attributes.end(), prefix, postfix, tag);
} }
} }
} }
@ -4142,12 +4261,12 @@ VulkanHppGenerator::MemberData VulkanHppGenerator::readStructMember(tinyxml2::XM
{ {
assert(child->PreviousSibling() && (strcmp(child->PreviousSibling()->Value(), "[") == 0) assert(child->PreviousSibling() && (strcmp(child->PreviousSibling()->Value(), "[") == 0)
&& child->NextSibling() && (strcmp(child->NextSibling()->Value(), "]") == 0)); && child->NextSibling() && (strcmp(child->NextSibling()->Value(), "]") == 0));
memberData.arraySize = child->GetText(); memberData.arraySizes.push_back(child->GetText());
} }
else if (value == "name") else if (value == "name")
{ {
memberData.name = child->GetText(); memberData.name = child->GetText();
memberData.arraySize = readArraySize(child->NextSibling()); std::tie(memberData.arraySizes, memberData.bitCount) = readModifiers(child->NextSibling());
} }
else if (value == "type") else if (value == "type")
{ {
@ -4235,6 +4354,10 @@ void VulkanHppGenerator::readType(tinyxml2::XMLElement const* element)
{ {
readDefine(element, attributes); readDefine(element, attributes);
} }
else if (categoryIt->second == "enum")
{
readTypeEnum(element, attributes);
}
else if (categoryIt->second == "funcpointer") else if (categoryIt->second == "funcpointer")
{ {
readFuncpointer(element, attributes); readFuncpointer(element, attributes);
@ -4251,7 +4374,7 @@ void VulkanHppGenerator::readType(tinyxml2::XMLElement const* element)
{ {
readStruct(element, true, attributes); readStruct(element, true, attributes);
} }
else if ((categoryIt->second != "enum") && (categoryIt->second != "include")) else if ( categoryIt->second != "include")
{ {
throw std::runtime_error("Spec error on line " + std::to_string(element->GetLineNum()) + ": unknown category <" + categoryIt->second + ">"); throw std::runtime_error("Spec error on line " + std::to_string(element->GetLineNum()) + ": unknown category <" + categoryIt->second + ">");
} }
@ -4272,6 +4395,27 @@ void VulkanHppGenerator::readType(tinyxml2::XMLElement const* element)
#endif #endif
} }
void VulkanHppGenerator::readTypeEnum(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes)
{
checkAttributes(attributes, element->GetLineNum(), { { "category",{ "enum" } }, { "name",{} } }, { { "alias",{} }});
std::string name = attributes.find("name")->second;
auto aliasIt = attributes.find("alias");
if ((aliasIt != attributes.end()))
{
auto enumIt = m_enums.find(aliasIt->second);
assert(enumIt != m_enums.end());
assert(enumIt->second.alias.empty());
enumIt->second.alias = name;
}
else
{
assert(m_enums.find(name) == m_enums.end());
m_enums[name]; // insert an empty EnumData
}
}
void VulkanHppGenerator::readTypes(tinyxml2::XMLElement const* element) void VulkanHppGenerator::readTypes(tinyxml2::XMLElement const* element)
{ {
checkAttributes(getAttributes(element), element->GetLineNum(), { { "comment",{} } }, {}); checkAttributes(getAttributes(element), element->GetLineNum(), { { "comment",{} } }, {});
@ -4344,7 +4488,7 @@ std::string VulkanHppGenerator::TypeData::compose() const
return prefix + (prefix.empty() ? "" : " ") + ((type.substr(0, 2) == "Vk") ? "VULKAN_HPP_NAMESPACE::" : "") + stripPrefix(type, "Vk") + postfix; return prefix + (prefix.empty() ? "" : " ") + ((type.substr(0, 2) == "Vk") ? "VULKAN_HPP_NAMESPACE::" : "") + stripPrefix(type, "Vk") + postfix;
} }
int main( int argc, char **argv ) int main(int argc, char **argv)
{ {
static const std::string classArrayProxy = R"( static const std::string classArrayProxy = R"(
#if !defined(VULKAN_HPP_DISABLE_ENHANCED_MODE) #if !defined(VULKAN_HPP_DISABLE_ENHANCED_MODE)
@ -5074,22 +5218,50 @@ int main( int argc, char **argv )
static const std::string constExpressionArrayCopy = R"( static const std::string constExpressionArrayCopy = R"(
template <typename T, size_t N, size_t I> template <typename T, size_t N, size_t I>
class ConstExpressionArrayCopy class ConstExpression1DArrayCopy
{ {
public: public:
VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N], std::array<T,N> const& src) VULKAN_HPP_NOEXCEPT VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N], std::array<T,N> const& src) VULKAN_HPP_NOEXCEPT
{ {
dst[I-1] = src[I-1]; dst[I-1] = src[I-1];
ConstExpressionArrayCopy<T, N, I - 1>::copy(dst, src); ConstExpression1DArrayCopy<T, N, I - 1>::copy(dst, src);
} }
}; };
template <typename T, size_t N> template <typename T, size_t N>
class ConstExpressionArrayCopy<T, N, 0> class ConstExpression1DArrayCopy<T, N, 0>
{ {
public: public:
VULKAN_HPP_CONSTEXPR_14 static void copy(T /*dst*/[N], std::array<T,N> const& /*src*/) VULKAN_HPP_NOEXCEPT {} VULKAN_HPP_CONSTEXPR_14 static void copy(T /*dst*/[N], std::array<T,N> const& /*src*/) VULKAN_HPP_NOEXCEPT {}
}; };
template <typename T, size_t N, size_t M, size_t I, size_t J>
class ConstExpression2DArrayCopy
{
public:
VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N][M], std::array<std::array<T,M>, N> const& src) VULKAN_HPP_NOEXCEPT
{
dst[I - 1][J - 1] = src[I - 1][J - 1];
ConstExpression2DArrayCopy<T, N, M, I, J - 1>::copy(dst, src);
}
};
template <typename T, size_t N, size_t M, size_t I>
class ConstExpression2DArrayCopy<T, N, M, I, 0>
{
public:
VULKAN_HPP_CONSTEXPR_14 static void copy(T dst[N][M], std::array<std::array<T, M>, N> const& src) VULKAN_HPP_NOEXCEPT
{
ConstExpression2DArrayCopy<T, N, M, I - 1, M>::copy(dst, src);
}
};
template <typename T, size_t N, size_t M>
class ConstExpression2DArrayCopy<T, N, M, 0, 0>
{
public:
VULKAN_HPP_CONSTEXPR_14 static void copy(T /*dst*/[N][M], std::array<std::array<T, M>, N> const& /*src*/) VULKAN_HPP_NOEXCEPT {}
};
)"; )";
static const std::string defines = R"( static const std::string defines = R"(

View File

@ -83,11 +83,11 @@ class VulkanHppGenerator
: optional(false) : optional(false)
{} {}
TypeData type; TypeData type;
std::string name; std::string name;
std::string arraySize; std::vector<std::string> arraySizes;
std::string len; std::string len;
bool optional; bool optional;
}; };
struct CommandData struct CommandData
@ -120,7 +120,9 @@ class VulkanHppGenerator
{ {
void addEnumValue(std::string const& valueName, bool bitmask, bool bitpos, std::string const& prefix, std::string const& postfix, std::string const& tag); void addEnumValue(std::string const& valueName, bool bitmask, bool bitpos, std::string const& prefix, std::string const& postfix, std::string const& tag);
std::string alias; // alias for this enum
std::vector<std::pair<std::string, std::string>> aliases; // pairs of vulkan enum value and corresponding vk::-namespace enum value std::vector<std::pair<std::string, std::string>> aliases; // pairs of vulkan enum value and corresponding vk::-namespace enum value
bool isBitmask = false;
std::string platform; std::string platform;
std::vector<EnumValueData> values; std::vector<EnumValueData> values;
}; };
@ -136,10 +138,11 @@ class VulkanHppGenerator
struct MemberData struct MemberData
{ {
TypeData type; TypeData type;
std::string name; std::string name;
std::string arraySize; std::vector<std::string> arraySizes;
std::string values; std::string bitCount;
std::string values;
}; };
struct StructureData struct StructureData
@ -240,6 +243,7 @@ class VulkanHppGenerator
std::vector<MemberData> readStructMembers(std::vector<tinyxml2::XMLElement const*> const& children); std::vector<MemberData> readStructMembers(std::vector<tinyxml2::XMLElement const*> const& children);
void readTag(tinyxml2::XMLElement const* element); void readTag(tinyxml2::XMLElement const* element);
void readType(tinyxml2::XMLElement const* element); void readType(tinyxml2::XMLElement const* element);
void readTypeEnum(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes);
void registerDeleter(std::string const& name, std::pair<std::string, CommandData> const& commandData); void registerDeleter(std::string const& name, std::pair<std::string, CommandData> const& commandData);
void unlinkCommandFromHandle(std::string const& name); void unlinkCommandFromHandle(std::string const& name);
#if !defined(NDEBUG) #if !defined(NDEBUG)
@ -248,7 +252,6 @@ class VulkanHppGenerator
private: private:
std::map<std::string, std::string> m_baseTypes; std::map<std::string, std::string> m_baseTypes;
std::map<std::string, EnumData> m_bitmaskBits;
std::map<std::string, BitmaskData> m_bitmasks; std::map<std::string, BitmaskData> m_bitmasks;
std::map<std::string, std::string> m_commandToHandle; std::map<std::string, std::string> m_commandToHandle;
std::map<std::string, EnumData> m_enums; std::map<std::string, EnumData> m_enums;

File diff suppressed because it is too large Load Diff