Add support for Vulkan call delegation to support custom loaders. (#174)

This commit is contained in:
Markus Tavenrath 2018-01-22 22:36:15 +08:00 committed by Andreas Süßenbach
parent d74e5f6199
commit e97e34675d
4 changed files with 4262 additions and 1839 deletions

View File

@ -1541,6 +1541,7 @@ tinyxml2::XMLNode const* VulkanHppGenerator::readCommandParamType(tinyxml2::XMLN
tinyxml2::XMLElement const* typeElement = node->ToElement(); tinyxml2::XMLElement const* typeElement = node->ToElement();
checkEmptyElement(typeElement); checkEmptyElement(typeElement);
std::string type = strip(node->ToElement()->GetText(), "Vk"); std::string type = strip(node->ToElement()->GetText(), "Vk");
param.unchangedType = param.type + node->ToElement()->GetText();
param.type += type; param.type += type;
param.pureType = type; param.pureType = type;
@ -1552,6 +1553,7 @@ tinyxml2::XMLNode const* VulkanHppGenerator::readCommandParamType(tinyxml2::XMLN
std::string value = trimEnd(node->Value()); std::string value = trimEnd(node->Value());
assert((value == "*") || (value == "**") || (value == "* const*")); assert((value == "*") || (value == "**") || (value == "* const*"));
param.type += value; param.type += value;
param.unchangedType += value;
node = node->NextSibling(); node = node->NextSibling();
} }
@ -1635,7 +1637,7 @@ void VulkanHppGenerator::readCommandsCommand(tinyxml2::XMLElement const* element
} }
else if (value == "proto") else if (value == "proto")
{ {
readCommandProto(child, commandData.returnType, commandData.fullName); readCommandProto(child, commandData.returnType, commandData.unchangedReturnType, commandData.fullName);
} }
#if !defined(NDEBUG) #if !defined(NDEBUG)
else else
@ -1661,7 +1663,7 @@ void VulkanHppGenerator::readCommandsCommand(tinyxml2::XMLElement const* element
m_commands.insert(std::make_pair(commandData.fullName, commandData)); m_commands.insert(std::make_pair(commandData.fullName, commandData));
} }
void VulkanHppGenerator::readCommandProto(tinyxml2::XMLElement const* element, std::string & returnType, std::string & fullName) void VulkanHppGenerator::readCommandProto(tinyxml2::XMLElement const* element, std::string & returnType, std::string & unchangedReturnType, std::string & fullName)
{ {
checkAttributes(getAttributes(element), element->GetLineNum(), {}, {}); checkAttributes(getAttributes(element), element->GetLineNum(), {}, {});
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element); std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
@ -1669,6 +1671,7 @@ void VulkanHppGenerator::readCommandProto(tinyxml2::XMLElement const* element, s
// get return type and name of the command // get return type and name of the command
returnType = strip(children[0]->GetText(), "Vk"); returnType = strip(children[0]->GetText(), "Vk");
unchangedReturnType = children[0]->GetText();
fullName = startLowerCase(strip(children[1]->GetText(), "vk")); fullName = startLowerCase(strip(children[1]->GetText(), "vk"));
// add an empty DependencyData to this name // add an empty DependencyData to this name
@ -2777,7 +2780,7 @@ void VulkanHppGenerator::writeCall(std::ostream & os, CommandData const& command
} }
// the original function call // the original function call
os << "vk" << startUpperCase(commandData.fullName) << "( "; os << "d.vk" << startUpperCase(commandData.fullName) << "( ";
if (!commandData.className.empty()) if (!commandData.className.empty())
{ {
@ -3201,10 +3204,8 @@ void VulkanHppGenerator::writeExceptionsForEnum(std::ostream & os, EnumData cons
void VulkanHppGenerator::writeFunction(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique, bool isStructureChain) 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)) writeFunctionHeaderTemplate(os, indentation, commandData, enhanced, !definition, isStructureChain);
{
writeFunctionHeaderTemplate(os, indentation, commandData, !definition, isStructureChain);
}
os << indentation << (definition ? "VULKAN_HPP_INLINE " : ""); os << indentation << (definition ? "VULKAN_HPP_INLINE " : "");
writeFunctionHeaderReturnType(os, indentation, commandData, enhanced, singular, unique, isStructureChain); writeFunctionHeaderReturnType(os, indentation, commandData, enhanced, singular, unique, isStructureChain);
if (definition && !commandData.className.empty()) if (definition && !commandData.className.empty())
@ -3607,7 +3608,7 @@ void VulkanHppGenerator::writeFunctionBodyStandard(std::ostream & os, std::strin
} }
// call the original function // call the original function
os << "vk" << startUpperCase(commandData.fullName) << "( "; os << "d.vk" << startUpperCase(commandData.fullName) << "( ";
if (!commandData.className.empty()) if (!commandData.className.empty())
{ {
@ -3663,7 +3664,7 @@ void VulkanHppGenerator::writeFunctionHeaderArguments(std::ostream & os, Command
} }
else else
{ {
writeFunctionHeaderArgumentsStandard(os, commandData); writeFunctionHeaderArgumentsStandard(os, commandData, withDefaults);
} }
os << ")"; os << ")";
if (!commandData.className.empty()) if (!commandData.className.empty())
@ -3805,14 +3806,29 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsEnhanced(std::ostream & os,
argEncountered = true; argEncountered = true;
} }
} }
os << " ";
if (argEncountered)
{
os << ", ";
}
} }
os << "Dispatch const &d";
if (withDefaults)
{
os << " = Dispatch()";
}
os << " ";
} }
void VulkanHppGenerator::writeFunctionHeaderArgumentsStandard(std::ostream & os, CommandData const& commandData) void VulkanHppGenerator::writeFunctionHeaderArgumentsStandard(std::ostream & os, CommandData const& commandData, bool withDefaults)
{ {
// for the standard case, just list all the arguments as we've got them // for the standard case, just list all the arguments as we've got them
bool argEncountered = false; bool argEncountered = false;
// determine the last argument, where we might provide some default for
size_t lastArgument = commandData.params.size() - 1;
for (size_t i = commandData.className.empty() ? 0 : 1; i < commandData.params.size(); i++) for (size_t i = commandData.className.empty() ? 0 : 1; i < commandData.params.size(); i++)
{ {
if (argEncountered) if (argEncountered)
@ -3825,11 +3841,36 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsStandard(std::ostream & os,
{ {
os << "[" << commandData.params[i].arraySize << "]"; os << "[" << commandData.params[i].arraySize << "]";
} }
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, BitmaskData>::const_iterator flagIt = m_bitmasks.find(commandData.params[i].pureType);
if (flagIt != 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); });
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());
if (enumIt->second.values.empty())
{
// there are no bits in this flag -> provide the default
os << " = " << commandData.params[i].pureType << "()";
}
}
}
argEncountered = true; argEncountered = true;
} }
if (argEncountered) if (argEncountered)
{ {
os << " "; os << ", ";
}
os << "Dispatch const &d";
if (withDefaults)
{
os << " = Dispatch() ";
} }
} }
@ -3893,19 +3934,20 @@ void VulkanHppGenerator::writeFunctionHeaderReturnType(std::ostream & os, std::s
os << replaceWithMap(templateString, { { "returnType", returnType } }); os << replaceWithMap(templateString, { { "returnType", returnType } });
} }
void VulkanHppGenerator::writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool withDefault, bool isStructureChain) void VulkanHppGenerator::writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool withDefault, bool isStructureChain)
{ {
if (isStructureChain) std::string dispatch = withDefault ? std::string("typename Dispatch = DispatchLoader") : std::string("typename Dispatch");
if (enhanced && isStructureChain)
{ {
os << indentation << "template <typename ...T>" << std::endl; os << indentation << "template <typename ...T, " << dispatch << ">" << std::endl;
} }
else if ((commandData.templateParam != ~0) && ((commandData.templateParam != commandData.returnParam) || (commandData.enhancedReturnType == "Result"))) else if (enhanced && (commandData.templateParam != ~0) && ((commandData.templateParam != commandData.returnParam) || (commandData.enhancedReturnType == "Result")))
{ {
// if there's a template parameter, not being the return parameter or where the enhanced return type is 'Result' -> templatize on type 'T' // if there's a template parameter, not being the return parameter or where the enhanced return type is 'Result' -> templatize on type 'T'
assert(commandData.enhancedReturnType.find("Allocator") == std::string::npos); assert(commandData.enhancedReturnType.find("Allocator") == std::string::npos);
os << indentation << "template <typename T>" << std::endl; os << indentation << "template <typename T, " << dispatch << ">" << std::endl;
} }
else if ((commandData.enhancedReturnType.find("Allocator") != std::string::npos)) else if (enhanced && (commandData.enhancedReturnType.find("Allocator") != std::string::npos))
{ {
// otherwise, if there's an Allocator used in the enhanced return type, we templatize on that Allocator // otherwise, if there's an Allocator used in the enhanced return type, we templatize on that Allocator
assert((commandData.enhancedReturnType.substr(0, 12) == "std::vector<") && (commandData.enhancedReturnType.find(',') != std::string::npos) && (12 < commandData.enhancedReturnType.find(','))); assert((commandData.enhancedReturnType.substr(0, 12) == "std::vector<") && (commandData.enhancedReturnType.find(',') != std::string::npos) && (12 < commandData.enhancedReturnType.find(',')));
@ -3915,8 +3957,13 @@ void VulkanHppGenerator::writeFunctionHeaderTemplate(std::ostream & os, std::str
// for the default type get the type from the enhancedReturnType, which is of the form 'std::vector<Type,Allocator>' // for the default type get the type from the enhancedReturnType, which is of the form 'std::vector<Type,Allocator>'
os << " = std::allocator<" << commandData.enhancedReturnType.substr(12, commandData.enhancedReturnType.find(',') - 12) << ">"; os << " = std::allocator<" << commandData.enhancedReturnType.substr(12, commandData.enhancedReturnType.find(',') - 12) << ">";
} }
os << ", " << dispatch;
os << "> " << std::endl; os << "> " << std::endl;
} }
else
{
os << indentation << "template<" << dispatch << ">" << std::endl;
}
} }
void VulkanHppGenerator::writeResultEnum(std::ostream & os) void VulkanHppGenerator::writeResultEnum(std::ostream & os)
@ -4771,6 +4818,48 @@ void VulkanHppGenerator::EnumData::addEnumValue(std::string const &name, std::st
} }
} }
void VulkanHppGenerator::writeDelegationClass(std::ostream &os)
{
os << "class DispatchLoader" << std::endl
<< "{" << std::endl
<< "public:\n";
for (auto command : m_commands)
{
enterProtect(os, command.second.protect);
os << " " << command.second.unchangedReturnType << " vk" << startUpperCase(command.second.fullName) << "( ";
bool first = true;
for (auto param : command.second.params)
{
if (!first) {
os << ", ";
}
os << param.unchangedType << " " << param.name;
if (!param.arraySize.empty())
{
os << "[" << param.arraySize << "]";
}
first = false;
}
os << " ) const\n"
<< " {\n"
<< " return ::vk" << startUpperCase(command.second.fullName) << "( ";
first = true;
for (auto param : command.second.params)
{
if (!first) {
os << ", ";
}
os << param.name;
first = false;
}
os << ");\n";
os << " }\n";
leaveProtect(os, command.second.protect);
}
os << "};\n";
}
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
@ -4900,6 +4989,8 @@ int main( int argc, char **argv )
<< resultValueHeader << resultValueHeader
<< createResultValueHeader; << createResultValueHeader;
generator.writeDelegationClass(ofs);
generator.writeTypes(ofs, defaultValues); generator.writeTypes(ofs, defaultValues);
generator.writeStructureChainValidation(ofs); generator.writeStructureChainValidation(ofs);
generator.writeToStringFunctions(ofs); generator.writeToStringFunctions(ofs);

