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();
checkEmptyElement(typeElement);
std::string type = strip(node->ToElement()->GetText(), "Vk");
param.unchangedType = param.type + node->ToElement()->GetText();
param.type += type;
param.pureType = type;
@ -1552,6 +1553,7 @@ tinyxml2::XMLNode const* VulkanHppGenerator::readCommandParamType(tinyxml2::XMLN
std::string value = trimEnd(node->Value());
assert((value == "*") || (value == "**") || (value == "* const*"));
param.type += value;
param.unchangedType += value;
node = node->NextSibling();
}
@ -1635,7 +1637,7 @@ void VulkanHppGenerator::readCommandsCommand(tinyxml2::XMLElement const* element
}
else if (value == "proto")
{
readCommandProto(child, commandData.returnType, commandData.fullName);
readCommandProto(child, commandData.returnType, commandData.unchangedReturnType, commandData.fullName);
}
#if !defined(NDEBUG)
else
@ -1661,7 +1663,7 @@ void VulkanHppGenerator::readCommandsCommand(tinyxml2::XMLElement const* element
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(), {}, {});
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
returnType = strip(children[0]->GetText(), "Vk");
unchangedReturnType = children[0]->GetText();
fullName = startLowerCase(strip(children[1]->GetText(), "vk"));
// add an empty DependencyData to this name
@ -2777,7 +2780,7 @@ void VulkanHppGenerator::writeCall(std::ostream & os, CommandData const& command
}
// the original function call
os << "vk" << startUpperCase(commandData.fullName) << "( ";
os << "d.vk" << startUpperCase(commandData.fullName) << "( ";
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)
{
if (enhanced && (!singular || isStructureChain))
{
writeFunctionHeaderTemplate(os, indentation, commandData, !definition, isStructureChain);
}
writeFunctionHeaderTemplate(os, indentation, commandData, enhanced, !definition, isStructureChain);
os << indentation << (definition ? "VULKAN_HPP_INLINE " : "");
writeFunctionHeaderReturnType(os, indentation, commandData, enhanced, singular, unique, isStructureChain);
if (definition && !commandData.className.empty())
@ -3607,7 +3608,7 @@ void VulkanHppGenerator::writeFunctionBodyStandard(std::ostream & os, std::strin
}
// call the original function
os << "vk" << startUpperCase(commandData.fullName) << "( ";
os << "d.vk" << startUpperCase(commandData.fullName) << "( ";
if (!commandData.className.empty())
{
@ -3663,7 +3664,7 @@ void VulkanHppGenerator::writeFunctionHeaderArguments(std::ostream & os, Command
}
else
{
writeFunctionHeaderArgumentsStandard(os, commandData);
writeFunctionHeaderArgumentsStandard(os, commandData, withDefaults);
}
os << ")";
if (!commandData.className.empty())
@ -3805,14 +3806,29 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsEnhanced(std::ostream & os,
argEncountered = true;
}
}
os << " ";
if (argEncountered)
{
os << ", ";
}
}
os << "Dispatch const &d";
if (withDefaults)
{
os << " = Dispatch()";
}
void VulkanHppGenerator::writeFunctionHeaderArgumentsStandard(std::ostream & os, CommandData const& commandData)
os << " ";
}
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
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++)
{
if (argEncountered)
@ -3825,11 +3841,36 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsStandard(std::ostream & os,
{
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;
}
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 } });
}
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'
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
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>'
os << " = std::allocator<" << commandData.enhancedReturnType.substr(12, commandData.enhancedReturnType.find(',') - 12) << ">";
}
os << ", " << dispatch;
os << "> " << std::endl;
}
else
{
os << indentation << "template<" << dispatch << ">" << std::endl;
}
}
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 )
{
@ -4900,6 +4989,8 @@ int main( int argc, char **argv )
<< resultValueHeader
<< createResultValueHeader;
generator.writeDelegationClass(ofs);
generator.writeTypes(ofs, defaultValues);
generator.writeStructureChainValidation(ofs);
generator.writeToStringFunctions(ofs);

View File

@ -46,6 +46,7 @@ class VulkanHppGenerator
void writeStructureChainValidation(std::ostream & os);
void writeToStringFunctions(std::ostream & os);
void writeTypes(std::ostream & os, std::map<std::string, std::string> const& defaultValues);
void writeDelegationClass(std::ostream &os);
#if !defined(NDEBUG)
void checkExtensionRequirements();
void skipVendorIDs(tinyxml2::XMLElement const* element);
@ -87,6 +88,7 @@ class VulkanHppGenerator
struct ParamData
{
std::string type;
std::string unchangedType;
std::string name;
std::string arraySize;
std::string pureType;
@ -110,6 +112,7 @@ class VulkanHppGenerator
std::string reducedName;
size_t returnParam;
std::string returnType;
std::string unchangedReturnType;
std::set<size_t> skippedParams;
std::vector<std::string> successCodes;
size_t templateParam;
@ -211,7 +214,7 @@ class VulkanHppGenerator
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);
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 readEnumsEnum(tinyxml2::XMLElement const* element, EnumData & enumData, std::string const& tag);
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 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 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 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 writeStructSetter(std::ostream & os, std::string const& structureName, MemberData const& memberData);
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