diff --git a/README.md b/README.md index d9e52a1..fa3310d 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,9 @@ vk::StructureChain c = }; ``` +If one of the structures of a StructureChain is to be removed, maybe due to some optional settings, you can use the function ```vk::StructureChain::unlink()```. It modifies the StructureChain such that the specified structure isn't part of the pNext-chain any more. Note, that the actual memory layout of the StructureChain is not modified by that function. +In case that very same structure has to be re-added to the StructureChain again, use ```vk::StructureChain::relink()```. + 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: ``` diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index acc4604..460b40f 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -4739,6 +4739,18 @@ int main( int argc, char **argv ) static const bool valid = true; }; + template + struct isPartOfStructureChain + { + static const bool valid = false; + }; + + template + struct isPartOfStructureChain + { + static const bool valid = std::is_same::value || isPartOfStructureChain::valid; + }; + template class StructureChainElement { @@ -4785,6 +4797,45 @@ int main( int argc, char **argv ) ); } + template + void unlink() VULKAN_HPP_NOEXCEPT + { + static_assert(isPartOfStructureChain::valid, "Can't unlink Structure that's not part of this StructureChain!"); + static_assert(!std::is_same>::type>::value, "It's not allowed to unlink the first element!"); + VkBaseOutStructure * ptr = reinterpret_cast(&get()); + assert(ptr != nullptr); + VkBaseOutStructure ** ppNext = &(reinterpret_cast(this)->pNext); + assert(*ppNext != nullptr); + while (*ppNext != ptr) + { + ppNext = &(*ppNext)->pNext; + assert(*ppNext != nullptr); // fires, if the ClassType member has already been unlinked ! + } + assert(*ppNext == ptr); + *ppNext = (*ppNext)->pNext; + } + + template + void relink() VULKAN_HPP_NOEXCEPT + { + static_assert(isPartOfStructureChain::valid, "Can't relink Structure that's not part of this StructureChain!"); + static_assert(!std::is_same>::type>::value, "It's not allowed to have the first element unlinked!"); + VkBaseOutStructure * ptr = reinterpret_cast(&get()); + assert(ptr != nullptr); + VkBaseOutStructure ** ppNext = &(reinterpret_cast(this)->pNext); + assert(*ppNext != nullptr); +#if !defined(NDEBUG) + while (*ppNext) + { + assert(*ppNext != ptr); // fires, if the ClassType member has not been unlinked before + ppNext = &(*ppNext)->pNext; + } + ppNext = &(reinterpret_cast(this)->pNext); +#endif + ptr->pNext = *ppNext; + *ppNext = ptr; + } + private: template void link() VULKAN_HPP_NOEXCEPT diff --git a/tests/StructureChain/StructureChain.cpp b/tests/StructureChain/StructureChain.cpp index 07cde8f..b4213d8 100644 --- a/tests/StructureChain/StructureChain.cpp +++ b/tests/StructureChain/StructureChain.cpp @@ -43,6 +43,7 @@ int main(int /*argc*/, char ** /*argv*/) vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo)); + VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); // some valid StructureChains @@ -61,6 +62,22 @@ int main(int /*argc*/, char ** /*argv*/) //vk::StructureChain x; //vk::StructureChain x; + // unlink a struct from a StructureChain + sc7.unlink(); + + // some invalid unlink calls + //sc7.unlink(); // assertion fires on trying to unlink some already unlinked structure + //sc7.unlink(); + //sc1.unlink(); + + // re-link a struct + sc7.relink(); + + // invalid re-linking + //sc7.relink(); + //sc1.relink(); + //sc1.relink(); // assertion fires on trying to relink some structure that hasn't been unlinked + // simple call, passing structures in vk::PhysicalDeviceFeatures2 pdf; physicalDevice.getFeatures2(&pdf); diff --git a/vulkan/vulkan.hpp b/vulkan/vulkan.hpp index c5003af..51e477f 100644 --- a/vulkan/vulkan.hpp +++ b/vulkan/vulkan.hpp @@ -431,6 +431,18 @@ namespace VULKAN_HPP_NAMESPACE static const bool valid = true; }; + template + struct isPartOfStructureChain + { + static const bool valid = false; + }; + + template + struct isPartOfStructureChain + { + static const bool valid = std::is_same::value || isPartOfStructureChain::valid; + }; + template class StructureChainElement { @@ -477,6 +489,45 @@ namespace VULKAN_HPP_NAMESPACE ); } + template + void unlink() VULKAN_HPP_NOEXCEPT + { + static_assert(isPartOfStructureChain::valid, "Can't unlink Structure that's not part of this StructureChain!"); + static_assert(!std::is_same>::type>::value, "It's not allowed to unlink the first element!"); + VkBaseOutStructure * ptr = reinterpret_cast(&get()); + assert(ptr != nullptr); + VkBaseOutStructure ** ppNext = &(reinterpret_cast(this)->pNext); + assert(*ppNext != nullptr); + while (*ppNext != ptr) + { + ppNext = &(*ppNext)->pNext; + assert(*ppNext != nullptr); // fires, if the ClassType member has already been unlinked ! + } + assert(*ppNext == ptr); + *ppNext = (*ppNext)->pNext; + } + + template + void relink() VULKAN_HPP_NOEXCEPT + { + static_assert(isPartOfStructureChain::valid, "Can't relink Structure that's not part of this StructureChain!"); + static_assert(!std::is_same>::type>::value, "It's not allowed to have the first element unlinked!"); + VkBaseOutStructure * ptr = reinterpret_cast(&get()); + assert(ptr != nullptr); + VkBaseOutStructure ** ppNext = &(reinterpret_cast(this)->pNext); + assert(*ppNext != nullptr); +#if !defined(NDEBUG) + while (*ppNext) + { + assert(*ppNext != ptr); // fires, if the ClassType member has not been unlinked before + ppNext = &(*ppNext)->pNext; + } + ppNext = &(reinterpret_cast(this)->pNext); +#endif + ptr->pNext = *ppNext; + *ppNext = ptr; + } + private: template void link() VULKAN_HPP_NOEXCEPT