Extend checking of StructureChains to allow transitive extension. (#254)

This commit is contained in:
Andreas Süßenbach 2018-09-20 15:20:00 +02:00 committed by Markus Tavenrath
parent 1ddafc1c56
commit 295d5c755f
3 changed files with 106 additions and 34 deletions

View File

@ -372,8 +372,34 @@ const std::string arrayProxyHeader = R"(
)"; )";
const std::string structureChainHeader = R"( const std::string structureChainHeader = R"(
template <typename X, typename Y> struct isStructureChainValid { enum { value = false }; }; 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> template <class Element>
class StructureChainElement class StructureChainElement
{ {
@ -390,75 +416,78 @@ const std::string structureChainHeader = R"(
public: public:
StructureChain() StructureChain()
{ {
link<StructureElements...>(); link<void, StructureElements...>();
} }
StructureChain(StructureChain const &rhs) StructureChain(StructureChain const &rhs)
{ {
linkAndCopy<StructureElements...>(rhs); linkAndCopy<void, StructureElements...>(rhs);
} }
StructureChain(StructureElements const &... elems) StructureChain(StructureElements const &... elems)
{ {
linkAndCopyElements<StructureElements...>(elems...); linkAndCopyElements<void, StructureElements...>(elems...);
} }
StructureChain& operator=(StructureChain const &rhs) StructureChain& operator=(StructureChain const &rhs)
{ {
linkAndCopy<StructureElements...>(rhs); linkAndCopy<void, StructureElements...>(rhs);
return *this; return *this;
} }
template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);} template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);}
private: private:
template<typename X> template<typename List, typename X>
void link() 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() 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); X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this); Y& y = static_cast<Y&>(*this);
x.pNext = &y; 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) 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); 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) 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); X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this); Y& y = static_cast<Y&>(*this);
x = static_cast<X const &>(rhs); x = static_cast<X const &>(rhs);
x.pNext = &y; 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) void linkAndCopyElements(X const &xelem)
{ {
static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
static_cast<X&>(*this) = xelem; 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) 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); X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this); Y& y = static_cast<Y&>(*this);
x = xelem; x = xelem;
x.pNext = &y; x.pNext = &y;
linkAndCopyElements<Y, Z...>(yelem, zelem...); linkAndCopyElements<TypeList<List, X>, Y, Z...>(yelem, zelem...);
} }
}; };

View File

@ -37,14 +37,28 @@ int main(int /*argc*/, char * /*argv[]*/)
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo)); vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo));
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices(); 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]; vk::PhysicalDevice & pd = physicalDevices[0];
// simple call, passing structures in // simple call, passing structures in
vk::PhysicalDeviceFeatures2 pdf; vk::PhysicalDeviceFeatures2 pdf;
pd.getFeatures2(&pdf); pd.getFeatures2(&pdf);
vk::StructureChain<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures> z;
// simple calls, getting structure back // simple calls, getting structure back
vk::PhysicalDeviceFeatures2 a = pd.getFeatures2(); vk::PhysicalDeviceFeatures2 a = pd.getFeatures2();
vk::PhysicalDeviceFeatures2 b = pd.getFeatures2(vk::DispatchLoaderStatic()); vk::PhysicalDeviceFeatures2 b = pd.getFeatures2(vk::DispatchLoaderStatic());

View File

@ -479,8 +479,34 @@ namespace VULKAN_HPP_NAMESPACE
#endif #endif
template <typename X, typename Y> struct isStructureChainValid { enum { value = false }; }; 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> template <class Element>
class StructureChainElement class StructureChainElement
{ {
@ -497,75 +523,78 @@ namespace VULKAN_HPP_NAMESPACE
public: public:
StructureChain() StructureChain()
{ {
link<StructureElements...>(); link<void, StructureElements...>();
} }
StructureChain(StructureChain const &rhs) StructureChain(StructureChain const &rhs)
{ {
linkAndCopy<StructureElements...>(rhs); linkAndCopy<void, StructureElements...>(rhs);
} }
StructureChain(StructureElements const &... elems) StructureChain(StructureElements const &... elems)
{ {
linkAndCopyElements<StructureElements...>(elems...); linkAndCopyElements<void, StructureElements...>(elems...);
} }
StructureChain& operator=(StructureChain const &rhs) StructureChain& operator=(StructureChain const &rhs)
{ {
linkAndCopy<StructureElements...>(rhs); linkAndCopy<void, StructureElements...>(rhs);
return *this; return *this;
} }
template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);} template<typename ClassType> ClassType& get() { return static_cast<ClassType&>(*this);}
private: private:
template<typename X> template<typename List, typename X>
void link() 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() 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); X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this); Y& y = static_cast<Y&>(*this);
x.pNext = &y; 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) 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); 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) 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); X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this); Y& y = static_cast<Y&>(*this);
x = static_cast<X const &>(rhs); x = static_cast<X const &>(rhs);
x.pNext = &y; 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) void linkAndCopyElements(X const &xelem)
{ {
static_assert(extendCheck<List, X>::valid, "The structure chain is not valid!");
static_cast<X&>(*this) = xelem; 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) 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); X& x = static_cast<X&>(*this);
Y& y = static_cast<Y&>(*this); Y& y = static_cast<Y&>(*this);
x = xelem; x = xelem;
x.pNext = &y; x.pNext = &y;
linkAndCopyElements<Y, Z...>(yelem, zelem...); linkAndCopyElements<TypeList<List, X>, Y, Z...>(yelem, zelem...);
} }
}; };