Add support for structure pointer chains & bump version to 1.0.57 (#119)

This commit is contained in:
Markus Tavenrath 2017-08-16 11:46:45 +02:00 committed by Andreas Süßenbach
parent a50ea7dc6c
commit bca6564dac
4 changed files with 454 additions and 50 deletions

View File

@ -155,6 +155,32 @@ vkSubresourceLayout layout = vkGetImageSubResourceLayout(image, subresource);
auto layout = device.getImageSubResourceLayout(image, { {} /* flags*/, 0 /* miplevel */, 0 /* layout */ });
```
# Structure Pointer Chains
Vulkan allows chaining of structures through the pNext pointer. Vulkan-Hpp has a variadic template class which allows constructing of such structure chains with minimal efforts.
In addition to this it checks at compile time if the spec allows the construction of such a pNext chain.
```
// This will compile successfully.
vk::StructureChain<vk::MemoryAllocateInfo, vk::ImportMemoryFdInfoKHR> c;
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
// This will fail compilation since it's not valid according to the spec.
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedRequirementsKHR> c;
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
```
Sometimes the user has to pass a preallocated structure chain to query information. In those cases the corresponding query functions are variadic templates and do accept a structure chain to construct the return value:
```
// Query vk::MemoryRequirements2KHR and vk::MemoryDedicatedRequirementsKHR when calling Device::getBufferMemoryRequirements2KHR:
auto result = device.getBufferMemoryRequirements2KHR<vk::MemoryRequirements2KHR, vk::MemoryDedicatedRequirementsKHR>({});
vk::MemoryRequirements2KHR &memReqs = result.get<vk::MemoryRequirements2KHR>();
vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedRequirementsKHR>();
```
# Return values, Error Codes & Exceptions
By default Vulkan-Hpp has exceptions enabled. This means that Vulkan-Hpp checks the return code of each function call which returns a Vk::Result. If Vk::Result is a failure a std::runtime_error will be thrown.
Since there is no need to return the error code anymore the C++ bindings can now return the actual desired return value, i.e. a vulkan handle. In those cases ResultValue <SomeType>::type is defined as the returned type.

@ -1 +1 @@
Subproject commit 8e6dc96ef04a12dc4018ca682146d953733f105b
Subproject commit a9231ec465ec08eb367fc990ca160fe45d545470

View File

@ -352,6 +352,77 @@ const std::string arrayProxyHeader = R"(
#endif
)";
const std::string structureChainHeader = R"(
template <typename X, typename Y> constexpr bool isStructureChainValid() { return false; }
template <class Element>
class StructureChainElement
{
public:
explicit operator Element&() { return value; }
explicit operator const Element&() const { return value; }
private:
Element value;
};
template<typename ...StructureElements>
class StructureChain : private StructureChainElement<StructureElements>...
{
public:
StructureChain()
{
link<StructureElements...>();
}
StructureChain(StructureChain const &rhs)
{
linkAndCopy<StructureElements...>(rhs);
}
StructureChain& operator=(StructureChain const &rhs)
{
linkAndCopy(rhs);
return this;
}
template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);}
private:
template<typename X>
void link()
{
}
template<typename X, typename Y, typename ...Z>
void link()
{
static_assert(isStructureChainValid<X,Y>(), "The structure chain is not valid!");
X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this);
x.pNext = &y;
link<Y, Z...>();
}
template<typename X>
void linkAndCopy(StructureChain const &rhs)
{
static_cast<X&>(*this) = static_cast<X const &>(rhs);
}
template<typename X, typename Y, typename ...Z>
void linkAndCopy(StructureChain const &rhs)
{
static_assert(isStructureChainValid<X,Y>(), "The structure chain is not valid!");
X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this);
x = static_cast<X const &>(rhs);
x.pNext = &y;
linkAndCopy<Y, Z...>(rhs);
}
};
)";
const std::string versionCheckHeader = R"(
#if !defined(VULKAN_HPP_HAS_UNRESTRICTED_UNIONS)
# if defined(__clang__)
@ -752,6 +823,7 @@ struct StructData
bool isUnion;
std::vector<MemberData> members;
std::string protect;
std::vector<std::string> structExtends;
};
struct DeleterData
@ -771,6 +843,7 @@ struct VkData
std::map<std::string, HandleData> handles;
std::map<std::string, ScalarData> scalars;
std::map<std::string, StructData> structs;
std::set<std::string> extendedStructs; // structs which are referenced by the structextends tag
std::set<std::string> tags;
std::string typesafeCheck;
std::string version;
@ -817,7 +890,7 @@ void readTypeDefine( tinyxml2::XMLElement * element, VkData & vkData );
void readTypeFuncpointer( tinyxml2::XMLElement * element, std::list<DependencyData> & dependencies );
void readTypeHandle(tinyxml2::XMLElement * element, VkData & vkData);
void readTypeStruct( tinyxml2::XMLElement * element, VkData & vkData, bool isUnion );
void readTypeStructMember( tinyxml2::XMLElement * element, std::vector<MemberData> & members, std::set<std::string> & dependencies );
void readTypeStructMember( tinyxml2::XMLElement * element, VkData & vkData, StructData & structData );
void readTags(tinyxml2::XMLElement * element, std::set<std::string> & tags);
void readTypes(tinyxml2::XMLElement * element, VkData & vkData);
std::string reduceName(std::string const& name, bool singular = false);
@ -841,15 +914,15 @@ void writeDeleterClasses(std::ostream & os, std::pair<std::string, std::set<std:
void writeDeleterForwardDeclarations(std::ostream &os, std::pair<std::string, std::set<std::string>> const& deleterTypes, std::map<std::string, DeleterData> const& deleterData);
void writeEnumsToString(std::ostream & os, EnumData const& enumData);
void writeFlagsToString(std::ostream & os, std::string const& flagsName, EnumData const &enumData);
void writeFunction(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique);
void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool singular);
void writeFunction(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique, bool isStructureChain);
void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool singular, bool isStructureChain);
void writeFunctionBodyEnhancedCall(std::ostream &os, std::string const& indentation, std::set<std::string> const& vkTypes, CommandData const& commandData, bool singular);
void writeFunctionBodyEnhancedCallResult(std::ostream &os, std::string const& indentation, std::set<std::string> const& vkTypes, CommandData const& commandData, bool singular);
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);
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);
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);
void writeFunctionBodyEnhancedLocalCountVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData);
std::string writeFunctionBodyEnhancedLocalReturnVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool singular);
std::string writeFunctionBodyEnhancedLocalReturnVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool singular, bool isStructureChain);
void writeFunctionBodyEnhancedMultiVectorSizeCheck(std::ostream & os, std::string const& indentation, CommandData const& commandData);
void writeFunctionBodyEnhancedReturnResultValue(std::ostream & os, std::string const& indentation, std::string const& returnName, CommandData const& commandData, bool singular);
void writeFunctionBodyStandard(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData);
@ -858,8 +931,8 @@ void writeFunctionHeaderArguments(std::ostream & os, VkData const& vkData, Comma
void writeFunctionHeaderArgumentsEnhanced(std::ostream & os, VkData const& vkData, CommandData const& commandData, bool singular, bool withDefaults);
void writeFunctionHeaderArgumentsStandard(std::ostream & os, CommandData const& commandData);
void writeFunctionHeaderName(std::ostream & os, std::string const& name, bool singular, bool unique);
void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool singular, bool unique);
void writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool withDefault);
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 writeReinterpretCast(std::ostream & os, bool leadingConst, bool vulkanType, std::string const& type, bool trailingPointerToConst);
void writeStandardOrEnhanced(std::ostream & os, std::string const& standard, std::string const& enhanced);
void writeStructConstructor( std::ostream & os, std::string const& name, StructData const& structData, std::set<std::string> const& vkTypes, std::map<std::string,std::string> const& defaultValues );
@ -1826,6 +1899,23 @@ void readTypeStruct( tinyxml2::XMLElement * element, VkData & vkData, bool isUni
it->second.returnedOnly = !!element->Attribute( "returnedonly" );
it->second.isUnion = isUnion;
if (element->Attribute("structextends"))
{
std::string structextends = element->Attribute("structextends");
std::vector<std::string> structs;
size_t endPos = -1;
do
{
size_t startPos = endPos + 1;
endPos = structextends.find(',', startPos);
assert(structextends.substr(startPos, 2) == "Vk");
std::string structExtendName = structextends.substr(startPos + 2, endPos - startPos - 2);
it->second.structExtends.push_back(structExtendName);
vkData.extendedStructs.insert(structExtendName);
} while (endPos != std::string::npos);
assert(!it->second.structExtends.empty());
}
for (tinyxml2::XMLElement * child = element->FirstChildElement(); child; child = child->NextSiblingElement())
{
assert( child->Value() );
@ -1833,7 +1923,7 @@ void readTypeStruct( tinyxml2::XMLElement * element, VkData & vkData, bool isUni
assert((value == "comment") || (value == "member"));
if (value == "member")
{
readTypeStructMember(child, it->second.members, vkData.dependencies.back().dependencies);
readTypeStructMember(child, vkData, it->second);
}
}
@ -1841,13 +1931,14 @@ void readTypeStruct( tinyxml2::XMLElement * element, VkData & vkData, bool isUni
vkData.vkTypes.insert( name );
}
void readTypeStructMember(tinyxml2::XMLElement * element, std::vector<MemberData> & members, std::set<std::string> & dependencies)
void readTypeStructMember(tinyxml2::XMLElement * element, VkData & vkData, StructData & structData)
{
members.push_back(MemberData());
MemberData & member = members.back();
structData.members.push_back(MemberData());
MemberData & member = structData.members.back();
tinyxml2::XMLNode* child = readType(element->FirstChild(), member.type, member.pureType);
dependencies.insert(member.pureType);
vkData.dependencies.back().dependencies.insert(member.pureType);
assert((child->ToElement() && strcmp(child->Value(), "name") == 0));
member.name = child->ToElement()->GetText();
@ -2324,14 +2415,14 @@ void writeCallVulkanTypeParameter(std::ostream & os, ParamData const& paramData)
}
}
void writeFunction(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique)
void writeFunction(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool definition, bool enhanced, bool singular, bool unique, bool isStructureChain)
{
if (enhanced && !singular)
if (enhanced && (!singular || isStructureChain))
{
writeFunctionHeaderTemplate(os, indentation, commandData, !definition);
writeFunctionHeaderTemplate(os, indentation, commandData, !definition, isStructureChain);
}
os << indentation << (definition ? "VULKAN_HPP_INLINE " : "");
writeFunctionHeaderReturnType(os, indentation, commandData, enhanced, singular, unique);
writeFunctionHeaderReturnType(os, indentation, commandData, enhanced, singular, unique, isStructureChain);
if (definition && !commandData.className.empty())
{
os << commandData.className << "::";
@ -2352,7 +2443,7 @@ void writeFunction(std::ostream & os, std::string const& indentation, VkData con
}
else
{
writeFunctionBodyEnhanced(os, indentation, vkData, commandData, singular);
writeFunctionBodyEnhanced(os, indentation, vkData, commandData, singular, isStructureChain);
}
}
else
@ -2363,7 +2454,7 @@ void writeFunction(std::ostream & os, std::string const& indentation, VkData con
}
}
void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool singular)
void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation, VkData const& vkData, CommandData const& commandData, bool singular, bool isStructureChain)
{
if (1 < commandData.vectorParams.size())
{
@ -2373,7 +2464,7 @@ void writeFunctionBodyEnhanced(std::ostream & os, std::string const& indentation
std::string returnName;
if (commandData.returnParam != ~0)
{
returnName = writeFunctionBodyEnhancedLocalReturnVariable(os, indentation, commandData, singular);
returnName = writeFunctionBodyEnhancedLocalReturnVariable(os, indentation, commandData, singular, isStructureChain);
}
if (commandData.twoStep)
@ -2515,25 +2606,48 @@ void writeFunctionBodyEnhancedLocalCountVariable(std::ostream & os, std::string
os << indentation << " " << commandData.params[returnit->second].pureType << " " << startLowerCase(strip(commandData.params[returnit->second].name, "p")) << ";" << std::endl;
}
std::string writeFunctionBodyEnhancedLocalReturnVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool singular)
std::string writeFunctionBodyEnhancedLocalReturnVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool singular, bool isStructureChain)
{
std::string returnName = startLowerCase(strip(commandData.params[commandData.returnParam].name, "p"));
// there is a returned parameter -> we need a local variable to hold that value
if (commandData.returnType != commandData.enhancedReturnType)
{
// the returned parameter is somehow enanced by us
// the returned parameter is somehow enhanced by us
os << indentation << " ";
if (singular)
{
if (isStructureChain)
{
std::string const &pureType = commandData.params[commandData.returnParam].pureType;
// For StructureChains use the template parameters
os << "StructureChain<T...> structureChain;" << std::endl;
returnName = stripPluralS(returnName);
os << indentation << " " << pureType << "& " << returnName << " = structureChain.template get<" << pureType << ">()";
returnName = "structureChain";
}
else
{
// in singular case, just use the return parameters pure type for the return variable
returnName = stripPluralS(returnName);
os << commandData.params[commandData.returnParam].pureType << " " << returnName;
}
}
else
{
// in non-singular case, use the enhanced type for the return variable (like vector<...>)
if (isStructureChain)
{
std::string const &returnType = commandData.enhancedReturnType;
// For StructureChains use the template parameters
os << "StructureChain<T...> structureChain;" << std::endl;
os << indentation << " " << returnType << "& " << returnName << " = structureChain.template get<" << returnType << ">()";
returnName = "structureChain";
}
else
{
os << commandData.enhancedReturnType << " " << returnName;
}
std::map<size_t, size_t>::const_iterator it = commandData.vectorParams.find(commandData.returnParam);
if (it != commandData.vectorParams.end() && !commandData.twoStep)
@ -2982,7 +3096,7 @@ void writeFunctionHeaderName(std::ostream & os, std::string const& name, bool si
}
}
void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool singular, bool unique)
void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool enhanced, bool singular, bool unique, bool isStructureChain)
{
std::string templateString;
std::string returnType;
@ -2994,38 +3108,43 @@ void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indenta
// the unique version returns something prefixed with 'Unique'; potentially a vector of that stuff
// it's a vector, if it's not the singular version and the return parameter is a vector parameter
bool returnsVector = !singular && (commandData.vectorParams.find(commandData.returnParam) != commandData.vectorParams.end());
templateString = returnsVector ? "std::vector<Unique${returnType}> " : "Unique${returnType} ";
returnType = commandData.params[commandData.returnParam].pureType;
//os << replaceWithMap(, {{"returnType", commandData.params[commandData.returnParam].pureType }});
returnType = isStructureChain ? "StructureChain<T...>" : commandData.params[commandData.returnParam].pureType;
}
else if ((commandData.enhancedReturnType != commandData.returnType) && (commandData.returnType != "void"))
{
// if the enhanced return type differs from the original return type, and it's not void, we return a ResultValueType<...>::type
if (!singular && (commandData.enhancedReturnType.find("Allocator") != std::string::npos))
if (isStructureChain || (!singular && (commandData.enhancedReturnType.find("Allocator") != std::string::npos)))
{
// for the non-singular case with allocation, we need to prepend with 'typename' to keep compilers happy
templateString = "typename ResultValueType<${returnType}>::type ";
templateString = "typename ";
}
templateString += "ResultValueType<${returnType}>::type ";
assert(commandData.returnType == "Result");
// in singular case, we create the ResultValueType from the pure return type, otherwise from the enhanced return type
if (isStructureChain)
{
returnType = "StructureChain<T...>";
}
else
{
templateString = "ResultValueType<${returnType}>::type ";
}
assert(commandData.returnType == "Result");
// in singular case, we create the ResultValueType from the pure return type, otherwise from the enhanced return type
returnType = singular ? commandData.params[commandData.returnParam].pureType : commandData.enhancedReturnType;
}
}
else if ((commandData.returnParam != ~0) && (1 < commandData.successCodes.size()))
{
// if there is a return parameter at all, and there are multiple success codes, we return a ResultValue<...> with the pure return type
assert(commandData.returnType == "Result");
templateString = "ResultValue<${returnType}> ";
returnType = commandData.params[commandData.returnParam].pureType;
returnType = isStructureChain ? "StructureChain<T...>" : commandData.params[commandData.returnParam].pureType;
}
else
{
// and in every other case, we just return the enhanced return type.
templateString = "${returnType} ";
returnType = commandData.enhancedReturnType;
returnType = isStructureChain ? "StructureChain<T...>" : commandData.enhancedReturnType;
}
}
else
@ -3037,9 +3156,13 @@ void writeFunctionHeaderReturnType(std::ostream & os, std::string const& indenta
os << replaceWithMap(templateString, { { "returnType", returnType } });
}
void writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool withDefault)
void writeFunctionHeaderTemplate(std::ostream & os, std::string const& indentation, CommandData const& commandData, bool withDefault, bool isStructureChain)
{
if ((commandData.templateParam != ~0) && ((commandData.templateParam != commandData.returnParam) || (commandData.enhancedReturnType == "Result")))
if (isStructureChain)
{
os << indentation << "template <typename ...T>" << std::endl;
}
else if ((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);
@ -3275,20 +3398,27 @@ void writeTypeCommand(std::ostream & os, std::string const& indentation, VkData
{
enterProtect(os, commandData.protect);
bool isStructureChain = vkData.extendedStructs.find(commandData.enhancedReturnType) != vkData.extendedStructs.end();
// first create the standard version of the function
std::ostringstream standard;
writeFunction(standard, indentation, vkData, commandData, definition, false, false, false);
writeFunction(standard, indentation, vkData, commandData, definition, false, false, false, false);
// then the enhanced version, composed by up to four parts
// then the enhanced version, composed by up to five parts
std::ostringstream enhanced;
writeFunction(enhanced, indentation, vkData, commandData, definition, true, false, false);
writeFunction(enhanced, indentation, vkData, commandData, definition, true, false, false, false);
if (isStructureChain)
{
writeFunction(enhanced, indentation, vkData, commandData, definition, true, false, false, true);
}
// then a singular version, if a sized vector would be returned
std::map<size_t, size_t>::const_iterator returnVector = commandData.vectorParams.find(commandData.returnParam);
bool singular = (returnVector != commandData.vectorParams.end()) && (returnVector->second != ~0) && (commandData.params[returnVector->second].type.back() != '*');
if (singular)
{
writeFunction(enhanced, indentation, vkData, commandData, definition, true, true, false);
writeFunction(enhanced, indentation, vkData, commandData, definition, true, true, false, false);
}
// special handling for createDevice and createInstance !
@ -3298,11 +3428,11 @@ void writeTypeCommand(std::ostream & os, std::string const& indentation, VkData
if (((vkData.deleterData.find(commandData.className) != vkData.deleterData.end()) || specialWriteUnique) && ((commandData.reducedName.substr(0, 8) == "allocate") || (commandData.reducedName.substr(0, 6) == "create")))
{
enhanced << "#ifndef VULKAN_HPP_NO_SMART_HANDLE" << std::endl;
writeFunction(enhanced, indentation, vkData, commandData, definition, true, false, true);
writeFunction(enhanced, indentation, vkData, commandData, definition, true, false, true, false);
if (singular)
{
writeFunction(enhanced, indentation, vkData, commandData, definition, true, true, true);
writeFunction(enhanced, indentation, vkData, commandData, definition, true, true, true, false);
}
enhanced << "#endif /*VULKAN_HPP_NO_SMART_HANDLE*/" << std::endl;
}
@ -3898,6 +4028,29 @@ void writeTypeStruct( std::ostream & os, VkData const& vkData, DependencyData co
os << std::endl;
}
void writeStructureChainValidation(std::ostream & os, VkData const& vkData, DependencyData const& dependencyData)
{
std::map<std::string, StructData>::const_iterator it = vkData.structs.find(dependencyData.name);
assert(it != vkData.structs.end());
if (!it->second.structExtends.empty()) {
enterProtect(os, it->second.protect);
// write out allowed structure chains
for (auto extendName : it->second.structExtends)
{
std::map<std::string, StructData>::const_iterator itExtend = vkData.structs.find(extendName);
assert(itExtend != vkData.structs.end());
enterProtect(os, itExtend->second.protect);
os << " template <> constexpr bool isStructureChainValid<" << extendName << ", " << dependencyData.name << ">() { return true; }" << std::endl;
leaveProtect(os, itExtend->second.protect);
}
leaveProtect(os, it->second.protect);
}
}
void writeTypeUnion( std::ostream & os, VkData const& vkData, DependencyData const& dependencyData, std::map<std::string,std::string> const& defaultValues )
{
std::map<std::string, StructData>::const_iterator it = vkData.structs.find(dependencyData.name);
@ -4167,7 +4320,8 @@ int main( int argc, char **argv )
<< flagsHeader
<< optionalClassHeader
<< arrayProxyHeader
<< uniqueHandleHeader;
<< uniqueHandleHeader
<< structureChainHeader;
// first of all, write out vk::Result and the exception handling stuff
std::list<DependencyData>::const_iterator it = std::find_if(vkData.dependencies.begin(), vkData.dependencies.end(), [](DependencyData const& dp) { return dp.name == "Result"; });
@ -4199,6 +4353,17 @@ int main( int argc, char **argv )
assert(vkData.deleterTypes.find("") != vkData.deleterTypes.end());
writeTypes(ofs, vkData, defaultValues);
// write all template functions for the structure pointer chain validation
for (auto it = vkData.dependencies.begin(); it != vkData.dependencies.end(); ++it)
{
switch (it->category)
{
case DependencyData::Category::STRUCT:
writeStructureChainValidation(ofs, vkData, *it);
break;
}
}
// write all the to_string functions for enums and flags
for (auto it = vkData.dependencies.begin(); it != vkData.dependencies.end(); ++it)
{

View File

@ -33,7 +33,7 @@
# include <memory>
# include <vector>
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
static_assert( VK_HEADER_VERSION == 55 , "Wrong VK_HEADER_VERSION!" );
static_assert( VK_HEADER_VERSION == 57 , "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
@ -425,6 +425,75 @@ namespace vk
}
#endif
template <typename X, typename Y> constexpr bool isStructureChainValid() { return false; }
template <class Element>
class StructureChainElement
{
public:
explicit operator Element&() { return value; }
explicit operator const Element&() const { return value; }
private:
Element value;
};
template<typename ...StructureElements>
class StructureChain : private StructureChainElement<StructureElements>...
{
public:
StructureChain()
{
link<StructureElements...>();
}
StructureChain(StructureChain const &rhs)
{
linkAndCopy<StructureElements...>(rhs);
}
StructureChain& operator=(StructureChain const &rhs)
{
linkAndCopy<StructureElements...>(rhs);
return *this;
}
template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);}
private:
template<typename X>
void link()
{
}
template<typename X, typename Y, typename ...Z>
void link()
{
static_assert(isStructureChainValid<X,Y>(), "The structure chain is not valid!");
X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this);
x.pNext = &y;
link<Y, Z...>();
}
template<typename X>
void linkAndCopy(StructureChain const &rhs)
{
static_cast<X&>(*this) = static_cast<X const &>(rhs);
}
template<typename X, typename Y, typename ...Z>
void linkAndCopy(StructureChain const &rhs)
{
static_assert(isStructureChainValid<X,Y>(), "The structure chain is not valid!");
X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this);
x = static_cast<X const &>(rhs);
x.pNext = &y;
linkAndCopy<Y, Z...>(rhs);
}
};
enum class Result
{
eSuccess = VK_SUCCESS,
@ -25710,11 +25779,15 @@ namespace vk
void getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2KHR* pInfo, MemoryRequirements2KHR* pMemoryRequirements ) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
MemoryRequirements2KHR getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2KHR & info ) const;
template <typename ...T>
StructureChain<T...> getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2KHR & info ) const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
void getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2KHR* pInfo, MemoryRequirements2KHR* pMemoryRequirements ) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
MemoryRequirements2KHR getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2KHR & info ) const;
template <typename ...T>
StructureChain<T...> getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2KHR & info ) const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
void getImageSparseMemoryRequirements2KHR( const ImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, SparseImageMemoryRequirements2KHR* pSparseMemoryRequirements ) const;
@ -27949,6 +28022,14 @@ namespace vk
vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2KHR*>( &info ), reinterpret_cast<VkMemoryRequirements2KHR*>( &memoryRequirements ) );
return memoryRequirements;
}
template <typename ...T>
VULKAN_HPP_INLINE StructureChain<T...> Device::getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2KHR & info ) const
{
StructureChain<T...> structureChain;
MemoryRequirements2KHR& memoryRequirements = structureChain.template get<MemoryRequirements2KHR>();
vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2KHR*>( &info ), reinterpret_cast<VkMemoryRequirements2KHR*>( &memoryRequirements ) );
return structureChain;
}
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
VULKAN_HPP_INLINE void Device::getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2KHR* pInfo, MemoryRequirements2KHR* pMemoryRequirements ) const
@ -27962,6 +28043,14 @@ namespace vk
vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2KHR*>( &info ), reinterpret_cast<VkMemoryRequirements2KHR*>( &memoryRequirements ) );
return memoryRequirements;
}
template <typename ...T>
VULKAN_HPP_INLINE StructureChain<T...> Device::getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2KHR & info ) const
{
StructureChain<T...> structureChain;
MemoryRequirements2KHR& memoryRequirements = structureChain.template get<MemoryRequirements2KHR>();
vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2KHR*>( &info ), reinterpret_cast<VkMemoryRequirements2KHR*>( &memoryRequirements ) );
return structureChain;
}
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
VULKAN_HPP_INLINE void Device::getImageSparseMemoryRequirements2KHR( const ImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, SparseImageMemoryRequirements2KHR* pSparseMemoryRequirements ) const
@ -28188,11 +28277,15 @@ namespace vk
void getFeatures2KHR( PhysicalDeviceFeatures2KHR* pFeatures ) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
PhysicalDeviceFeatures2KHR getFeatures2KHR() const;
template <typename ...T>
StructureChain<T...> getFeatures2KHR() const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
void getProperties2KHR( PhysicalDeviceProperties2KHR* pProperties ) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
PhysicalDeviceProperties2KHR getProperties2KHR() const;
template <typename ...T>
StructureChain<T...> getProperties2KHR() const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
void getFormatProperties2KHR( Format format, FormatProperties2KHR* pFormatProperties ) const;
@ -28203,6 +28296,8 @@ namespace vk
Result getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, ImageFormatProperties2KHR* pImageFormatProperties ) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
ResultValueType<ImageFormatProperties2KHR>::type getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2KHR & imageFormatInfo ) const;
template <typename ...T>
typename ResultValueType<StructureChain<T...>>::type getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2KHR & imageFormatInfo ) const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
void getQueueFamilyProperties2KHR( uint32_t* pQueueFamilyPropertyCount, QueueFamilyProperties2KHR* pQueueFamilyProperties ) const;
@ -28271,6 +28366,8 @@ namespace vk
Result getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, SurfaceCapabilities2KHR* pSurfaceCapabilities ) const;
#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
ResultValueType<SurfaceCapabilities2KHR>::type getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo ) const;
template <typename ...T>
typename ResultValueType<StructureChain<T...>>::type getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo ) const;
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
Result getSurfaceFormats2KHR( const PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, SurfaceFormat2KHR* pSurfaceFormats ) const;
@ -28795,6 +28892,14 @@ namespace vk
vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2KHR*>( &features ) );
return features;
}
template <typename ...T>
VULKAN_HPP_INLINE StructureChain<T...> PhysicalDevice::getFeatures2KHR() const
{
StructureChain<T...> structureChain;
PhysicalDeviceFeatures2KHR& features = structureChain.template get<PhysicalDeviceFeatures2KHR>();
vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2KHR*>( &features ) );
return structureChain;
}
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
VULKAN_HPP_INLINE void PhysicalDevice::getProperties2KHR( PhysicalDeviceProperties2KHR* pProperties ) const
@ -28808,6 +28913,14 @@ namespace vk
vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2KHR*>( &properties ) );
return properties;
}
template <typename ...T>
VULKAN_HPP_INLINE StructureChain<T...> PhysicalDevice::getProperties2KHR() const
{
StructureChain<T...> structureChain;
PhysicalDeviceProperties2KHR& properties = structureChain.template get<PhysicalDeviceProperties2KHR>();
vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2KHR*>( &properties ) );
return structureChain;
}
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
VULKAN_HPP_INLINE void PhysicalDevice::getFormatProperties2KHR( Format format, FormatProperties2KHR* pFormatProperties ) const
@ -28834,6 +28947,14 @@ namespace vk
Result result = static_cast<Result>( vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2KHR*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2KHR*>( &imageFormatProperties ) ) );
return createResultValue( result, imageFormatProperties, "vk::PhysicalDevice::getImageFormatProperties2KHR" );
}
template <typename ...T>
VULKAN_HPP_INLINE typename ResultValueType<StructureChain<T...>>::type PhysicalDevice::getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2KHR & imageFormatInfo ) const
{
StructureChain<T...> structureChain;
ImageFormatProperties2KHR& imageFormatProperties = structureChain.template get<ImageFormatProperties2KHR>();
Result result = static_cast<Result>( vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2KHR*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2KHR*>( &imageFormatProperties ) ) );
return createResultValue( result, structureChain, "vk::PhysicalDevice::getImageFormatProperties2KHR" );
}
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
VULKAN_HPP_INLINE void PhysicalDevice::getQueueFamilyProperties2KHR( uint32_t* pQueueFamilyPropertyCount, QueueFamilyProperties2KHR* pQueueFamilyProperties ) const
@ -29015,6 +29136,14 @@ namespace vk
Result result = static_cast<Result>( vkGetPhysicalDeviceSurfaceCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), reinterpret_cast<VkSurfaceCapabilities2KHR*>( &surfaceCapabilities ) ) );
return createResultValue( result, surfaceCapabilities, "vk::PhysicalDevice::getSurfaceCapabilities2KHR" );
}
template <typename ...T>
VULKAN_HPP_INLINE typename ResultValueType<StructureChain<T...>>::type PhysicalDevice::getSurfaceCapabilities2KHR( const PhysicalDeviceSurfaceInfo2KHR & surfaceInfo ) const
{
StructureChain<T...> structureChain;
SurfaceCapabilities2KHR& surfaceCapabilities = structureChain.template get<SurfaceCapabilities2KHR>();
Result result = static_cast<Result>( vkGetPhysicalDeviceSurfaceCapabilities2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSurfaceInfo2KHR*>( &surfaceInfo ), reinterpret_cast<VkSurfaceCapabilities2KHR*>( &surfaceCapabilities ) ) );
return createResultValue( result, structureChain, "vk::PhysicalDevice::getSurfaceCapabilities2KHR" );
}
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
VULKAN_HPP_INLINE Result PhysicalDevice::getSurfaceFormats2KHR( const PhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pSurfaceFormatCount, SurfaceFormat2KHR* pSurfaceFormats ) const
@ -29939,6 +30068,90 @@ namespace vk
#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
template <> constexpr bool isStructureChainValid<PresentInfoKHR, DisplayPresentInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<ImageCreateInfo, DedicatedAllocationImageCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<BufferCreateInfo, DedicatedAllocationBufferCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, DedicatedAllocationMemoryAllocateInfoNV>() { return true; }
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ExportMemoryWin32HandleInfoNV>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<SubmitInfo, Win32KeyedMutexAcquireReleaseInfoNV>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
template <> constexpr bool isStructureChainValid<DeviceCreateInfo, PhysicalDeviceFeatures2KHR>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDevicePushDescriptorPropertiesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<PresentInfoKHR, PresentRegionsKHR>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceFeatures2KHR, PhysicalDeviceVariablePointerFeaturesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<DeviceCreateInfo, PhysicalDeviceVariablePointerFeaturesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDeviceIDPropertiesKHR>() { return true; }
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ExportMemoryWin32HandleInfoKHR>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<SubmitInfo, Win32KeyedMutexAcquireReleaseInfoKHR>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<SemaphoreCreateInfo, ExportSemaphoreWin32HandleInfoKHR>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<SubmitInfo, D3D12FenceSubmitInfoKHR>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<FenceCreateInfo, ExportFenceWin32HandleInfoKHR>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
template <> constexpr bool isStructureChainValid<PhysicalDeviceFeatures2KHR, PhysicalDeviceMultiviewFeaturesKHX>() { return true; }
template <> constexpr bool isStructureChainValid<DeviceCreateInfo, PhysicalDeviceMultiviewFeaturesKHX>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDeviceMultiviewPropertiesKHX>() { return true; }
template <> constexpr bool isStructureChainValid<RenderPassCreateInfo, RenderPassMultiviewCreateInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<RenderPassBeginInfo, DeviceGroupRenderPassBeginInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<CommandBufferBeginInfo, DeviceGroupCommandBufferBeginInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<SubmitInfo, DeviceGroupSubmitInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<BindSparseInfo, DeviceGroupBindSparseInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<ImageCreateInfo, ImageSwapchainCreateInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<BindImageMemoryInfoKHX, BindImageMemorySwapchainInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<PresentInfoKHR, PresentTimesInfoGOOGLE>() { return true; }
template <> constexpr bool isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportWScalingStateCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDeviceDiscardRectanglePropertiesEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceFeatures2KHR, PhysicalDevice16BitStorageFeaturesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<DeviceCreateInfo, PhysicalDevice16BitStorageFeaturesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<MemoryRequirements2KHR, MemoryDedicatedRequirementsKHR>() { return true; }
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, MemoryDedicatedAllocateInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<ImageFormatProperties2KHR, TextureLODGatherFormatPropertiesAMD>() { return true; }
template <> constexpr bool isStructureChainValid<PipelineMultisampleStateCreateInfo, PipelineCoverageToColorStateCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDeviceSamplerFilterMinmaxPropertiesEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceFeatures2KHR, PhysicalDeviceBlendOperationAdvancedFeaturesEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceProperties2KHR, PhysicalDeviceBlendOperationAdvancedPropertiesEXT>() { return true; }
template <> constexpr bool isStructureChainValid<SurfaceCapabilities2KHR, SharedPresentSurfaceCapabilitiesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<InstanceCreateInfo, DebugReportCallbackCreateInfoEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationStateRasterizationOrderAMD>() { return true; }
template <> constexpr bool isStructureChainValid<ImageCreateInfo, ExternalMemoryImageCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ExportMemoryAllocateInfoNV>() { return true; }
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ImportMemoryWin32HandleInfoNV>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
template <> constexpr bool isStructureChainValid<InstanceCreateInfo, ValidationFlagsEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PhysicalDeviceImageFormatInfo2KHR, PhysicalDeviceExternalImageFormatInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<ImageCreateInfo, ExternalMemoryImageCreateInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<BufferCreateInfo, ExternalMemoryBufferCreateInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ExportMemoryAllocateInfoKHR>() { return true; }
#ifdef VK_USE_PLATFORM_WIN32_KHR
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ImportMemoryWin32HandleInfoKHR>() { return true; }
#endif /*VK_USE_PLATFORM_WIN32_KHR*/
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, ImportMemoryFdInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<ImageFormatProperties2KHR, ExternalImageFormatPropertiesKHR>() { return true; }
template <> constexpr bool isStructureChainValid<SemaphoreCreateInfo, ExportSemaphoreCreateInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<FenceCreateInfo, ExportFenceCreateInfoKHR>() { return true; }
template <> constexpr bool isStructureChainValid<SwapchainCreateInfoKHR, SwapchainCounterCreateInfoEXT>() { return true; }
template <> constexpr bool isStructureChainValid<MemoryAllocateInfo, MemoryAllocateFlagsInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<PresentInfoKHR, DeviceGroupPresentInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<SwapchainCreateInfoKHR, DeviceGroupSwapchainCreateInfoKHX>() { return true; }
template <> constexpr bool isStructureChainValid<PipelineViewportStateCreateInfo, PipelineViewportSwizzleStateCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<GraphicsPipelineCreateInfo, PipelineDiscardRectangleStateCreateInfoEXT>() { return true; }
template <> constexpr bool isStructureChainValid<SamplerCreateInfo, SamplerReductionModeCreateInfoEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PipelineColorBlendStateCreateInfo, PipelineColorBlendAdvancedStateCreateInfoEXT>() { return true; }
template <> constexpr bool isStructureChainValid<PipelineMultisampleStateCreateInfo, PipelineCoverageModulationStateCreateInfoNV>() { return true; }
template <> constexpr bool isStructureChainValid<DeviceCreateInfo, DeviceGroupDeviceCreateInfoKHX>() { return true; }
VULKAN_HPP_INLINE std::string to_string(FramebufferCreateFlagBits)
{
return "(void)";