Browse Source

Vk: add a helper for connecting just one structure.

Without the extra overhead of Reference.
pull/494/head
Vladimír Vondruš 5 years ago
parent
commit
bd56ed2d51
  1. 28
      src/Magnum/Vk/Implementation/structureHelpers.h
  2. 20
      src/Magnum/Vk/Test/StructureHelpersTest.cpp

28
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 accident. Thus no "give me the first structure of this type" or "remove any
structure of this type from the chain". */ structure of this type from the chain". */
/* Meant to be used for connecting a longer chain of structures. Anything /* Connecting one structure to a pNext chain. Anything that was connected to
that was connected to the `next` pointer before is reconnected to the `next` pointer before is reconnected to `structure.pNext` */
`structure.pNext`; the `next` reference is rebound to the `structure.pNext` template<class T> inline void structureConnectOne(void*& next, T& structure, VkStructureType type) {
field connected so it can be passed to another structureConnect() again. */
template<class T> inline void structureConnect(Containers::Reference<void*>& next, T& structure, VkStructureType type) {
void* const previousNext = next; void* const previousNext = next;
*next = &structure; next = &structure;
structure.sType = type; structure.sType = type;
structure.pNext = previousNext; structure.pNext = previousNext;
next = structure.pNext;
} }
template<class T> inline void structureConnect(Containers::Reference<const void*>& next, T& structure, VkStructureType type) { template<class T> inline void structureConnectOne(const void*& next, T& structure, VkStructureType type) {
/* There's no better way as the pNext are either const void* or void* /* 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 and it's a mess. For example VkDeviceCreateInfo has const void* but it
can point to VkPhysicalDeviceFeatures2 which then has void* as it's can point to VkPhysicalDeviceFeatures2 which then has void* as it's
primarily an output structure. So we'll just drop all const-correctness primarily an output structure. So we'll just drop all const-correctness
and operate on void*. */ and operate on void*. */
structureConnectOne(const_cast<void*&>(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<class T> inline void structureConnect(Containers::Reference<void*>& next, T& structure, VkStructureType type) {
structureConnectOne(*next, structure, type);
next = structure.pNext;
}
template<class T> inline void structureConnect(Containers::Reference<const void*>& next, T& structure, VkStructureType type) {
/* Same reasoning as in structureConnectOne(), we just drop all
const-correctness and operate on void*. */
structureConnect(reinterpret_cast<Containers::Reference<void*>&>(next), structure, type); structureConnect(reinterpret_cast<Containers::Reference<void*>&>(next), structure, type);
} }

20
src/Magnum/Vk/Test/StructureHelpersTest.cpp

@ -32,6 +32,7 @@ namespace Magnum { namespace Vk { namespace Test { namespace {
struct StructureHelpersTest: TestSuite::Tester { struct StructureHelpersTest: TestSuite::Tester {
explicit StructureHelpersTest(); explicit StructureHelpersTest();
template<class T> void connectOne();
template<class T> void connect(); template<class T> void connect();
template<class T> void find(); template<class T> void find();
template<class T> void disconnectChain(); template<class T> void disconnectChain();
@ -39,6 +40,8 @@ struct StructureHelpersTest: TestSuite::Tester {
StructureHelpersTest::StructureHelpersTest() { StructureHelpersTest::StructureHelpersTest() {
addTests<StructureHelpersTest>({ addTests<StructureHelpersTest>({
&StructureHelpersTest::connectOne<VkDeviceCreateInfo>,
&StructureHelpersTest::connectOne<VkPhysicalDeviceFeatures2>,
&StructureHelpersTest::connect<VkDeviceCreateInfo>, &StructureHelpersTest::connect<VkDeviceCreateInfo>,
&StructureHelpersTest::connect<VkPhysicalDeviceFeatures2>, &StructureHelpersTest::connect<VkPhysicalDeviceFeatures2>,
&StructureHelpersTest::find<VkDeviceCreateInfo>, &StructureHelpersTest::find<VkDeviceCreateInfo>,
@ -55,6 +58,23 @@ template<> struct Type<void*> {
static const char* name() { return "void*"; } static const char* name() { return "void*"; }
}; };
template<class T> void StructureHelpersTest::connectOne() {
typedef typename std::remove_reference<decltype(T{}.pNext)>::type NextType;
setTestCaseTemplateName(Type<NextType>::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<class T> void StructureHelpersTest::connect() { template<class T> void StructureHelpersTest::connect() {
typedef typename std::remove_reference<decltype(T{}.pNext)>::type NextType; typedef typename std::remove_reference<decltype(T{}.pNext)>::type NextType;
setTestCaseTemplateName(Type<NextType>::name()); setTestCaseTemplateName(Type<NextType>::name());

Loading…
Cancel
Save