Add support for template strings in code generator to make the code generator more readable. (#103)

Update to Vulkan 1.0.48
This commit is contained in:
Markus Tavenrath 2017-05-11 09:21:14 -07:00 committed by Andreas Süßenbach
parent cd9d4f1388
commit 850e77938f
3 changed files with 187 additions and 132 deletions

@ -1 +1 @@
Subproject commit f985a50c1f0b6f37c706db32d70da85bc1e2d78f
Subproject commit 757a1232e6541db17585d1f59a17dfdaa272c100

View File

@ -25,6 +25,8 @@
#include <string>
#include <vector>
#include <exception>
#include <regex>
#include <iterator>
#include <tinyxml2.h>
@ -600,6 +602,38 @@ const std::string uniqueHandleHeader = R"(
)";
std::string replaceWithMap(std::string const &input, std::map<std::string, std::string> replacements)
{
// This will match ${someVariable} and contain someVariable in match group 1
std::regex re(R"(\$\{([^\}]+)\})");
auto it = std::sregex_iterator(input.begin(), input.end(), re);
auto end = std::sregex_iterator();
// No match, just return the original string
if (it == end)
{
return input;
}
std::string result = "";
while (it != end)
{
std::smatch match = *it;
auto itReplacement = replacements.find(match[1].str());
assert(itReplacement != replacements.end());
result += match.prefix().str() + ((itReplacement != replacements.end()) ? itReplacement->second : match[0].str());
++it;
// we've passed the last match. Append the rest of the orignal string
if (it == end)
{
result += match.suffix().str();
}
}
return result;
}
struct ParamData
{
std::string type;
@ -797,6 +831,7 @@ std::string toCamelCase(std::string const& value);
std::string toUpperCase(std::string const& name);
std::string trimEnd(std::string const& input);
void writeCall(std::ostream & os, CommandData const& commandData, std::set<std::string> const& vkTypes, bool firstCall, bool singular);
std::string generateCall(CommandData const& commandData, std::set<std::string> const& vkTypes, bool firstCall, bool singular);
void writeCallCountParameter(std::ostream & os, CommandData const& commandData, bool singular, std::map<size_t, size_t>::const_iterator it);
void writeCallParameter(std::ostream & os, ParamData const& paramData, std::set<std::string> const& vkTypes);
void writeCallPlainTypeParameter(std::ostream & os, ParamData const& paramData);
@ -1636,31 +1671,31 @@ void readExtensionType(tinyxml2::XMLElement * element, VkData & vkData, std::str
tinyxml2::XMLNode* readType(tinyxml2::XMLNode* element, std::string & type, std::string & pureType)
{
assert(element);
if (element->ToText())
{
std::string value = trimEnd(element->Value());
assert((value == "const") || (value == "struct"));
type = value + " ";
element = element->NextSibling();
assert(element);
}
assert(element);
if (element->ToText())
{
std::string value = trimEnd(element->Value());
assert((value == "const") || (value == "struct"));
type = value + " ";
element = element->NextSibling();
assert(element);
}
assert(element->ToElement());
assert((strcmp(element->Value(), "type") == 0) && element->ToElement() && element->ToElement()->GetText());
pureType = strip(element->ToElement()->GetText(), "Vk");
type += pureType;
assert(element->ToElement());
assert((strcmp(element->Value(), "type") == 0) && element->ToElement() && element->ToElement()->GetText());
pureType = strip(element->ToElement()->GetText(), "Vk");
type += pureType;
element = element->NextSibling();
assert(element);
if (element->ToText())
{
std::string value = trimEnd(element->Value());
assert((value == "*") || (value == "**") || (value == "* const*"));
type += value;
element = element->NextSibling();
}
return element;
element = element->NextSibling();
assert(element);
if (element->ToText())
{
std::string value = trimEnd(element->Value());
assert((value == "*") || (value == "**") || (value == "* const*"));
type += value;
element = element->NextSibling();
}
return element;
}
void readTypeBasetype( tinyxml2::XMLElement * element, std::list<DependencyData> & dependencies )
@ -2065,6 +2100,13 @@ std::string trimEnd(std::string const& input)
return result;
}
std::string generateCall(CommandData const& commandData, std::set<std::string> const& vkTypes, bool firstCall, bool singular)
{
std::ostringstream call;
writeCall(call, commandData, vkTypes, firstCall, singular);
return call.str();
}
void writeCall(std::ostream & os, CommandData const& commandData, std::set<std::string> const& vkTypes, bool firstCall, bool singular)
{
// get the parameter indices of the counter for vector parameters
@ -2374,76 +2416,81 @@ void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation
}
}
void writeFunctionBodyEnhanced(std::ostream &os, std::string const& templateString, std::string const& indentation, std::set<std::string> const& vkTypes, CommandData const& commandData, bool singular)
{
os << replaceWithMap(templateString, {
{ "call", generateCall(commandData, vkTypes, true, singular) },
{ "i", indentation }
});
}
void writeFunctionBodyEnhancedCall(std::ostream &os, std::string const& indentation, std::set<std::string> const& vkTypes, CommandData const& commandData, bool singular)
{
os << indentation << " ";
if (commandData.returnType != "void")
{
os << "return ";
}
writeCall(os, commandData, vkTypes, true, singular);
os << ";" << std::endl;
std::string const templateString = "${i} return ${call};\n";
std::string const templateStringVoid = "${i} ${call};\n";
writeFunctionBodyEnhanced(os, commandData.returnType == "void" ? templateStringVoid : templateString, indentation, vkTypes, commandData, singular);
}
void writeFunctionBodyEnhancedCallResult(std::ostream &os, std::string const& indentation, std::set<std::string> const& vkTypes, CommandData const& commandData, bool singular)
{
os << indentation << " Result result = static_cast<Result>( ";
writeCall(os, commandData, vkTypes, true, singular);
os << " );" << std::endl;
std::string const templateString = "${i} Result result = static_cast<Result>( ${call} );\n";
writeFunctionBodyEnhanced(os, templateString, indentation, vkTypes, commandData, singular);
}
void writeFunctionBodyTwoStep(std::ostream & os, std::string const &templateString, std::string const& indentation, std::set<std::string> const& vkTypes, std::string const& returnName, std::string const& sizeName, CommandData const& commandData)
{
std::map<std::string, std::string> replacements = {
{ "sizeName", sizeName },
{ "returnName", returnName },
{ "call1", generateCall(commandData, vkTypes, true, false) },
{ "call2", generateCall(commandData, vkTypes, false, false) },
{ "i", indentation }
};
os << replaceWithMap(templateString, replacements);
}
void writeFunctionBodyEnhancedCallTwoStep(std::ostream & os, std::string const& indentation, std::set<std::string> const& vkTypes, std::string const& returnName, std::string const& sizeName, CommandData const& commandData)
{
os << indentation << " ";
writeCall(os, commandData, vkTypes, true, false);
os << ";" << std::endl;
// resize the vector to hold the data according to the result from the first call
os << indentation << " " << returnName << ".resize( " << sizeName << " );" << std::endl
<< indentation << " ";
writeCall(os, commandData, vkTypes, false, false);
os << ";" << std::endl;
std::string const templateString =
R"(${i} ${call1};
${i} ${returnName}.resize( ${sizeName} );
${i} ${call2};
)";
writeFunctionBodyTwoStep(os, templateString, indentation, vkTypes, returnName, sizeName, commandData);
}
void writeFunctionBodyEnhancedCallTwoStepChecked(std::ostream & os, std::string const& indentation, std::set<std::string> const& vkTypes, std::string const& returnName, std::string const& sizeName, CommandData const& commandData)
{
os << indentation << " Result result = static_cast<Result>( ";
writeCall(os, commandData, vkTypes, true, false);
os << " );" << std::endl
<< indentation << " if ( ( result == Result::eSuccess ) && " << sizeName << " )" << std::endl
<< indentation << " {" << std::endl
<< indentation << " " << returnName << ".resize( " << sizeName << " );" << std::endl
<< indentation << " result = static_cast<Result>( ";
writeCall(os, commandData, vkTypes, false, false);
os << " );" << std::endl
<< indentation << " }" << std::endl;
std::string const templateString =
R"(${i} Result result = static_cast<Result>( ${call1} );
${i} if ( ( result == Result::eSuccess ) && ${sizeName} )
${i} {
${i} ${returnName}.resize( ${sizeName} );
${i} result = static_cast<Result>( ${call2} );
${i} }
)";
writeFunctionBodyTwoStep(os, templateString, indentation, vkTypes, returnName, sizeName, commandData);
}
void writeFunctionBodyEnhancedCallTwoStepIterate(std::ostream & os, std::string const& indentation, std::set<std::string> const& vkTypes, std::string const& returnName, std::string const& sizeName, CommandData const& commandData)
{
// we need a local variable of type 'Result' to get the results of the calls
os << indentation << " Result result;" << std::endl
<< indentation << " do" << std::endl
<< indentation << " {" << std::endl
<< indentation << " result = static_cast<Result>( ";
writeCall(os, commandData, vkTypes, true, false);
os << " );" << std::endl;
// check if the result was success and the size != 0
os << indentation << " if ( ( result == Result::eSuccess ) && " << sizeName << " )" << std::endl
<< indentation << " {" << std::endl
// resize the vector to hold the data according to the result from the first call
<< indentation << " " << returnName << ".resize( " << sizeName << " );" << std::endl
// we need a static cast again
<< indentation << " result = static_cast<Result>( ";
writeCall(os, commandData, vkTypes, false, false);
os << " );" << std::endl
<< indentation << " }" << std::endl
// close the loop until we got complete data
<< indentation << " } while ( result == Result::eIncomplete );" << std::endl
<< indentation << " assert( " << sizeName << " <= " << returnName << ".size() ); " << std::endl
<< indentation << " " << returnName << ".resize( " << sizeName << " ); " << std::endl;
std::string const templateString =
R"(${i} Result result;
${i} do
${i} {
${i} result = static_cast<Result>( ${call1} );
${i} if ( ( result == Result::eSuccess ) && ${sizeName} )
${i} {
${i} ${returnName}.resize( ${sizeName} );
${i} result = static_cast<Result>( ${call2} );
${i} }
${i} } while ( result == Result::eIncomplete );
${i} assert( ${sizeName} <= ${returnName}.size() );
${i} ${returnName}.resize( ${sizeName} );
)";
writeFunctionBodyTwoStep(os, templateString, indentation, vkTypes, returnName, sizeName, commandData);
}
void writeFunctionBodyEnhancedLocalCountVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData)
@ -2526,6 +2573,18 @@ std::string writeFunctionBodyEnhancedLocalReturnVariable(std::ostream & os, std:
void writeFunctionBodyEnhancedMultiVectorSizeCheck(std::ostream & os, std::string const& indentation, CommandData const& commandData)
{
std::string const templateString =
R"#(#ifdef VULKAN_HPP_NO_EXCEPTIONS
${i} assert( ${firstVectorName}.size() == ${secondVectorName}.size() );
#else
${i} if ( ${firstVectorName}.size() != ${secondVectorName}.size() )
${i} {
${i} throw LogicError( "vk::${className}::${reducedName}: ${firstVectorName}.size() != ${secondVectorName}.size()" );
${i} }
#endif // VULKAN_HPP_NO_EXCEPTIONS
)#";
// add some error checks if multiple vectors need to have the same size
for (std::map<size_t, size_t>::const_iterator it0 = commandData.vectorParams.begin(); it0 != commandData.vectorParams.end(); ++it0)
{
@ -2535,16 +2594,13 @@ void writeFunctionBodyEnhancedMultiVectorSizeCheck(std::ostream & os, std::strin
{
if ((it1->first != commandData.returnParam) && (it0->second == it1->second))
{
std::string firstVectorName = startLowerCase(strip(commandData.params[it0->first].name, "p"));
std::string secondVectorName = startLowerCase(strip(commandData.params[it1->first].name, "p"));
os << "#ifdef VULKAN_HPP_NO_EXCEPTIONS" << std::endl
<< indentation << " assert( " << firstVectorName << ".size() == " << secondVectorName << ".size() );" << std::endl
<< "#else" << std::endl
<< indentation << " if ( " << firstVectorName << ".size() != " << secondVectorName << ".size() )" << std::endl
<< indentation << " {" << std::endl
<< indentation << " throw LogicError( \"vk::" << commandData.className << "::" << commandData.reducedName << ": " << firstVectorName << ".size() != " << secondVectorName << ".size()\" );" << std::endl
<< indentation << " }" << std::endl
<< "#endif // VULKAN_HPP_NO_EXCEPTIONS" << std::endl;
os << replaceWithMap(templateString, std::map<std::string, std::string>( {
{ "firstVectorName", startLowerCase(strip(commandData.params[it0->first].name, "p")) },
{ "secondVectorName", startLowerCase(strip(commandData.params[it1->first].name, "p")) },
{ "className", commandData.className },
{ "reducedName", commandData.reducedName},
{ "i", indentation}
}));
}
}
}
@ -2707,15 +2763,20 @@ void writeFunctionBodyUnique(std::ostream & os, std::string const& indentation,
os << " )";
if (returnsVector)
{
// for vector returns, copy over the results from the non-unique function into a vector of Unique stuff
os << ";" << std::endl
<< indentation << " std::vector<Unique" << type << "> unique" << type << "s;" << std::endl
<< indentation << " unique" << type << "s.reserve( " << typeValue << "s.size() );" << std::endl
<< indentation << " for ( auto " << typeValue << " : " << typeValue << "s )" << std::endl
<< indentation << " {" << std::endl
<< indentation << " unique" << type << "s.push_back( Unique" << type << "( " << typeValue << ", deleter ) );" << std::endl
<< indentation << " }" << std::endl
<< indentation << " return unique" << type << "s;" << std::endl;
std::string const stringTemplate = R"(;
${i} std::vector<Unique${type}> unique${type}s;
${i} unique${type}s.reserve( ${typeValue}s.size() );
${i} for ( auto ${typeValue} : ${typeValue}s )
${i} {
${i} unique${type}s.push_back( Unique${type}( ${typeValue}, deleter ) );
${i} }
${i} return unique${type}s;
)";
os << replaceWithMap(stringTemplate, std::map<std::string, std::string>{
{ "i", indentation },
{ "type", type },
{ "typeValue", typeValue }
});
}
else
{

View File

@ -42,7 +42,7 @@
# include <vector>
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
static_assert( VK_HEADER_VERSION == 46 , "Wrong VK_HEADER_VERSION!" );
static_assert( VK_HEADER_VERSION == 48 , "Wrong VK_HEADER_VERSION!" );
// 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default.
// To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION
@ -6398,9 +6398,6 @@ namespace vk
ePhysicalDeviceExternalBufferInfoKHX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX,
eExternalBufferPropertiesKHX = VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX,
ePhysicalDeviceIdPropertiesKHX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX,
ePhysicalDeviceProperties2KHX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX,
eImageFormatProperties2KHX = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX,
ePhysicalDeviceImageFormatInfo2KHX = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX,
eExternalMemoryBufferCreateInfoKHX = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX,
eExternalMemoryImageCreateInfoKHX = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX,
eExportMemoryAllocateInfoKHX = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX,
@ -28859,9 +28856,6 @@ namespace vk
case StructureType::ePhysicalDeviceExternalBufferInfoKHX: return "PhysicalDeviceExternalBufferInfoKHX";
case StructureType::eExternalBufferPropertiesKHX: return "ExternalBufferPropertiesKHX";
case StructureType::ePhysicalDeviceIdPropertiesKHX: return "PhysicalDeviceIdPropertiesKHX";
case StructureType::ePhysicalDeviceProperties2KHX: return "PhysicalDeviceProperties2KHX";
case StructureType::eImageFormatProperties2KHX: return "ImageFormatProperties2KHX";
case StructureType::ePhysicalDeviceImageFormatInfo2KHX: return "PhysicalDeviceImageFormatInfo2KHX";
case StructureType::eExternalMemoryBufferCreateInfoKHX: return "ExternalMemoryBufferCreateInfoKHX";
case StructureType::eExternalMemoryImageCreateInfoKHX: return "ExternalMemoryImageCreateInfoKHX";
case StructureType::eExportMemoryAllocateInfoKHX: return "ExportMemoryAllocateInfoKHX";