diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index a59e50116..f4bd98f79 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -123,7 +123,7 @@ Vulkan function | Matching API @fn_vk{CmdWriteTimestamp} | | @fn_vk{CreateBuffer}, \n @fn_vk{DestroyBuffer} | | @fn_vk{CreateBufferView}, \n @fn_vk{DestroyBufferView} | | -@fn_vk{CreateCommandPool}, \n @fn_vk{DestroyCommandPool} | | +@fn_vk{CreateCommandPool}, \n @fn_vk{DestroyCommandPool} | @ref CommandPool constructor and destructor @fn_vk{CreateComputePipelines}, \n @fn_vk{DestroyComputePipelines} | | @fn_vk{CreateDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CreateDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @@ -304,6 +304,14 @@ Vulkan structure | Matching API --------------------------------------- | ------------ @type_vk{ApplicationInfo} | @ref InstanceCreateInfo +@subsection vulkan-mapping-structures-c C + +@m_class{m-fullwidth} + +Vulkan structure | Matching API +--------------------------------------- | ------------ +@type_vk{CommandPoolCreateInfo} | @ref CommandPoolCreateInfo + @subsection vulkan-mapping-structures-d D @m_class{m-fullwidth} diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 5704f8af8..0504291d0 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -27,6 +27,7 @@ find_package(Vulkan REQUIRED) set(MagnumVk_SRCS + CommandPool.cpp Extensions.cpp Handle.cpp Instance.cpp @@ -45,6 +46,7 @@ set(MagnumVk_GracefulAssert_SRCS LayerProperties.cpp) set(MagnumVk_HEADERS + CommandPool.h Device.h DeviceProperties.h Enums.h diff --git a/src/Magnum/Vk/CommandPool.cpp b/src/Magnum/Vk/CommandPool.cpp new file mode 100644 index 000000000..35e906496 --- /dev/null +++ b/src/Magnum/Vk/CommandPool.cpp @@ -0,0 +1,84 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "CommandPool.h" + +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Handle.h" +#include "Magnum/Vk/Result.h" + +namespace Magnum { namespace Vk { + +CommandPoolCreateInfo::CommandPoolCreateInfo(const UnsignedInt queueFamilyIndex, const Flags flags): _info{} { + _info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + _info.flags = VkCommandPoolCreateFlags(flags); + _info.queueFamilyIndex = queueFamilyIndex; +} + +CommandPoolCreateInfo::CommandPoolCreateInfo(NoInitT) noexcept {} + +CommandPoolCreateInfo::CommandPoolCreateInfo(const VkCommandPoolCreateInfo& info): + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(info) {} + +CommandPool CommandPool::wrap(Device& device, const VkCommandPool handle, const HandleFlags flags) { + CommandPool out{NoCreate}; + out._device = &device; + out._handle = handle; + out._flags = flags; + return out; +} + +CommandPool::CommandPool(Device& device, const CommandPoolCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} { + MAGNUM_VK_INTERNAL_ASSERT_RESULT(device->CreateCommandPool(device, info, nullptr, &_handle)); +} + +CommandPool::CommandPool(NoCreateT) noexcept: _device{}, _handle{} {} + +CommandPool::CommandPool(CommandPool&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} { + other._handle = {}; +} + +CommandPool::~CommandPool() { + if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) + (**_device).DestroyCommandPool(*_device, _handle, nullptr); +} + +CommandPool& CommandPool::operator=(CommandPool&& other) noexcept { + using std::swap; + swap(other._device, _device); + swap(other._handle, _handle); + swap(other._flags, _flags); + return *this; +} + +VkCommandPool CommandPool::release() { + const VkCommandPool handle = _handle; + _handle = {}; + return handle; +} + +}} diff --git a/src/Magnum/Vk/CommandPool.h b/src/Magnum/Vk/CommandPool.h new file mode 100644 index 000000000..02d01117f --- /dev/null +++ b/src/Magnum/Vk/CommandPool.h @@ -0,0 +1,222 @@ +#ifndef Magnum_Vk_CommandPool_h +#define Magnum_Vk_CommandPool_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::Vk::CommandPoolCreateInfo, @ref Magnum::Vk::CommandPool + * @m_since_latest + */ + +#include + +#include "Magnum/Tags.h" +#include "Magnum/Magnum.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" +#include "Magnum/Vk/visibility.h" + +namespace Magnum { namespace Vk { + +/** +@brief Command pool creation info +@m_since_latest + +Wraps a @type_vk_keyword{CommandPoolCreateInfo}. +@see @ref CommandPool +*/ +class MAGNUM_VK_EXPORT CommandPoolCreateInfo { + public: + /** + * @brief Command pool creation flag + * + * Wraps @type_vk_keyword{CommandPoolCreateFlagBits}. + * @see @ref Flags, @ref CommandPoolCreateInfo(UnsignedInt, Flags) + * @m_enum_values_as_keywords + */ + enum class Flag: UnsignedInt { + /** Command buffers allocated from this pool will be short-lived */ + Transient = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + + /** + * Allow individual command buffers to be reset to initial state + * instead of just the whole pool. + * + * @m_class{m-note m-success} + * + * @par + * Not using this flag may help the driver to use simpler + * per-pool allocators instead of per-buffer. + */ + ResetCommandBuffer = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + }; + + /** + * @brief Command pool creation flags + * + * Type-safe wrapper for @type_vk_keyword{CommandPoolCreateFlags}. + * @see @ref CommandPoolCreateInfo(UnsignedInt, Flags) + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param queueFamilyIndex Queue family index + * @param flags Command pool creation flags + * + * The following @type_vk{CommandPoolCreateInfo} fields are pre-filled + * in addition to `sType`, everything else is zero-filled: + * + * - `flags` + * - `queueFamilyIndex` + * + * @see @ref DeviceProperties::pickQueueFamily() + */ + explicit CommandPoolCreateInfo(UnsignedInt queueFamilyIndex, Flags flags = {}); + + /** + * @brief Construct without initializing the contents + * + * Note that not even the `sType` field is set --- the structure has to + * be fully initialized afterwards in order to be usable. + */ + explicit CommandPoolCreateInfo(NoInitT) noexcept; + + /** + * @brief Construct from existing data + * + * Copies the existing values verbatim, pointers are kept unchanged + * without taking over the ownership. Modifying the newly created + * instance will not modify the original data nor the pointed-to data. + */ + explicit CommandPoolCreateInfo(const VkCommandPoolCreateInfo& info); + + /** @brief Underlying @type_vk{CommandPoolCreateInfo} structure */ + VkCommandPoolCreateInfo& operator*() { return _info; } + /** @overload */ + const VkCommandPoolCreateInfo& operator*() const { return _info; } + /** @overload */ + VkCommandPoolCreateInfo* operator->() { return &_info; } + /** @overload */ + const VkCommandPoolCreateInfo* operator->() const { return &_info; } + /** @overload */ + operator const VkCommandPoolCreateInfo*() const { return &_info; } + + private: + VkCommandPoolCreateInfo _info; +}; + +CORRADE_ENUMSET_OPERATORS(CommandPoolCreateInfo::Flags) + +/** +@brief Command pool +@m_since_latest + +Wraps a @type_vk_keyword{CommandPool}. +*/ +class MAGNUM_VK_EXPORT CommandPool { + public: + /** + * @brief Wrap existing Vulkan handle + * @param device Vulkan device the command pool is created on + * @param handle The @type_vk{CommandPool} handle + * @param flags Handle flags + * + * The @p handle is expected to be of an existing Vulkan command pool. + * Unlike a command pool created using a constructor, the Vulkan + * command pool is by default not deleted on destruction, use @p flags + * for different behavior. + */ + static CommandPool wrap(Device& device, VkCommandPool handle, HandleFlags flags = {}); + + /** + * @brief Constructor + * @param device Vulkan device to create the command pool on + * @param info Command pool creation info + * + * @see @fn_vk_keyword{CreateCommandPool} + */ + explicit CommandPool(Device& device, const CommandPoolCreateInfo& info); + + /** + * @brief Construct without creating the instance + * + * The constructed instance is equivalent to moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + */ + explicit CommandPool(NoCreateT) noexcept; + + /** @brief Copying is not allowed */ + CommandPool(const CommandPool&) = delete; + + /** @brief Move constructor */ + CommandPool(CommandPool&& other) noexcept; + + /** + * @brief Destructor + * + * Destroys associated @type_vk{CommandPool} handle, unless the + * instance was created using @ref wrap() without @ref HandleFlag::DestroyOnDestruction + * specified. + * @see @fn_vk_keyword{DestroyCommandPool}, @ref release() + */ + ~CommandPool(); + + /** @brief Copying is not allowed */ + CommandPool& operator=(const CommandPool&) = delete; + + /** @brief Move assignment */ + CommandPool& operator=(CommandPool&& other) noexcept; + + /** @brief Underlying @type_vk{CommandPool} handle */ + VkCommandPool handle() { return _handle; } + /** @overload */ + operator VkCommandPool() { return _handle; } + + /** @brief Handle flags */ + HandleFlags handleFlags() const { return _flags; } + + /** + * @brief Release the underlying Vulkan command pool + * + * Releases ownership of the Vulkan command pool and returns its handle + * so @fn_vk{DestroyCommandPool} is not called on destruction. The + * internal state is then equivalent to moved-from state. + * @see @ref wrap() + */ + VkCommandPool release(); + + private: + /* Can't be a reference because of the NoCreate constructor */ + Device* _device; + + VkCommandPool _handle; + HandleFlags _flags; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index d39b1c124..c7e59593e 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -24,6 +24,7 @@ # DEALINGS IN THE SOFTWARE. # +corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDevicePropertiesTest DevicePropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkEnumsTest EnumsTest.cpp LIBRARIES MagnumVkTestLib) @@ -37,6 +38,7 @@ corrade_add_test(VkResultTest ResultTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkVersionTest VersionTest.cpp LIBRARIES MagnumVk) if(BUILD_VK_TESTS) + corrade_add_test(VkCommandPoolVkTest CommandPoolVkTest.cpp LIBRARIES MagnumVulkanTester) corrade_add_test(VkDeviceVkTest DeviceVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkDevicePropertiesVkTest DevicePropertiesVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkExtensionPropertiesVkTest ExtensionPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib) diff --git a/src/Magnum/Vk/Test/CommandPoolTest.cpp b/src/Magnum/Vk/Test/CommandPoolTest.cpp new file mode 100644 index 000000000..8e26bd477 --- /dev/null +++ b/src/Magnum/Vk/Test/CommandPoolTest.cpp @@ -0,0 +1,96 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Vk/CommandPool.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct CommandPoolTest: TestSuite::Tester { + explicit CommandPoolTest(); + + void createInfoConstruct(); + void createInfoConstructNoInit(); + void createInfoConstructFromVk(); + + void constructNoCreate(); + void constructCopy(); +}; + +CommandPoolTest::CommandPoolTest() { + addTests({&CommandPoolTest::createInfoConstruct, + &CommandPoolTest::createInfoConstructNoInit, + &CommandPoolTest::createInfoConstructFromVk, + + &CommandPoolTest::constructNoCreate, + &CommandPoolTest::constructCopy}); +} + +void CommandPoolTest::createInfoConstruct() { + CommandPoolCreateInfo info{37, CommandPoolCreateInfo::Flag::ResetCommandBuffer|CommandPoolCreateInfo::Flag::Transient}; + CORRADE_COMPARE(info->queueFamilyIndex, 37); + CORRADE_COMPARE(info->flags, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT|VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); +} + +void CommandPoolTest::createInfoConstructNoInit() { + CommandPoolCreateInfo info{NoInit}; + info->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + new(&info) CommandPoolCreateInfo{NoInit}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); + + CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void CommandPoolTest::createInfoConstructFromVk() { + VkCommandPoolCreateInfo vkInfo; + vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + + CommandPoolCreateInfo info{vkInfo}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); +} + +void CommandPoolTest::constructNoCreate() { + { + CommandPool pool{NoCreate}; + CORRADE_VERIFY(!pool.handle()); + } + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void CommandPoolTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::CommandPoolTest) diff --git a/src/Magnum/Vk/Test/CommandPoolVkTest.cpp b/src/Magnum/Vk/Test/CommandPoolVkTest.cpp new file mode 100644 index 000000000..4846bf6f8 --- /dev/null +++ b/src/Magnum/Vk/Test/CommandPoolVkTest.cpp @@ -0,0 +1,102 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Magnum/Vk/CommandPool.h" +#include "Magnum/Vk/DeviceProperties.h" +#include "Magnum/Vk/Handle.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/VulkanTester.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct CommandPoolVkTest: VulkanTester { + explicit CommandPoolVkTest(); + + void construct(); + void constructMove(); + void wrap(); +}; + +CommandPoolVkTest::CommandPoolVkTest() { + addTests({&CommandPoolVkTest::construct, + &CommandPoolVkTest::constructMove, + &CommandPoolVkTest::wrap}); +} + +void CommandPoolVkTest::construct() { + { + CommandPool pool{device(), CommandPoolCreateInfo{ + deviceProperties().pickQueueFamily(QueueFlag::Graphics), + CommandPoolCreateInfo::Flag::ResetCommandBuffer}}; + CORRADE_VERIFY(pool.handle()); + CORRADE_COMPARE(pool.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + +void CommandPoolVkTest::constructMove() { + CommandPool a{device(), CommandPoolCreateInfo{ + deviceProperties().pickQueueFamily(QueueFlag::Graphics), + CommandPoolCreateInfo::Flag::Transient}}; + VkCommandPool handle = a.handle(); + + CommandPool b = std::move(a); + CORRADE_VERIFY(!a.handle()); + CORRADE_COMPARE(b.handle(), handle); + CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction); + + CommandPool c{NoCreate}; + c = std::move(b); + CORRADE_VERIFY(!b.handle()); + CORRADE_COMPARE(b.handleFlags(), HandleFlags{}); + CORRADE_COMPARE(c.handle(), handle); + CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction); + + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); + CORRADE_VERIFY(std::is_nothrow_move_assignable::value); +} + +void CommandPoolVkTest::wrap() { + VkCommandPool pool{}; + CORRADE_COMPARE(Result(device()->CreateCommandPool(device(), + CommandPoolCreateInfo{ + deviceProperties().pickQueueFamily(QueueFlag::Graphics)}, + nullptr, &pool)), Result::Success); + CORRADE_VERIFY(pool); + + auto wrapped = CommandPool::wrap(device(), pool, HandleFlag::DestroyOnDestruction); + CORRADE_COMPARE(wrapped.handle(), pool); + + /* Release the handle again, destroy by hand */ + CORRADE_COMPARE(wrapped.release(), pool); + CORRADE_VERIFY(!wrapped.handle()); + device()->DestroyCommandPool(device(), pool, nullptr); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::CommandPoolVkTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 3cb353a7a..171a2a170 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -36,6 +36,7 @@ namespace Magnum { namespace Vk { #ifndef DOXYGEN_GENERATING_OUTPUT +class CommandPool; class Device; class DeviceCreateInfo; class DeviceProperties;