View File

@ -46,6 +46,7 @@ class VulkanHppGenerator
void writeStructureChainValidation(std::ostream & os); void writeStructureChainValidation(std::ostream & os);
void writeToStringFunctions(std::ostream & os); void writeToStringFunctions(std::ostream & os);
void writeTypes(std::ostream & os, std::map<std::string, std::string> const& defaultValues); void writeTypes(std::ostream & os, std::map<std::string, std::string> const& defaultValues);
void writeDelegationClass(std::ostream &os);
#if !defined(NDEBUG) #if !defined(NDEBUG)
void checkExtensionRequirements(); void checkExtensionRequirements();
void skipVendorIDs(tinyxml2::XMLElement const* element); void skipVendorIDs(tinyxml2::XMLElement const* element);
@ -87,6 +88,7 @@ class VulkanHppGenerator
struct ParamData struct ParamData
{ {
std::string type; std::string type;
std::string unchangedType;
std::string name; std::string name;
std::string arraySize; std::string arraySize;
std::string pureType; std::string pureType;
@ -110,6 +112,7 @@ class VulkanHppGenerator
std::string reducedName; std::string reducedName;
size_t returnParam; size_t returnParam;
std::string returnType; std::string returnType;
std::string unchangedReturnType;
std::set<size_t> skippedParams; std::set<size_t> skippedParams;
std::vector<std::string> successCodes; std::vector<std::string> successCodes;
size_t templateParam; size_t templateParam;
@ -211,7 +214,7 @@ class VulkanHppGenerator
bool readCommandParam(tinyxml2::XMLElement const* element, std::set<std::string> & dependencies, std::vector<ParamData> & params); bool readCommandParam(tinyxml2::XMLElement const* element, std::set<std::string> & dependencies, std::vector<ParamData> & params);
tinyxml2::XMLNode const* readCommandParamType(tinyxml2::XMLNode const* node, ParamData& param); tinyxml2::XMLNode const* readCommandParamType(tinyxml2::XMLNode const* node, ParamData& param);
void readCommandsCommand(tinyxml2::XMLElement const* element); void readCommandsCommand(tinyxml2::XMLElement const* element);
void readCommandProto(tinyxml2::XMLElement const* element, std::string & returnType, std::string & fullName); void readCommandProto(tinyxml2::XMLElement const* element, std::string & returnType, std::string & unchangedReturnType, std::string & fullName);
void readDisabledExtensionRequire(tinyxml2::XMLElement const* element); void readDisabledExtensionRequire(tinyxml2::XMLElement const* element);
void readEnumsEnum(tinyxml2::XMLElement const* element, EnumData & enumData, std::string const& tag); void readEnumsEnum(tinyxml2::XMLElement const* element, EnumData & enumData, std::string const& tag);
void readEnumsConstant(tinyxml2::XMLElement const* element); void readEnumsConstant(tinyxml2::XMLElement const* element);
@ -260,9 +263,9 @@ class VulkanHppGenerator
void writeFunctionBodyStandard(std::ostream & os, std::string const& indentation, CommandData const& commandData); void writeFunctionBodyStandard(std::ostream & os, std::string const& indentation, CommandData const& commandData);
void writeFunctionHeaderArguments(std::ostream & os, CommandData const& commandData, bool enhanced, bool singular, bool withDefaults); void writeFunctionHeaderArguments(std::ostream & os, CommandData const& commandData, bool enhanced, bool singular, bool withDefaults);
void writeFunctionHeaderArgumentsEnhanced(std::ostream & os, CommandData const& commandData, bool singular, bool withDefaults); void writeFunctionHeaderArgumentsEnhanced(std::ostream & os, CommandData const& commandData, bool singular, bool withDefaults);
void writeFunctionHeaderArgumentsStandard(std::ostream & os, CommandData const& commandData); void writeFunctionHeaderArgumentsStandard(std::ostream & os, CommandData const& commandData, bool withDefaults);
void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool singular, bool unique, bool isStructureChain); void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool singular, bool unique, bool isStructureChain);
void writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool withDefault, bool isStructureChain); void writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool withDefault, bool isStructureChain);
void writeStructConstructor(std::ostream & os, std::string const& name, StructData const& structData, std::map<std::string, std::string> const& defaultValues); void writeStructConstructor(std::ostream & os, std::string const& name, StructData const& structData, std::map<std::string, std::string> const& defaultValues);
void writeStructSetter(std::ostream & os, std::string const& structureName, MemberData const& memberData); void writeStructSetter(std::ostream & os, std::string const& structureName, MemberData const& memberData);
void writeStructureChainValidation(std::ostream & os, DependencyData const& dependencyData); void writeStructureChainValidation(std::ostream & os, DependencyData const& dependencyData);

@ -1 +1 @@
Subproject commit 4155ac0c7345c760be0b79d44040691a5c4fff06 Subproject commit cc1745b552dd12bb1297a99f82044f83b06729e0

File diff suppressed because it is too large Load Diff