From bd56ed2d515820246adcf1300d1cecb3038d0926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 6 Jan 2021 17:39:57 +0100 Subject: [PATCH] Vk: add a helper for connecting just one structure. Without the extra overhead of Reference. --- .../Vk/Implementation/structureHelpers.h | 28 +++++++++++++------ src/Magnum/Vk/Test/StructureHelpersTest.cpp | 20 +++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/Magnum/Vk/Implementation/structureHelpers.h b/src/Magnum/Vk/Implementation/structureHelpers.h index ba96a3457..75a4c9057 100644 --- a/src/Magnum/Vk/Implementation/structureHelpers.h +++ b/src/Magnum/Vk/Implementation/structureHelpers.h @@ -39,24 +39,36 @@ namespace Magnum { namespace Vk { namespace Implementation { accident. Thus no "give me the first structure of this type" or "remove any structure of this type from the chain". */ -/* Meant to be used for connecting a longer chain of structures. Anything - that was connected to the `next` pointer before is reconnected to - `structure.pNext`; the `next` reference is rebound to the `structure.pNext` - field connected so it can be passed to another structureConnect() again. */ -template inline void structureConnect(Containers::Reference& next, T& structure, VkStructureType type) { +/* Connecting one structure to a pNext chain. Anything that was connected to + the `next` pointer before is reconnected to `structure.pNext` */ +template inline void structureConnectOne(void*& next, T& structure, VkStructureType type) { void* const previousNext = next; - *next = &structure; + next = &structure; structure.sType = type; structure.pNext = previousNext; - next = structure.pNext; } -template inline void structureConnect(Containers::Reference& next, T& structure, VkStructureType type) { +template inline void structureConnectOne(const void*& next, T& structure, VkStructureType type) { /* There's no better way as the pNext are either const void* or void* and it's a mess. For example VkDeviceCreateInfo has const void* but it can point to VkPhysicalDeviceFeatures2 which then has void* as it's primarily an output structure. So we'll just drop all const-correctness and operate on void*. */ + structureConnectOne(const_cast(next), structure, type); +} + +/* Meant to be used for connecting a longer chain of structures. Anything + that was connected to the `next` pointer before is reconnected to + `structure.pNext`; the `next` reference is rebound to the `structure.pNext` + field connected so it can be passed to another structureConnect() again. */ +template inline void structureConnect(Containers::Reference& next, T& structure, VkStructureType type) { + structureConnectOne(*next, structure, type); + next = structure.pNext; +} + +template inline void structureConnect(Containers::Reference& next, T& structure, VkStructureType type) { + /* Same reasoning as in structureConnectOne(), we just drop all + const-correctness and operate on void*. */ structureConnect(reinterpret_cast&>(next), structure, type); } diff --git a/src/Magnum/Vk/Test/StructureHelpersTest.cpp b/src/Magnum/Vk/Test/StructureHelpersTest.cpp index 2b0dfc5c6..d7d486f39 100644 --- a/src/Magnum/Vk/Test/StructureHelpersTest.cpp +++ b/src/Magnum/Vk/Test/StructureHelpersTest.cpp @@ -32,6 +32,7 @@ namespace Magnum { namespace Vk { namespace Test { namespace { struct StructureHelpersTest: TestSuite::Tester { explicit StructureHelpersTest(); + template void connectOne(); template void connect(); template void find(); template void disconnectChain(); @@ -39,6 +40,8 @@ struct StructureHelpersTest: TestSuite::Tester { StructureHelpersTest::StructureHelpersTest() { addTests({ + &StructureHelpersTest::connectOne, + &StructureHelpersTest::connectOne, &StructureHelpersTest::connect, &StructureHelpersTest::connect, &StructureHelpersTest::find, @@ -55,6 +58,23 @@ template<> struct Type { static const char* name() { return "void*"; } }; +template void StructureHelpersTest::connectOne() { + typedef typename std::remove_reference::type NextType; + setTestCaseTemplateName(Type::name()); + + VkPhysicalDeviceVariablePointersFeatures variableFeatures{}; + + T info{}; + info.pNext = &variableFeatures; + + VkPhysicalDeviceMultiviewFeatures multiviewFeatures{}; + Implementation::structureConnectOne(info.pNext, multiviewFeatures, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES); + CORRADE_COMPARE(info.pNext, &multiviewFeatures); + CORRADE_COMPARE(multiviewFeatures.sType, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES); + /* The pre-existing next pointer should be preserved */ + CORRADE_COMPARE(multiviewFeatures.pNext, &variableFeatures); +} + template void StructureHelpersTest::connect() { typedef typename std::remove_reference::type NextType; setTestCaseTemplateName(Type::name());