update generator and generated header file with owner type

This commit is contained in:
dokipen3d 2018-09-25 22:33:47 +12:00
commit ef1b128ff5
10 changed files with 7890 additions and 5787 deletions

View File

@ -78,7 +78,11 @@ set_property(TARGET VulkanHppGenerator PROPERTY CXX_STANDARD 11)
target_include_directories(VulkanHppGenerator PRIVATE "${CMAKE_SOURCE_DIR}/tinyxml2")
option (SAMPLES_BUILD OFF)
if (SAMPLES_BUILD)
add_subdirectory(samples)
endif (SAMPLES_BUILD)
option (TESTS_BUILD OFF)
if (TESTS_BUILD)
add_subdirectory(tests)
endif (TESTS_BUILD)

View File

@ -191,15 +191,22 @@ vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> c =
};
```
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:
Sometimes the user has to pass a preallocated structure chain to query information. For those cases there are two corresponding getter functions. One with a variadic template generating a structure chain of at least two elements to construct the return value:
```
// Query vk::MemoryRequirements2KHR and vk::MemoryDedicatedRequirementsKHR when calling Device::getBufferMemoryRequirements2KHR:
// Query vk::MemoryRequirements2HR 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>();
```
To get just the base structure, without chaining, the other getter function provided does not need a template argument for the structure to get:
```
// Query just vk::MemoryRequirements2KHR
vk::MemoryRequirements2KHR memoryRequirements = device.getBufferMemoryRequirements2KHR({});
```
### 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 dd9919749a56177c2eb9b6525c0979722a3c24ff
Subproject commit 9858c1e89e21246f779226d2be779fd33bb6a50d

View File

@ -23,6 +23,8 @@
#include <iterator>
#include "VulkanHppGenerator.hpp"
const size_t INVALID_INDEX = (size_t)~0;
const std::string vkNamespace = R"(
#if !defined(VULKAN_HPP_NAMESPACE)
#define VULKAN_HPP_NAMESPACE vk
@ -372,8 +374,34 @@ const std::string arrayProxyHeader = R"(
)";
const std::string structureChainHeader = R"(
template <typename X, typename Y> struct isStructureChainValid { enum { value = false }; };
template <typename P, typename T>
struct TypeList
{
using list = P;
using last = T;
};
template <typename List, typename X>
struct extendCheck
{
static const bool valid = isStructureChainValid<typename List::last, X>::value || extendCheck<typename List::list,X>::valid;
};
template <typename T, typename X>
struct extendCheck<TypeList<void,T>,X>
{
static const bool valid = isStructureChainValid<T, X>::value;
};
template <typename X>
struct extendCheck<void,X>
{
static const bool valid = true;
};
template <class Element>
class StructureChainElement
{
@ -390,75 +418,78 @@ const std::string structureChainHeader = R"(
public:
StructureChain()
{
link<StructureElements...>();
link<void, StructureElements...>();
}
StructureChain(StructureChain const &rhs)
{
linkAndCopy<StructureElements...>(rhs);
linkAndCopy<void, StructureElements...>(rhs);
}
StructureChain(StructureElements const &... elems)
{
linkAndCopyElements<StructureElements...>(elems...);
linkAndCopyElements<void, StructureElements...>(elems...);
}
StructureChain& operator=(StructureChain const &rhs)
{
linkAndCopy<StructureElements...>(rhs);
linkAndCopy<void, StructureElements...>(rhs);
return *this;
}
template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);}
private:
template<typename X>
template<typename List, typename X>
void link()
{
static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
}
template<typename X, typename Y, typename ...Z>
template<typename List, typename X, typename Y, typename ...Z>
void link()
{
static_assert(isStructureChainValid<X,Y>::value, "The structure chain is not valid!");
static_assert(extendCheck<List,X>::valid, "The structure chain is not valid!");
X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this);
x.pNext = &y;
link<Y, Z...>();
link<TypeList<List, X>, Y, Z...>();
}
template<typename X>
template<typename List, typename X>
void linkAndCopy(StructureChain const &rhs)
{
static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
static_cast<X&>(*this) = static_cast<X const &>(rhs);
}
template<typename X, typename Y, typename ...Z>
template<typename List, typename X, typename Y, typename ...Z>
void linkAndCopy(StructureChain const &rhs)
{
static_assert(isStructureChainValid<X,Y>::value, "The structure chain is not valid!");
static_assert(extendCheck<List, X>::valid, "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);
linkAndCopy<TypeList<List, X>, Y, Z...>(rhs);
}
template<typename X>
template<typename List, typename X>
void linkAndCopyElements(X const &xelem)
{
static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
static_cast<X&>(*this) = xelem;
}
template<typename X, typename Y, typename ...Z>
template<typename List, typename X, typename Y, typename ...Z>
void linkAndCopyElements(X const &xelem, Y const &yelem, Z const &... zelem)
{
static_assert(isStructureChainValid<X,Y>::value, "The structure chain is not valid!");
static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this);
x = xelem;
x.pNext = &y;
linkAndCopyElements<Y, Z...>(yelem, zelem...);
linkAndCopyElements<TypeList<List, X>, Y, Z...>(yelem, zelem...);
}
};
@ -637,12 +668,17 @@ const std::string uniqueHandleHeader = R"(
using Owner = typename UniqueHandleTraits<Type,Dispatch>::owner;
using Deleter = typename UniqueHandleTraits<Type,Dispatch>::deleter;
public:
explicit UniqueHandle( Type const& value = Type(), Deleter const& deleter = Deleter() )
explicit UniqueHandle( Type const& value = Type() )
: UniqueHandle(value, Deleter())
{}
explicit UniqueHandle( Type const& value, Deleter const& deleter = Deleter() )
: Deleter( deleter)
, m_value( value )
{}
explicit UniqueHandle( Type const& value = Type(), Owner const& owner = Owner() )
explicit UniqueHandle( Type const& value, Owner const& owner = Owner() )
: Deleter( owner)
, m_value( value )
{}
@ -1393,7 +1429,7 @@ bool VulkanHppGenerator::containsUnion(std::string const& type, std::map<std::st
std::map<std::string, std::string> VulkanHppGenerator::createDefaults()
{
std::map<std::string, std::string> defaultValues;
for (auto dependency : m_dependencies)
for (auto const& dependency : m_dependencies)
{
assert(defaultValues.find(dependency.name) == defaultValues.end());
switch (dependency.category)
@ -1431,7 +1467,7 @@ void VulkanHppGenerator::determineEnhancedReturnType(CommandData & commandData)
// if there is a return parameter of type void or Result, and if it's of type Result it either has just one success code
// or two success codes, where the second one is of type eIncomplete and it's a two-step process
// -> we can return that parameter
if ((commandData.returnParam != ~0)
if ((commandData.returnParam != INVALID_INDEX)
&& ((commandData.returnType == "void")
|| ((commandData.returnType == "Result")
&& ((commandData.successCodes.size() == 1)
@ -1508,29 +1544,33 @@ void VulkanHppGenerator::determineReturnParam(CommandData & commandData)
{
if ((commandData.params[i].type.find('*') != std::string::npos)
&& (commandData.params[i].type.find("const") == std::string::npos)
&& std::find_if(commandData.vectorParams.begin(), commandData.vectorParams.end(), [i](std::pair<size_t, size_t> const& vp) { return vp.second == i; }) == commandData.vectorParams.end()
&& ((commandData.vectorParams.find(i) == commandData.vectorParams.end()) || commandData.twoStep || (commandData.successCodes.size() == 1)))
&& std::find_if(commandData.vectorParams.begin(), commandData.vectorParams.end(), [i](std::pair<size_t, size_t> const& vp) { return vp.second == i; }) == commandData.vectorParams.end())
{
// it's a non-const pointer, not a vector-size parameter, if it's a vector parameter, its a two-step process or there's just one success code
// it's a non-const pointer and not a vector-size parameter
std::map<size_t, size_t>::const_iterator vpit = commandData.vectorParams.find(i);
if ((vpit == commandData.vectorParams.end()) || commandData.twoStep || (commandData.vectorParams.size() > 1) || (vpit->second == INVALID_INDEX) || (commandData.params[vpit->second].type.find('*') != std::string::npos))
{
// it's not a vector parameter, or a two-step process, or there is at least one more vector parameter, or the size argument of this vector parameter is not an argument, or the size argument of this vector parameter is provided by a pointer
// -> look for another non-cost pointer argument
auto paramIt = std::find_if(commandData.params.begin() + i + 1, commandData.params.end(), [](ParamData const& pd)
{
return (pd.type.find('*') != std::string::npos) && (pd.type.find("const") == std::string::npos);
});
// if there is another such argument, we can't decide which one to return -> return none (~0)
// if there is another such argument, we can't decide which one to return -> return INVALID_INDEX
// otherwise return the index of the selcted parameter
commandData.returnParam = paramIt != commandData.params.end() ? ~0 : i;
}
}
}
}
}
void VulkanHppGenerator::determineSkippedParams(CommandData & commandData)
{
// the size-parameters of vector parameters are not explicitly used in the enhanced API
std::for_each(commandData.vectorParams.begin(), commandData.vectorParams.end(), [&commandData](std::pair<size_t, size_t> const& vp) { if (vp.second != ~0) commandData.skippedParams.insert(vp.second); });
std::for_each(commandData.vectorParams.begin(), commandData.vectorParams.end(), [&commandData](std::pair<size_t, size_t> const& vp) { if (vp.second != INVALID_INDEX) commandData.skippedParams.insert(vp.second); });
// and the return parameter is also skipped
if (commandData.returnParam != ~0)
if (commandData.returnParam != INVALID_INDEX)
{
commandData.skippedParams.insert(commandData.returnParam);
}
@ -1553,7 +1593,7 @@ void VulkanHppGenerator::determineTemplateParam(CommandData & commandData)
break;
}
}
assert((commandData.templateParam == ~0) || (commandData.vectorParams.find(commandData.templateParam) != commandData.vectorParams.end()));
assert((commandData.templateParam == INVALID_INDEX) || (commandData.vectorParams.find(commandData.templateParam) != commandData.vectorParams.end()));
}
void VulkanHppGenerator::determineVectorParams(CommandData & commandData)
@ -1567,9 +1607,9 @@ void VulkanHppGenerator::determineVectorParams(CommandData & commandData)
auto findIt = std::find_if(begin, it, findLambda); // look for a parameter named as the len of this parameter
assert((std::count_if(begin, end, findLambda) == 0) || (findIt < it)); // make sure, there is no other parameter like that
// add this parameter as a vector parameter, using the len-name parameter as the second value (or ~0 if there is nothing like that)
commandData.vectorParams.insert(std::make_pair(std::distance(begin, it), findIt < it ? std::distance(begin, findIt) : ~0));
assert((commandData.vectorParams[std::distance(begin, it)] != ~0)
// add this parameter as a vector parameter, using the len-name parameter as the second value (or INVALID_INDEX if there is nothing like that)
commandData.vectorParams.insert(std::make_pair(std::distance(begin, it), findIt < it ? std::distance(begin, findIt) : INVALID_INDEX));
assert((commandData.vectorParams[std::distance(begin, it)] != INVALID_INDEX)
|| (it->len == "null-terminated")
|| (it->len == "pAllocateInfo::descriptorSetCount")
|| (it->len == "pAllocateInfo::commandBufferCount"));
@ -1953,11 +1993,19 @@ void VulkanHppGenerator::readEnums(tinyxml2::XMLElement const* element)
{
checkAttributes(attributes, element->GetLineNum(), { { "name",{} },{ "type",{ "bitmask", "enum" } } }, { { "comment",{} } }); // re-check with type as required
if (std::find_if(m_dependencies.begin(), m_dependencies.end(), [&name](DependencyData const& dd) { return dd.name == name; }) == m_dependencies.end())
{
// add an empty DependencyData on this name into the dependencies list
m_dependencies.push_back(DependencyData(DependencyData::Category::ENUM, name));
// add this enum to the set of Vulkan data types
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
}
// ad an empty EnumData on this name into the enums map
std::map<std::string, EnumData>::iterator it = m_enums.insert(std::make_pair(name, EnumData(name))).first;
assert(it->second.postfix.empty() && it->second.prefix.empty() && it->second.protect.empty() && it->second.values.empty());
if (name == "Result")
{
@ -2014,10 +2062,6 @@ void VulkanHppGenerator::readEnums(tinyxml2::XMLElement const* element)
}
#endif
}
// add this enum to the set of Vulkan data types
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
}
}
@ -2190,6 +2234,7 @@ void VulkanHppGenerator::readExtensionsExtension(tinyxml2::XMLElement const* ele
{ "obsoletedby", {} },
{ "platform",{} },
{ "promotedto", {} },
{ "provisional", {} },
{ "protect",{} },
{ "requires",{} },
{ "requiresCore",{} },
@ -2537,8 +2582,11 @@ void VulkanHppGenerator::readTypeBitmask(tinyxml2::XMLElement const* element, st
{
// Generate FlagBits name, add a DependencyData for that name, and add it to the list of enums and vulkan types
requires = generateEnumNameForFlags(name);
assert(std::find_if(m_dependencies.begin(), m_dependencies.end(), [&requires](DependencyData const& dd) { return dd.name == requires; }) == m_dependencies.end());
m_dependencies.push_back(DependencyData(DependencyData::Category::ENUM, requires));
assert(m_enums.find(requires) == m_enums.end());
m_enums.insert(std::make_pair(requires, EnumData(requires, true)));
assert(m_vkTypes.find(requires) == m_vkTypes.end());
m_vkTypes.insert(requires);
}
@ -2583,7 +2631,7 @@ void VulkanHppGenerator::readTypeDefine(tinyxml2::XMLElement const* element, std
std::string text = trim(child->GetText());
if (text == "VK_HEADER_VERSION")
{
m_version = element->LastChild()->ToText()->Value();
m_version = trimEnd(element->LastChild()->ToText()->Value());
}
// ignore all the other defines
assert(!child->NextSiblingElement() || (child->NextSiblingElement() && !child->NextSiblingElement()->FirstAttribute() && (strcmp(child->NextSiblingElement()->Value(), "type") == 0) && !child->NextSiblingElement()->NextSiblingElement()));
@ -2700,6 +2748,8 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
std::vector<tinyxml2::XMLElement const*> children = getChildElements(element);
checkElements(children, { "comment", "member" });
std::string name = strip(attributes.find("name")->second, "Vk");
auto aliasIt = attributes.find("alias");
if (aliasIt != attributes.end())
{
@ -2708,16 +2758,12 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
std::string alias = strip(aliasIt->second, "Vk");
checkAlias(m_structs, alias, element->GetLineNum());
std::string name = strip(attributes.find("name")->second, "Vk");
auto structsIt = m_structs.find(alias);
assert((structsIt != m_structs.end()) && structsIt->second.alias.empty());
structsIt->second.alias = name;
}
else
{
std::string name = strip(attributes.find("name")->second, "Vk");
m_dependencies.push_back(DependencyData(isUnion ? DependencyData::Category::UNION : DependencyData::Category::STRUCT, name));
assert(m_structs.find(name) == m_structs.end());
@ -2756,9 +2802,6 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
#endif
}
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
for (auto const& s : m_structs)
{
if (isSubStruct(s, name, it->second))
@ -2768,6 +2811,9 @@ void VulkanHppGenerator::readTypeStruct(tinyxml2::XMLElement const* element, boo
}
}
}
assert(m_vkTypes.find(name) == m_vkTypes.end());
m_vkTypes.insert(name);
}
void VulkanHppGenerator::readTypeStructMember(tinyxml2::XMLElement const* element, StructData & structData)
@ -2880,10 +2926,24 @@ void VulkanHppGenerator::sortDependencies()
bool found = false;
for (std::list<DependencyData>::iterator it = m_dependencies.begin(); it != m_dependencies.end(); ++it)
{
// check if all dependencies of it are already listed
if (std::find_if(it->dependencies.begin(), it->dependencies.end(), [&listedTypes](std::string const& d) { return listedTypes.find(d) == listedTypes.end(); }) == it->dependencies.end())
{
// add it to the end of the sorted list and the set of listed types, remove it from the list of dependencies to handle and start over with the next dependency
sortedDependencies.push_back(*it);
listedTypes.insert(it->name);
// if it is a struct, add any alias of it to the list of encountered types
if (it->category == DependencyData::Category::STRUCT)
{
std::map<std::string, StructData>::const_iterator sit = m_structs.find(it->name);
assert(sit != m_structs.end());
if (!sit->second.alias.empty())
{
assert(listedTypes.find(sit->second.alias) == listedTypes.end());
listedTypes.insert(sit->second.alias);
}
}
m_dependencies.erase(it);
found = true;
break;
@ -2891,7 +2951,7 @@ void VulkanHppGenerator::sortDependencies()
}
if (!found)
{
// resolve direct circular dependencies
// at least one dependency of it is not yet listed -> resolve direct circular dependencies
for (std::list<DependencyData>::iterator it = m_dependencies.begin(); !found && it != m_dependencies.end(); ++it)
{
for (std::set<std::string>::const_iterator dit = it->dependencies.begin(); dit != it->dependencies.end(); ++dit)
@ -2901,9 +2961,8 @@ void VulkanHppGenerator::sortDependencies()
{
if (depIt->dependencies.find(it->name) != depIt->dependencies.end())
{
// we only have just one case, for now!
assert((it->category == DependencyData::Category::HANDLE) && (depIt->category == DependencyData::Category::STRUCT)
|| (it->category == DependencyData::Category::STRUCT) && (depIt->category == DependencyData::Category::STRUCT));
// we only have two cases, for now!
assert((depIt->category == DependencyData::Category::STRUCT) && ((it->category == DependencyData::Category::HANDLE) || (it->category == DependencyData::Category::STRUCT)));
it->forwardDependencies.insert(*dit);
it->dependencies.erase(*dit);
found = true;
@ -2913,7 +2972,14 @@ void VulkanHppGenerator::sortDependencies()
#if !defined(NDEBUG)
else
{
assert(std::find_if(sortedDependencies.begin(), sortedDependencies.end(), [&dit](DependencyData const& dd) { return(dd.name == *dit); }) != sortedDependencies.end());
// here, only already sorted dependencies should occur, or structs that are aliased and sorted
std::list<DependencyData>::const_iterator sdit = std::find_if(sortedDependencies.begin(), sortedDependencies.end(), [&dit](DependencyData const& dd) { return(dd.name == *dit); });
if (sdit == sortedDependencies.end())
{
std::map<std::string, StructData>::const_iterator sit = std::find_if(m_structs.begin(), m_structs.end(), [&dit](std::pair<std::string, StructData> const& sd) { return sd.second.alias == *dit; });
assert(sit != m_structs.end());
assert(std::find_if(sortedDependencies.begin(), sortedDependencies.end(), [name = sit->first](DependencyData const& dd) { return dd.name == name; }) != sortedDependencies.end());
}
}
#endif
}
@ -3001,8 +3067,9 @@ void VulkanHppGenerator::writeCall(std::ostream & os, CommandData const& command
if (!commandData.className.empty())
{
// if it's member of a class -> add the first parameter with "m_" as prefix
os << "m_" << commandData.params[0].name;
// if it's member of a class -> the first argument is the member variable, starting with "m_"
assert(commandData.className == commandData.params[0].type);
os << "m_" << startLowerCase(commandData.className);
if (1 < commandData.params.size())
{
os << ", ";
@ -3280,7 +3347,7 @@ ${i} }
${i} return createResultValue( result, ${typeVariable}s, VULKAN_HPP_NAMESPACE_STRING "::${class}::${function}Unique" );
)";
std::string type = (commandData.returnParam != ~0) ? commandData.params[commandData.returnParam].pureType : "";
std::string type = (commandData.returnParam != INVALID_INDEX) ? commandData.params[commandData.returnParam].pureType : "";
std::string typeVariable = startLowerCase(type);
std::ostringstream arguments;
writeArguments(arguments, commandData, true, singular, 1, commandData.params.size() - 1);
@ -3312,7 +3379,7 @@ ${i} return createResultValue( result, ${typeVariable}s, VULKAN_HPP_NAMESPACE_S
}
std::string returnName;
if (commandData.returnParam != ~0)
if (commandData.returnParam != INVALID_INDEX)
{
returnName = writeFunctionBodyEnhancedLocalReturnVariable(os, indentation, commandData, singular, isStructureChain);
}
@ -3324,7 +3391,7 @@ ${i} return createResultValue( result, ${typeVariable}s, VULKAN_HPP_NAMESPACE_S
// we now might have to check the result, resize the returned vector accordingly, and call the function again
std::map<size_t, size_t>::const_iterator returnit = commandData.vectorParams.find(commandData.returnParam);
assert(returnit != commandData.vectorParams.end() && (returnit->second != ~0));
assert(returnit != commandData.vectorParams.end() && (returnit->second != INVALID_INDEX));
std::string sizeName = startLowerCase(strip(commandData.params[returnit->second].name, "p"));
if (commandData.returnType == "Result")
@ -3359,7 +3426,7 @@ ${i} return createResultValue( result, ${typeVariable}s, VULKAN_HPP_NAMESPACE_S
{
writeFunctionBodyEnhancedReturnResultValue(os, indentation, returnName, commandData, singular, unique);
}
else if ((commandData.returnParam != ~0) && (commandData.returnType != commandData.enhancedReturnType))
else if ((commandData.returnParam != INVALID_INDEX) && (commandData.returnType != commandData.enhancedReturnType))
{
// for the other returning cases, when the return type is somhow enhanced, just return the local returnVariable
os << indentation << " return " << returnName << ";" << std::endl;
@ -3403,7 +3470,7 @@ std::string VulkanHppGenerator::writeFunctionBodyEnhancedLocalReturnVariable(std
{
std::string const &pureType = commandData.params[commandData.returnParam].pureType;
// For StructureChains use the template parameters
os << "StructureChain<T...> structureChain;" << std::endl;
os << "StructureChain<X, Y, Z...> structureChain;" << std::endl;
returnName = stripPluralS(returnName);
os << indentation << " " << pureType << "& " << returnName << " = structureChain.template get<" << pureType << ">()";
returnName = "structureChain";
@ -3422,7 +3489,7 @@ std::string VulkanHppGenerator::writeFunctionBodyEnhancedLocalReturnVariable(std
{
std::string const &returnType = commandData.enhancedReturnType;
// For StructureChains use the template parameters
os << "StructureChain<T...> structureChain;" << std::endl;
os << "StructureChain<X, Y, Z...> structureChain;" << std::endl;
os << indentation << " " << returnType << "& " << returnName << " = structureChain.template get<" << returnType << ">()";
returnName = "structureChain";
}
@ -3436,7 +3503,7 @@ std::string VulkanHppGenerator::writeFunctionBodyEnhancedLocalReturnVariable(std
{
// if the return parameter is a vector parameter, and not part of a two-step algorithm, initialize its size
std::string size;
if (it->second == ~0)
if (it->second == INVALID_INDEX)
{
assert(!commandData.params[commandData.returnParam].len.empty());
// the size of the vector is not given by an other parameter, but by some member of a parameter, described as 'parameter::member'
@ -3539,10 +3606,10 @@ ${i} }
void VulkanHppGenerator::writeFunctionBodyEnhancedLocalCountVariable(std::ostream & os, std::string const& indentation, CommandData const& commandData)
{
// local count variable to hold the size of the vector to fill
assert(commandData.returnParam != ~0);
assert(commandData.returnParam != INVALID_INDEX);
std::map<size_t, size_t>::const_iterator returnit = commandData.vectorParams.find(commandData.returnParam);
assert(returnit != commandData.vectorParams.end() && (returnit->second != ~0));
assert(returnit != commandData.vectorParams.end() && (returnit->second != INVALID_INDEX));
assert((commandData.returnType == "Result") || (commandData.returnType == "void"));
// take the pure type of the size parameter; strip the leading 'p' from its name for its local name
@ -3587,8 +3654,8 @@ ${i} }
void VulkanHppGenerator::writeFunctionBodyEnhancedReturnResultValue(std::ostream & os, std::string const& indentation, std::string const& returnName, CommandData const& commandData, bool singular, bool unique)
{
std::string type = (commandData.returnParam != ~0) ? commandData.params[commandData.returnParam].pureType : "";
std::string returnVectorName = (commandData.returnParam != ~0) ? strip(commandData.params[commandData.returnParam].name, "p", "s") : "";
std::string type = (commandData.returnParam != INVALID_INDEX) ? commandData.params[commandData.returnParam].pureType : "";
std::string returnVectorName = (commandData.returnParam != INVALID_INDEX) ? strip(commandData.params[commandData.returnParam].name, "p", "s") : "";
if (unique)
{
@ -3609,7 +3676,7 @@ void VulkanHppGenerator::writeFunctionBodyEnhancedReturnResultValue(std::ostream
}
// if the return type is "Result" or there is at least one success code, create the Result/Value construct to return
if (commandData.returnParam != ~0)
if (commandData.returnParam != INVALID_INDEX)
{
// if there's a return parameter, list it in the Result/Value constructor
os << returnName << ", ";
@ -3660,7 +3727,8 @@ void VulkanHppGenerator::writeFunctionBodyStandard(std::ostream & os, std::strin
if (!commandData.className.empty())
{
// the command is part of a class -> the first argument is the member variable, starting with "m_"
os << "m_" << commandData.params[0].name;
assert(commandData.className == commandData.params[0].type);
os << "m_" << startLowerCase(commandData.className);
}
// list all the arguments
@ -3726,7 +3794,7 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsEnhanced(std::ostream & os,
if (commandData.skippedParams.size() + (commandData.className.empty() ? 0 : 1) < commandData.params.size())
{
// determine the last argument, where we might provide some default for
size_t lastArgument = size_t(~0);
size_t lastArgument = INVALID_INDEX;
for (size_t i = commandData.params.size() - 1; i < commandData.params.size(); i--)
{
if (commandData.skippedParams.find(i) == commandData.skippedParams.end())
@ -3815,7 +3883,7 @@ void VulkanHppGenerator::writeFunctionHeaderArgumentsEnhanced(std::ostream & os,
{
// the argument is a vector
// it's optional, if it's marked as optional and there's no size specified
bool optional = commandData.params[i].optional && (it->second == ~0);
bool optional = commandData.params[i].optional && (it->second == INVALID_INDEX);
assert((rightStarPos != std::string::npos) && (commandData.params[i].type[rightStarPos] == '*'));
if (commandData.params[i].type.find("char") != std::string::npos)
{
@ -3940,7 +4008,7 @@ void VulkanHppGenerator::writeFunctionHeaderReturnType(std::ostream & os, Comman
bool returnsVector = !singular && (commandData.vectorParams.find(commandData.returnParam) != commandData.vectorParams.end());
templateString += returnsVector ? "ResultValueType<std::vector<UniqueHandle<${returnType},Dispatch>,Allocator>>::type " : "typename ResultValueType<UniqueHandle<${returnType},Dispatch>>::type ";
returnType = isStructureChain ? "StructureChain<T...>" : commandData.params[commandData.returnParam].pureType;
returnType = isStructureChain ? "StructureChain<X, Y, Z...>" : commandData.params[commandData.returnParam].pureType;
}
else if ((commandData.enhancedReturnType != commandData.returnType) && (commandData.returnType != "void"))
{
@ -3951,25 +4019,25 @@ void VulkanHppGenerator::writeFunctionHeaderReturnType(std::ostream & os, Comman
// in singular case, we create the ResultValueType from the pure return type, otherwise from the enhanced return type
if (isStructureChain)
{
returnType = "StructureChain<T...>";
returnType = "StructureChain<X, Y, Z...>";
}
else
{
returnType = singular ? commandData.params[commandData.returnParam].pureType : commandData.enhancedReturnType;
}
}
else if ((commandData.returnParam != ~0) && (1 < commandData.successCodes.size()))
else if ((commandData.returnParam != INVALID_INDEX) && (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 = isStructureChain ? "StructureChain<T...>" : commandData.params[commandData.returnParam].pureType;
returnType = isStructureChain ? "StructureChain<X, Y, Z...>" : commandData.params[commandData.returnParam].pureType;
}
else
{
// and in every other case, we just return the enhanced return type.
templateString = "${returnType} ";
returnType = isStructureChain ? "StructureChain<T...>" : commandData.enhancedReturnType;
returnType = isStructureChain ? "StructureChain<X, Y, Z...>" : commandData.enhancedReturnType;
}
}
else
@ -3986,9 +4054,9 @@ void VulkanHppGenerator::writeFunctionHeaderTemplate(std::ostream & os, std::str
std::string dispatch = withDefault ? std::string("typename Dispatch = DispatchLoaderStatic") : std::string("typename Dispatch");
if (enhanced && isStructureChain)
{
os << indentation << "template <typename ...T, " << dispatch << ">" << std::endl;
os << indentation << "template <typename X, typename Y, typename ...Z, " << dispatch << ">" << std::endl;
}
else if (enhanced && (commandData.templateParam != ~0) && ((commandData.templateParam != commandData.returnParam) || (commandData.enhancedReturnType == "Result")))
else if (enhanced && (commandData.templateParam != INVALID_INDEX) && ((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);
@ -4219,11 +4287,9 @@ void VulkanHppGenerator::writeStructureChainValidation(std::ostream & os)
// write all template functions for the structure pointer chain validation
for (auto it = m_dependencies.begin(); it != m_dependencies.end(); ++it)
{
switch (it->category)
if (it->category == DependencyData::Category::STRUCT)
{
case DependencyData::Category::STRUCT:
writeStructureChainValidation(os, *it);
break;
}
}
}
@ -4233,7 +4299,8 @@ void VulkanHppGenerator::writeStructureChainValidation(std::ostream & os, Depend
std::map<std::string, StructData>::const_iterator it = m_structs.find(dependencyData.name);
assert(it != m_structs.end());
if (!it->second.structExtends.empty()) {
if (!it->second.structExtends.empty())
{
enterProtect(os, it->second.protect);
// write out allowed structure chains
@ -4305,6 +4372,8 @@ void VulkanHppGenerator::writeToStringFunctions(std::ostream & os)
assert(m_enums.find(it->name) != m_enums.end());
writeEnumsToString(os, m_enums.find(it->name)->second);
break;
default:
break;
}
}
}
@ -4409,7 +4478,7 @@ void VulkanHppGenerator::writeTypeCommand(std::ostream & os, std::string const&
// 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) &&
(returnVector->second != INVALID_INDEX) &&
(commandData.params[returnVector->first].pureType != "void") &&
(commandData.params[returnVector->second].type.back() != '*');
if (singular)
@ -4685,17 +4754,22 @@ void VulkanHppGenerator::writeTypeStruct(std::ostream & os, DependencyData const
// create the setters
if (!it->second.returnedOnly)
{
for (size_t i = 0; i<it->second.members.size(); i++)
for (size_t i = 0; i < it->second.members.size(); i++)
{
writeStructSetter(os, dependencyData.name, it->second.members[i]);
}
}
// the cast-operator to the wrapped struct
os << " operator const Vk" << dependencyData.name << "&() const" << std::endl
// the implicit cast-operators to the native type
os << " operator Vk" << dependencyData.name << " const&() const" << std::endl
<< " {" << std::endl
<< " return *reinterpret_cast<const Vk" << dependencyData.name << "*>(this);" << std::endl
<< " }" << std::endl
<< std::endl
<< " operator Vk" << dependencyData.name << " &()" << std::endl
<< " {" << std::endl
<< " return *reinterpret_cast<Vk" << dependencyData.name << "*>(this);" << std::endl
<< " }" << std::endl
<< std::endl;
// operator==() and operator!=()
@ -4795,7 +4869,7 @@ void VulkanHppGenerator::writeUniqueTypes(std::ostream &os, std::pair<std::strin
std::string deleterType = (deleterTypes.first.empty() ? "NoParent" : deleterTypes.first);
os << " template <typename Dispatch> class UniqueHandleTraits<" << dt << ",Dispatch> {public: " << "using owner = " << deleterType << "; " << "using deleter = " << (ddit->second.pool.empty() ? "Object" : "Pool") << ((ddit->second.call.substr(0, 4) == "free") ? "Free<" : "Destroy<") << "owner" << (ddit->second.pool.empty() ? "" : ", " + ddit->second.pool) << ",Dispatch>;};\n";
os << " template <typename Dispatch> class UniqueHandleTraits<" << dt << ",Dispatch> {public: " << "using owner = " << deleterType << "; " << "using deleter = " << (ddit->second.pool.empty() ? "Object" : "Pool") << ((ddit->second.call.substr(0, 4) == "free") ? "Free<" : "Destroy<") << (deleterTypes.first.empty() ? "NoParent" : deleterTypes.first) << (ddit->second.pool.empty() ? "" : ", " + ddit->second.pool) << ",Dispatch>; };\n";
os << " using Unique" << dt << " = UniqueHandle<" << dt << ",DispatchLoaderStatic>;" << std::endl;
}
os << "#endif /*VULKAN_HPP_NO_SMART_HANDLE*/" << std::endl
@ -4862,11 +4936,16 @@ void VulkanHppGenerator::writeTypeUnion(std::ostream & os, DependencyData const&
writeStructSetter(os, dependencyData.name, it->second.members[i]);
}
// the implicit cast operator to the native type
os << " operator Vk" << dependencyData.name << " const& () const" << std::endl
// the implicit cast operators to the native type
os << " operator Vk" << dependencyData.name << " const&() const" << std::endl
<< " {" << std::endl
<< " return *reinterpret_cast<const Vk" << dependencyData.name << "*>(this);" << std::endl
<< " }" << std::endl
<< std::endl
<< " operator Vk" << dependencyData.name << " &()" << std::endl
<< " {" << std::endl
<< " return *reinterpret_cast<Vk" << dependencyData.name << "*>(this);" << std::endl
<< " }" << std::endl
<< std::endl;
// the union member variables
@ -5057,7 +5136,8 @@ void VulkanHppGenerator::writeDelegationClassDynamic(std::ostream &os)
enterProtect(os, command.second.protect);
if (!command.second.params.empty()
&& m_handles.find(command.second.params[0].type) != m_handles.end()
&& command.second.params[0].type != "Instance")
&& command.second.params[0].type != "Instance"
&& command.second.params[0].type != "PhysicalDevice")
{
os << " vk" << startUpperCase(command.second.fullName) << " = PFN_vk" << startUpperCase(command.second.fullName)
<< "(device ? device.getProcAddr( \"vk" << startUpperCase(command.second.fullName) << "\") : instance.getProcAddr( \"vk" << startUpperCase(command.second.fullName) << "\"));" << std::endl;

45
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,45 @@
# Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.2)
project(Vulkan-Hpp_Tests)
option (TESTS_BUILD_WITH_LOCAL_VULKAN_HPP OFF)
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
add_definitions(-DNOMINMAX -DVK_USE_PLATFORM_WIN32_KHR)
else()
error("unhandled platform !")
endif()
FILE (GLOB linkunits ${CMAKE_CURRENT_SOURCE_DIR}/*)
if (TESTS_BUILD_WITH_LOCAL_VULKAN_HPP)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../Vulkan-Docs/include")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..")
else()
include_directories("$ENV{VK_SDK_PATH}/include")
endif()
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../glm")
FOREACH( linkunit ${linkunits} )
if( IS_DIRECTORY ${linkunit} )
if( EXISTS ${linkunit}/CMakeLists.txt )
string( REGEX REPLACE "^.*/([^/]*)$" "\\1" LINK_NAME ${linkunit} )
add_subdirectory( ${LINK_NAME} )
endif()
endif()
ENDFOREACH( linkunit ${linkunits} )

View File

@ -0,0 +1,35 @@
# Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.2)
project(DeviceFunctions)
set(HEADERS
)
set(SOURCES
DeviceFunctions.cpp
)
source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})
add_executable(DeviceFunctions
${HEADERS}
${SOURCES}
)
set_target_properties(DeviceFunctions PROPERTIES FOLDER "Tests")
target_link_libraries(DeviceFunctions "$ENV{VK_SDK_PATH}/Lib/vulkan-1.lib")

View File

@ -0,0 +1,62 @@
// Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// VulkanHpp Samples : DeviceFunctions
// Compile test on device functions
#include "vulkan/vulkan.hpp"
#include <iostream>
static char const* AppName = "DeviceFunctions";
static char const* EngineName = "Vulkan.hpp";
int main(int /*argc*/, char * /*argv[]*/)
{
try
{
vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1);
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo));
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
assert(!physicalDevices.empty());
// get the QueueFamilyProperties of the first PhysicalDevice
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevices[0].getQueueFamilyProperties();
// get the first index into queueFamiliyProperties which supports graphics
size_t graphicsQueueFamilyIndex = std::distance(queueFamilyProperties.begin(),
std::find_if(queueFamilyProperties.begin(),
queueFamilyProperties.end(),
[](vk::QueueFamilyProperties const& qfp) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; }));
assert(graphicsQueueFamilyIndex < queueFamilyProperties.size());
// create a UniqueDevice
float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(graphicsQueueFamilyIndex), 1, &queuePriority);
vk::UniqueDevice device = physicalDevices[0].createDeviceUnique(vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo));
std::vector<uint8_t> data;
device->getAccelerationStructureHandleNVX<uint8_t>({}, data, vk::DispatchLoaderDynamic());
}
catch (vk::SystemError err)
{
std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1);
}
catch (...)
{
std::cout << "unknown error\n";
exit(-1);
}
return 0;
}

View File

@ -0,0 +1,35 @@
# Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.2)
project(StructureChain)
set(HEADERS
)
set(SOURCES
StructureChain.cpp
)
source_group(headers FILES ${HEADERS})
source_group(sources FILES ${SOURCES})
add_executable(StructureChain
${HEADERS}
${SOURCES}
)
set_target_properties(StructureChain PROPERTIES FOLDER "Tests")
target_link_libraries(StructureChain "$ENV{VK_SDK_PATH}/Lib/vulkan-1.lib")

View File

@ -0,0 +1,86 @@
// Copyright(c) 2018, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// VulkanHpp Tests : StructureChain
// Compile-test for StructureChains
#include "vulkan/vulkan.hpp"
#include <iostream>
static char const* AppName = "StructureChain";
static char const* EngineName = "Vulkan.hpp";
#if defined(_MSC_VER)
#pragma warning( disable : 4189 )
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-variable"
#else
// unknow compiler... just ignore the warnings for yourselves ;)
#endif
int main(int /*argc*/, char * /*argv[]*/)
{
try
{
vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1);
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo));
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
// some valid StructureChains
vk::StructureChain<vk::PhysicalDeviceProperties2> sc0;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties> sc1;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceMaintenance3Properties> sc2;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc3;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties> sc4;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc6;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc7;
// some not valid StructureChains
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties> x;
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties, vk::PhysicalDevicePushDescriptorPropertiesKHR> x;
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDevicePushDescriptorPropertiesKHR, vk::PhysicalDeviceMaintenance3Properties> x;
//vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceIDProperties> x;
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceProperties2> x;
vk::PhysicalDevice & pd = physicalDevices[0];
// simple call, passing structures in
vk::PhysicalDeviceFeatures2 pdf;
pd.getFeatures2(&pdf);
// simple calls, getting structure back
vk::PhysicalDeviceFeatures2 a = pd.getFeatures2();
vk::PhysicalDeviceFeatures2 b = pd.getFeatures2(vk::DispatchLoaderStatic());
// complex calls, getting StructureChain back
auto c = pd.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>();
vk::PhysicalDeviceFeatures2 & c0 = c.get<vk::PhysicalDeviceFeatures2>();
vk::PhysicalDeviceVariablePointerFeatures & c1 = c.get<vk::PhysicalDeviceVariablePointerFeatures>();
auto d = pd.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>(vk::DispatchLoaderStatic());
vk::PhysicalDeviceFeatures2 & d0 = d.get<vk::PhysicalDeviceFeatures2>();
vk::PhysicalDeviceVariablePointerFeatures & d1 = d.get<vk::PhysicalDeviceVariablePointerFeatures>();
}
catch (vk::SystemError err)
{
std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1);
}
catch (...)
{
std::cout << "unknown error\n";
exit(-1);
}
return 0;
}

File diff suppressed because it is too large Load Diff