From aa384a5d385784723e86b0b837cfd994c0e49157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Jun 2020 17:25:24 +0200 Subject: [PATCH] Vk: initial device enumeration. --- doc/vulkan-mapping.dox | 4 +- src/Magnum/Vk/CMakeLists.txt | 2 + src/Magnum/Vk/DeviceProperties.cpp | 123 ++++++++++ src/Magnum/Vk/DeviceProperties.h | 218 ++++++++++++++++++ .../Vk/Implementation/InstanceState.cpp | 14 +- src/Magnum/Vk/Implementation/InstanceState.h | 2 + src/Magnum/Vk/Test/CMakeLists.txt | 2 + src/Magnum/Vk/Test/DevicePropertiesTest.cpp | 73 ++++++ src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp | 110 +++++++++ src/Magnum/Vk/Vk.h | 2 + 10 files changed, 547 insertions(+), 3 deletions(-) create mode 100644 src/Magnum/Vk/DeviceProperties.cpp create mode 100644 src/Magnum/Vk/DeviceProperties.h create mode 100644 src/Magnum/Vk/Test/DevicePropertiesTest.cpp create mode 100644 src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 0d7724e86..e9b986a10 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -169,7 +169,7 @@ Vulkan function | Matching API @fn_vk{EnumerateInstanceExtensionProperties} | @ref enumerateInstanceExtensionProperties() @fn_vk{EnumerateInstanceLayerProperties} | @ref enumerateLayerProperties() @fn_vk{EnumerateInstanceVersion} @m_class{m-label m-flat m-success} **1.1** | @ref enumerateInstanceVersion() -@fn_vk{EnumeratePhysicalDevices} | | +@fn_vk{EnumeratePhysicalDevices} | @ref enumerateDevices() @fn_vk{EnumeratePhysicalDeviceGroups} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @subsection vulkan-mapping-functions-f F @@ -208,7 +208,7 @@ Vulkan function | Matching API @fn_vk{GetPhysicalDeviceFormatProperties}, \n @fn_vk{GetPhysicalDeviceFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceMemoryProperties}, \n @fn_vk{GetPhysicalDeviceMemoryProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@fn_vk{GetPhysicalDeviceProperties}, \n @fn_vk{GetPhysicalDeviceProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | +@fn_vk{GetPhysicalDeviceProperties}, \n @fn_vk{GetPhysicalDeviceProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref DeviceProperties @fn_vk{GetPhysicalDeviceQueueFamilyProperties}, \n @fn_vk{GetPhysicalDeviceQueueFamilyProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPhysicalDeviceSparseImageFormatProperties}, \n @fn_vk{GetPhysicalDeviceSparseImageFormatProperties2} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{GetPipelineCacheData} | | diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 07246bb36..bde2ccd7f 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -27,6 +27,7 @@ find_package(Vulkan REQUIRED) set(MagnumVk_SRCS + DeviceProperties.cpp Extensions.cpp Handle.cpp Instance.cpp @@ -43,6 +44,7 @@ set(MagnumVk_GracefulAssert_SRCS set(MagnumVk_HEADERS Device.h + DeviceProperties.h Enums.h Extensions.h ExtensionProperties.h diff --git a/src/Magnum/Vk/DeviceProperties.cpp b/src/Magnum/Vk/DeviceProperties.cpp new file mode 100644 index 000000000..bed65c26e --- /dev/null +++ b/src/Magnum/Vk/DeviceProperties.cpp @@ -0,0 +1,123 @@ +/* + 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 "DeviceProperties.h" + +#include +#include +#include + +#include "Magnum/Vk/Instance.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/Implementation/InstanceState.h" + +namespace Magnum { namespace Vk { + +struct DeviceProperties::State { + VkPhysicalDeviceProperties2 properties{}; +}; + +DeviceProperties::DeviceProperties(NoCreateT) noexcept: _instance{}, _handle{} {} + +DeviceProperties::DeviceProperties(Instance& instance, VkPhysicalDevice handle): _instance{&instance}, _handle{handle} {} + +/* The VkDeviceProperties handle doesn't need to be destroyed so it's enough to + just rely on the implicit behavior */ +DeviceProperties::DeviceProperties(DeviceProperties&&) noexcept = default; + +DeviceProperties::~DeviceProperties() = default; + +DeviceProperties& DeviceProperties::operator=(DeviceProperties&&) noexcept = default; + +Containers::StringView DeviceProperties::name() { + return properties().properties.deviceName; +} + +const VkPhysicalDeviceProperties2& DeviceProperties::properties() { + if(!_state) _state.emplace(); + + /* Properties not fetched yet, do that now */ + if(!_state->properties.sType) { + _state->properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + + _instance->state().getPhysicalDevicePropertiesImplementation(*this, _state->properties); + } + + return _state->properties; +} + +void DeviceProperties::getPropertiesImplementationDefault(DeviceProperties& self, VkPhysicalDeviceProperties2& properties) { + return (**self._instance).GetPhysicalDeviceProperties(self._handle, &properties.properties); +} + +void DeviceProperties::getPropertiesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceProperties2& properties) { + return (**self._instance).GetPhysicalDeviceProperties2KHR(self._handle, &properties); +} + +void DeviceProperties::getPropertiesImplementation11(DeviceProperties& self, VkPhysicalDeviceProperties2& properties) { + return (**self._instance).GetPhysicalDeviceProperties2(self._handle, &properties); +} + +Containers::Array enumerateDevices(Instance& instance) { + /* Retrieve total device count */ + UnsignedInt count; + MAGNUM_VK_INTERNAL_ASSERT_RESULT(instance->EnumeratePhysicalDevices(instance, &count, nullptr)); + + /* Allocate memory for the output, fetch the handles into it */ + Containers::Array out{Containers::NoInit, count}; + Containers::ArrayView handles{reinterpret_cast(out.data()), count}; + MAGNUM_VK_INTERNAL_ASSERT_RESULT(instance->EnumeratePhysicalDevices(instance, &count, handles.data())); + + /* Expect the device count didn't change between calls */ + CORRADE_INTERNAL_ASSERT(count == out.size()); + + /* Construct actual DeviceProperties instances from these, go backwards so + we don't overwrite the not-yet-processed handles */ + for(std::size_t i = count; i != 0; --i) + new(out.data() + i - 1) DeviceProperties{instance, handles[i - 1]}; + + return out; +} + +Debug& operator<<(Debug& debug, const DeviceType value) { + debug << "Vk::DeviceType" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::DeviceType::value: return debug << "::" << Debug::nospace << #value; + _c(Other) + _c(IntegratedGpu) + _c(DiscreteGpu) + _c(VirtualGpu) + _c(Cpu) + #undef _c + /* LCOV_EXCL_STOP */ + } + + /* Vulkan docs have the values in decimal, so not converting to hex */ + return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; +} + +}} diff --git a/src/Magnum/Vk/DeviceProperties.h b/src/Magnum/Vk/DeviceProperties.h new file mode 100644 index 000000000..535700407 --- /dev/null +++ b/src/Magnum/Vk/DeviceProperties.h @@ -0,0 +1,218 @@ +#ifndef Magnum_Vk_DeviceProperties_h +#define Magnum_Vk_DeviceProperties_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::DeviceProperties, enum @ref Magnum::Vk::DeviceType, function @ref Magnum::Vk::enumerateDevices() + * @m_since_latest + */ + +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Tags.h" +#include "Magnum/Vk/Vulkan.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/visibility.h" + +namespace Magnum { namespace Vk { + +namespace Implementation { struct InstanceState; } + +/** +@brief Physical device type +@m_since_latest + +Wraps a @type_vk_keyword{PhysicalDeviceType}. +@see @ref DeviceProperties::type() +@m_enum_values_as_keywords +*/ +enum class DeviceType: Int { + /** Anything that does not match any other available types */ + Other = VK_PHYSICAL_DEVICE_TYPE_OTHER, + + /** + * Typically a device embedded in or tightly coupled with the host + */ + IntegratedGpu = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, + + /** + * Typically a separate processor connected to the host via an + * interlink + */ + DiscreteGpu = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + + /** Typically a virtual node in a virtualization environment */ + VirtualGpu = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, + + /** Typically running on the same processors as the host */ + Cpu = VK_PHYSICAL_DEVICE_TYPE_CPU +}; + +/** +@debugoperatorclassenum{DeviceProperties,DeviceType} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DeviceType value); + +/** +@brief Physical device properties +@m_since_latest + +Wraps a @type_vk_keyword{PhysicalDevice} along with its (lazy-populated) +properties. +@see @ref enumeratePhysicalDevices() +*/ +class MAGNUM_VK_EXPORT DeviceProperties { + public: + /** + * @brief Wrap existing Vulkan physical device + * @param instance Vulkan instance + * @param handle The @type_vk{PhysicalDevice} handle + * + * The @p handle is expected to be originating from @p instance. Unlike + * with other handle types, the @type_vk{PhysicalDevice} handles don't + * have to be destroyed at the end. so there's no equivalent of e.g. + * @ref Instance::release() or @ref Instance::handleFlags(). + */ + static DeviceProperties wrap(Instance& instance, VkPhysicalDevice handle) { + return DeviceProperties{instance, handle}; + } + + /** + * @brief Construct without populating the contents + * + * 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 DeviceProperties(NoCreateT) noexcept; + + /** @brief Copying is not allowed */ + DeviceProperties(const DeviceProperties&) = delete; + + /** @brief Move constructor */ + DeviceProperties(DeviceProperties&&) noexcept; + + ~DeviceProperties(); + + /** @brief Copying is not allowed */ + DeviceProperties& operator=(const DeviceProperties&) = delete; + + /** @brief Move assignment */ + DeviceProperties& operator=(DeviceProperties&&) noexcept; + + /** @brief Underlying @type_vk{PhysicalDevice} handle */ + VkPhysicalDevice handle() { return _handle; } + /** @overload */ + operator VkPhysicalDevice() { return _handle; } + + /** + * @brief Raw device properties + * + * Populated lazily on first request. If Vulkan 1.1 or the + * @vk_extension{KHR,get_physical_device_properties2} extension is not + * enabled on the originating instance, only the Vulkan 1.0 subset of + * device properties is queried, with the `pNext` member being + * @cpp nullptr @ce. + * @see @fn_vk_keyword{GetPhysicalDeviceProperties2}, + * @fn_vk_keyword{GetPhysicalDeviceProperties} + */ + const VkPhysicalDeviceProperties2& properties(); + + /** + * @brief API version + * + * Convenience access to @ref properties() internals, populated lazily + * on first request. + */ + Version apiVersion() { + return Version(properties().properties.apiVersion); + } + + /** + * @brief Driver version + * + * Convenience access to @ref properties() internals, populated lazily + * on first request. + */ + Version driverVersion() { + return Version(properties().properties.driverVersion); + } + + /** + * @brief Device type + * + * Convenience access to @ref properties() internals, populated lazily + * on first request. + */ + DeviceType type() { + return DeviceType(properties().properties.deviceType); + } + + /** + * @brief Device name + * + * Convenience access to @ref properties() internals, populated lazily + * on first request. + */ + Containers::StringView name(); + + private: + friend Implementation::InstanceState; + + #ifndef DOXYGEN_GENERATING_OUTPUT + /* The DAMN THING lists this among friends, which is AN IMPLEMENTATION + DETAIL */ + friend MAGNUM_VK_EXPORT Containers::Array enumerateDevices(Instance&); + #endif + + explicit DeviceProperties(Instance& instance, VkPhysicalDevice handle); + + MAGNUM_VK_LOCAL static void getPropertiesImplementationDefault(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); + MAGNUM_VK_LOCAL static void getPropertiesImplementationKHR(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); + MAGNUM_VK_LOCAL static void getPropertiesImplementation11(DeviceProperties& self, VkPhysicalDeviceProperties2& properties); + + /* Can't be a reference because of the NoCreate constructor */ + Instance* _instance; + + VkPhysicalDevice _handle; + struct State; + Containers::Pointer _state; +}; + +/** +@brief Enumerate physical devices +@m_since_latest + +@see @fn_vk_keyword{EnumeratePhysicalDevices} +*/ +MAGNUM_VK_EXPORT Containers::Array enumerateDevices(Instance& instance); + +}} + +#endif diff --git a/src/Magnum/Vk/Implementation/InstanceState.cpp b/src/Magnum/Vk/Implementation/InstanceState.cpp index ffd0c0337..5c151b5f4 100644 --- a/src/Magnum/Vk/Implementation/InstanceState.cpp +++ b/src/Magnum/Vk/Implementation/InstanceState.cpp @@ -25,8 +25,20 @@ #include "InstanceState.h" +#include "Magnum/Vk/Extensions.h" +#include "Magnum/Vk/Instance.h" +#include "Magnum/Vk/DeviceProperties.h" + namespace Magnum { namespace Vk { namespace Implementation { -InstanceState::InstanceState(Instance&, Int argc, const char** argv): argc{argc}, argv{argv} {} +InstanceState::InstanceState(Instance& instance, Int argc, const char** argv): argc{argc}, argv{argv} { + if(instance.isVersionSupported(Version::Vk11)) { + getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementation11; + } else if(instance.isExtensionEnabled()) { + getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementationKHR; + } else { + getPhysicalDevicePropertiesImplementation = DeviceProperties::getPropertiesImplementationDefault; + } +} }}} diff --git a/src/Magnum/Vk/Implementation/InstanceState.h b/src/Magnum/Vk/Implementation/InstanceState.h index 077464da6..f746de43a 100644 --- a/src/Magnum/Vk/Implementation/InstanceState.h +++ b/src/Magnum/Vk/Implementation/InstanceState.h @@ -35,6 +35,8 @@ struct InstanceState { Int argc; const char** argv; + + void(*getPhysicalDevicePropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&); }; }}} diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index d49d3b474..9ec60218b 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(VkDevicePropertiesTest DevicePropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkEnumsTest EnumsTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkExtensionsTest ExtensionsTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkExtensionPropertiesTest ExtensionPropertiesTest.cpp LIBRARIES MagnumVk) @@ -35,6 +36,7 @@ corrade_add_test(VkResultTest ResultTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkVersionTest VersionTest.cpp LIBRARIES MagnumVk) if(BUILD_VK_TESTS) + corrade_add_test(VkDevicePropertiesVkTest DevicePropertiesVkTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkExtensionPropertiesVkTest ExtensionPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkLayerPropertiesVkTest LayerPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkInstanceVkTest InstanceVkTest.cpp LIBRARIES MagnumVk) diff --git a/src/Magnum/Vk/Test/DevicePropertiesTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesTest.cpp new file mode 100644 index 000000000..3aab323d6 --- /dev/null +++ b/src/Magnum/Vk/Test/DevicePropertiesTest.cpp @@ -0,0 +1,73 @@ +/* + 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 + +#include "Magnum/Vk/DeviceProperties.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DevicePropertiesTest: TestSuite::Tester { + explicit DevicePropertiesTest(); + + void constructNoCreate(); + void constructCopy(); + + void debugDeviceType(); +}; + +DevicePropertiesTest::DevicePropertiesTest() { + addTests({&DevicePropertiesTest::constructNoCreate, + &DevicePropertiesTest::constructCopy, + + &DevicePropertiesTest::debugDeviceType}); +} + +void DevicePropertiesTest::constructNoCreate() { + { + DeviceProperties properties{NoCreate}; + CORRADE_VERIFY(!properties.handle()); + } + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); +} + +void DevicePropertiesTest::constructCopy() { + CORRADE_VERIFY(!(std::is_constructible{})); + CORRADE_VERIFY(!(std::is_assignable{})); +} + +void DevicePropertiesTest::debugDeviceType() { + std::ostringstream out; + Debug{&out} << DeviceType::DiscreteGpu << DeviceType(-10007655); + CORRADE_COMPARE(out.str(), "Vk::DeviceType::DiscreteGpu Vk::DeviceType(-10007655)\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DevicePropertiesTest) diff --git a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp new file mode 100644 index 000000000..5e0b98ce9 --- /dev/null +++ b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp @@ -0,0 +1,110 @@ +/* + 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 +#include + +#include "Magnum/Vk/DeviceProperties.h" +#include "Magnum/Vk/Instance.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/Version.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DevicePropertiesVkTest: TestSuite::Tester { + explicit DevicePropertiesVkTest(); + + void enumerate(); + void constructMove(); + void wrap(); + + Instance _instance; +}; + +DevicePropertiesVkTest::DevicePropertiesVkTest(): _instance{InstanceCreateInfo{arguments().first, arguments().second}} { + addTests({&DevicePropertiesVkTest::enumerate, + &DevicePropertiesVkTest::constructMove, + &DevicePropertiesVkTest::wrap}); +} + +void DevicePropertiesVkTest::enumerate() { + Containers::Array devices = enumerateDevices(_instance); + Debug{} << "Found" << devices.size() << "devices"; + CORRADE_VERIFY(!devices.empty()); + + for(DeviceProperties& device: devices) { + CORRADE_ITERATION(device.name()); + + CORRADE_VERIFY(device.handle()); + CORRADE_COMPARE_AS(device.apiVersion(), Version::Vk10, + TestSuite::Compare::GreaterOrEqual); + CORRADE_COMPARE_AS(device.driverVersion(), Version::Vk10, + TestSuite::Compare::GreaterOrEqual); + CORRADE_VERIFY(device.type() != DeviceType::Other); + CORRADE_VERIFY(!device.name().isEmpty()); + } +} + +void DevicePropertiesVkTest::constructMove() { + Containers::Array devices = enumerateDevices(_instance); + CORRADE_VERIFY(!devices.empty()); + VkPhysicalDevice handle = devices[0].handle(); + Containers::StringView name = devices[0].name(); + + DeviceProperties a = std::move(devices[0]); + CORRADE_COMPARE(a.handle(), handle); + CORRADE_COMPARE(a.name(), name); + + DeviceProperties b = DeviceProperties::wrap(_instance, nullptr); + b = std::move(a); + CORRADE_COMPARE(b.handle(), handle); + CORRADE_COMPARE(b.name(), name); + + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); + CORRADE_VERIFY(std::is_nothrow_move_assignable::value); +} + +void DevicePropertiesVkTest::wrap() { + VkPhysicalDevice handle; + UnsignedInt count = 1; + auto result = Result(_instance->EnumeratePhysicalDevices(_instance, &count, &handle)); + { + /** @todo clean up once Compare::AnyOf exists */ + CORRADE_ITERATION(result); + CORRADE_VERIFY(result == Result::Success || result == Result::Incomplete); + } + + DeviceProperties wrapped = DeviceProperties::wrap(_instance, handle); + CORRADE_VERIFY(wrapped.handle()); + + Containers::Array devices = enumerateDevices(_instance); + CORRADE_COMPARE(wrapped.name(), devices[0].name()); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DevicePropertiesVkTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 587ccef7a..5fe7b1ca4 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -34,6 +34,8 @@ namespace Magnum { namespace Vk { #ifndef DOXYGEN_GENERATING_OUTPUT +class DeviceProperties; +enum class DeviceType: Int; class Extension; class ExtensionProperties; enum class HandleFlag: UnsignedByte;