diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index f2834c65e..20b26f70f 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -83,7 +83,7 @@ DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const Ext /* Take the minimum of instance and device version. Instance version being smaller than a device version happens mainly if there's a forced Vulkan version via --magnum-vulkan version, which will be later used to cap available features. */ - _state->version = Version(Math::min(UnsignedInt(deviceProperties._instance->version()), UnsignedInt(deviceProperties.apiVersion()))); + _state->version = Version(Math::min(UnsignedInt(deviceProperties._instance->version()), UnsignedInt(deviceProperties.version()))); /* If there are any disabled extensions, sort them and save for later -- we'll use them to filter the ones added by the app */ @@ -317,7 +317,7 @@ Device::Device(Instance& instance, const DeviceCreateInfo& info, DevicePropertie _properties.emplace(DeviceProperties::wrap(instance, info._physicalDevice)); const Version version = info._state->version != Version::None ? - info._state->version : _properties->apiVersion(); + info._state->version : _properties->version(); /* Print all enabled extensions if we're not told to be quiet */ if(!info._state || !info._state->quietLog) { diff --git a/src/Magnum/Vk/Device.h b/src/Magnum/Vk/Device.h index 1613b56ab..ca2104cbd 100644 --- a/src/Magnum/Vk/Device.h +++ b/src/Magnum/Vk/Device.h @@ -462,7 +462,7 @@ class MAGNUM_VK_EXPORT Device { * * Unless overriden using `--magnum-vulkan-version` on the * @ref Vk-Device-command-line "command line", corresponds to - * @ref DeviceProperties::apiVersion(). + * @ref DeviceProperties::version(). */ Version version() const { return _version; } diff --git a/src/Magnum/Vk/DeviceProperties.cpp b/src/Magnum/Vk/DeviceProperties.cpp index 40833869c..9a5e28d86 100644 --- a/src/Magnum/Vk/DeviceProperties.cpp +++ b/src/Magnum/Vk/DeviceProperties.cpp @@ -47,12 +47,88 @@ namespace Magnum { namespace Vk { struct DeviceProperties::State { + explicit State(Instance& instance, VkPhysicalDevice handle); + + /* Cached device extension properties to dispatch on when querying + properties. Should be only used through + DeviceProperties::extensionPropertiesInternal(). */ + Containers::Optional extensions; + + void(*getPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&); + void(*getQueueFamilyPropertiesImplementation)(DeviceProperties&, UnsignedInt&, VkQueueFamilyProperties2*); + void(*getMemoryPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceMemoryProperties2&); + VkPhysicalDeviceProperties2 properties{}; VkPhysicalDeviceDriverProperties driverProperties{}; VkPhysicalDeviceMemoryProperties2 memoryProperties{}; Containers::Array queueFamilyProperties; }; +DeviceProperties::State::State(Instance& instance, const VkPhysicalDevice handle) { + /* All this extension-dependent dispatch has to be stored per physical + device, not just on instance, because it's actually instance-level + functionality depending on a version of a particular device. According + to https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap3.html#fundamentals-validusage-versions : + + Physical-device-level functionality or behavior added by a new core + version of the API must not be used unless it is supported by the + physical device as determined by VkPhysicalDeviceProperties::apiVersion + and the specified version of VkApplicationInfo::apiVersion. + + and https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap4.html#_extending_physical_device_core_functionality : + + New core physical-device-level functionality can be used when the + physical-device version is greater than or equal to the version of + Vulkan that added the new functionality. The Vulkan version supported + by a physical device can be obtained by calling + vkGetPhysicalDeviceProperties. + + and https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap4.html#initialization-phys-dev-extensions : + + Applications must not use a VkPhysicalDevice in any command added by an + extension or core version that is not supported by that physical + device. + + Which means for example, if Vulkan 1.1 is supported by the instance, it + doesn't actually imply I can use vkGetPhysicalDeviceProperties2() -- I + can only use that in case the device supports 1.1 as well, which means I + have to call vkGetPhysicalDeviceProperties() first in order to be able + to call vkGetPhysicalDeviceProperties2(). + + On the other hand, if the device is 1.0 but the instance + supports VK_KHR_get_physical_device_properties2, I can call + vkGetPhysicalDeviceProperties2KHR() directly -- https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap4.html#initialization-phys-dev-extensions : + + When the VK_KHR_get_physical_device_properties2 extension is enabled, + or when both the instance and the physical-device versions are at least + 1.1, physical-device-level functionality of a device extension can be + used with a physical device if the corresponding extension is + enumerated by vkEnumerateDeviceExtensionProperties for that physical + device, even before a logical device has been created. + + This also explains why e.g. VK_KHR_driver_properties is a device + extension and not instance extension -- I can only add it to the pNext + chain if the device is able to understand it, even though it's shoveled + there by an instance-level API. */ + + instance->GetPhysicalDeviceProperties(handle, &properties.properties); + + /* Have to check both the instance and device version, see above */ + if(instance.isVersionSupported(Version::Vk11) && Version(properties.properties.apiVersion) >= Version::Vk11) { + getPropertiesImplementation = &DeviceProperties::getPropertiesImplementation11; + getQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementation11; + getMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementation11; + } else if(instance.isExtensionEnabled()) { + getPropertiesImplementation = &DeviceProperties::getPropertiesImplementationKHR; + getQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationKHR; + getMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementationKHR; + } else { + getPropertiesImplementation = DeviceProperties::getPropertiesImplementationDefault; + getQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationDefault; + getMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementationDefault; + } +} + DeviceProperties::DeviceProperties(NoCreateT) noexcept: _instance{}, _handle{} {} DeviceProperties::DeviceProperties(Instance& instance, VkPhysicalDevice handle): _instance{&instance}, _handle{handle} {} @@ -65,8 +141,20 @@ DeviceProperties::~DeviceProperties() = default; DeviceProperties& DeviceProperties::operator=(DeviceProperties&&) noexcept = default; +Version DeviceProperties::version() { + return Version(properties1().apiVersion); +} + +bool DeviceProperties::isVersionSupported(const Version version) { + return Version(properties1().apiVersion) >= version; +} + +DeviceType DeviceProperties::type() { + return DeviceType(properties1().deviceType); +} + Containers::StringView DeviceProperties::name() { - return properties().properties.deviceName; + return properties1().deviceName; } DeviceDriver DeviceProperties::driver() { @@ -74,6 +162,10 @@ DeviceDriver DeviceProperties::driver() { return properties(), DeviceDriver(_state->driverProperties.driverID); } +Version DeviceProperties::driverVersion() { + return Version(properties1().driverVersion); +} + Containers::StringView DeviceProperties::driverName() { /* Ensure the values are populated first */ return properties(), _state->driverProperties.driverName; @@ -84,8 +176,14 @@ Containers::StringView DeviceProperties::driverInfo() { return properties(), _state->driverProperties.driverInfo; } +const VkPhysicalDeviceProperties& DeviceProperties::properties1() { + if(!_state) _state.emplace(*_instance, _handle); + + return _state->properties.properties; +} + const VkPhysicalDeviceProperties2& DeviceProperties::properties() { - if(!_state) _state.emplace(); + if(!_state) _state.emplace(*_instance, _handle); /* Properties not fetched yet, do that now */ if(!_state->properties.sType) { @@ -93,17 +191,14 @@ const VkPhysicalDeviceProperties2& DeviceProperties::properties() { Containers::Reference next = _state->properties.pNext; - /* Device extension properties. Populated only if needed. */ - ExtensionProperties extensions{NoCreate}; - /* Fetch driver properties, if supported */ - if(_instance->isVersionSupported(Version::Vk12) || (extensions = enumerateExtensionProperties()).isSupported()) { + if(isVersionSupported(Version::Vk12) || extensionPropertiesInternal().isSupported()) { *next = &_state->driverProperties; next = _state->driverProperties.pNext; _state->driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; } - _instance->state().getPhysicalDevicePropertiesImplementation(*this, _state->properties); + _state->getPropertiesImplementation(*this, _state->properties); } return _state->properties; @@ -132,18 +227,24 @@ ExtensionProperties DeviceProperties::enumerateExtensionProperties(std::initiali return enumerateExtensionProperties(Containers::arrayView(layers)); } +const ExtensionProperties& DeviceProperties::extensionPropertiesInternal() { + if(!_state) _state.emplace(*_instance, _handle); + if(!_state->extensions) _state->extensions = enumerateExtensionProperties(); + return *_state->extensions; +} + Containers::ArrayView DeviceProperties::queueFamilyProperties() { - if(!_state) _state.emplace(); + if(!_state) _state.emplace(*_instance, _handle); /* Fetch if not already */ if(_state->queueFamilyProperties.empty()) { UnsignedInt count; - _instance->state().getPhysicalDeviceQueueFamilyPropertiesImplementation(*this, count, nullptr); + _state->getQueueFamilyPropertiesImplementation(*this, count, nullptr); _state->queueFamilyProperties = Containers::Array{Containers::ValueInit, count}; for(VkQueueFamilyProperties2& i: _state->queueFamilyProperties) i.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; - _instance->state().getPhysicalDeviceQueueFamilyPropertiesImplementation(*this, count, _state->queueFamilyProperties); + _state->getQueueFamilyPropertiesImplementation(*this, count, _state->queueFamilyProperties); CORRADE_INTERNAL_ASSERT(count == _state->queueFamilyProperties.size()); } @@ -211,11 +312,11 @@ Containers::Optional DeviceProperties::tryPickQueueFamily(const Que } const VkPhysicalDeviceMemoryProperties2& DeviceProperties::memoryProperties() { - if(!_state) _state.emplace(); + if(!_state) _state.emplace(*_instance, _handle); if(!_state->memoryProperties.sType) { _state->memoryProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; - _instance->state().getPhysicalDeviceMemoryPropertiesImplementation(*this, _state->memoryProperties); + _state->getMemoryPropertiesImplementation(*this, _state->memoryProperties); } return _state->memoryProperties; diff --git a/src/Magnum/Vk/DeviceProperties.h b/src/Magnum/Vk/DeviceProperties.h index e934f6bef..101fab0b3 100644 --- a/src/Magnum/Vk/DeviceProperties.h +++ b/src/Magnum/Vk/DeviceProperties.h @@ -327,14 +327,19 @@ class MAGNUM_VK_EXPORT DeviceProperties { const VkPhysicalDeviceProperties2& properties(); /** - * @brief API version + * @brief Device version * * Convenience access to @ref properties() internals, populated lazily * on first request. */ - Version apiVersion() { - return Version(properties().properties.apiVersion); - } + Version version(); + + /** + * @brief Whether given version is supported on the device + * + * Compares @p version against @ref version(). + */ + bool isVersionSupported(Version version); /** * @brief Device type @@ -342,9 +347,7 @@ class MAGNUM_VK_EXPORT DeviceProperties { * Convenience access to @ref properties() internals, populated lazily * on first request. */ - DeviceType type() { - return DeviceType(properties().properties.deviceType); - } + DeviceType type(); /** * @brief Device name @@ -373,9 +376,7 @@ class MAGNUM_VK_EXPORT DeviceProperties { * Convenience access to @ref properties() internals, populated lazily * on first request. */ - Version driverVersion() { - return Version(properties().properties.driverVersion); - } + Version driverVersion(); /** * @brief Driver name @@ -612,6 +613,22 @@ class MAGNUM_VK_EXPORT DeviceProperties { explicit DeviceProperties(Instance& instance, VkPhysicalDevice handle); + /* The vkPhysicalDeviceProperties() function has to get called in any + case to decide if vkPhysicalDeviceProperties2() can get called. That + means we can get the VkPhysicalDeviceProperties subset in a cheaper + way than when going through properties(). This distinction however + would only confuse the users, so it's a private API and while + version(), name(), driverVersion() etc. queries use it they only + mention properties() in the public docs. */ + MAGNUM_VK_LOCAL const VkPhysicalDeviceProperties& properties1(); + + /* Cached version of enumerateExtensionProperties() for internal use by + the property query functions. The enumerateExtensionProperties() API + returns by-value because every time there can be a different set of + layers, so we can't do any caching on that level but need a separate + function. */ + MAGNUM_VK_LOCAL const ExtensionProperties& extensionPropertiesInternal(); + 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); diff --git a/src/Magnum/Vk/Implementation/InstanceState.cpp b/src/Magnum/Vk/Implementation/InstanceState.cpp index 75449384c..ffd0c0337 100644 --- a/src/Magnum/Vk/Implementation/InstanceState.cpp +++ b/src/Magnum/Vk/Implementation/InstanceState.cpp @@ -25,26 +25,8 @@ #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& instance, Int argc, const char** argv): argc{argc}, argv{argv} { - if(instance.isVersionSupported(Version::Vk11)) { - getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementation11; - getPhysicalDeviceQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementation11; - getPhysicalDeviceMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementation11; - } else if(instance.isExtensionEnabled()) { - getPhysicalDevicePropertiesImplementation = &DeviceProperties::getPropertiesImplementationKHR; - getPhysicalDeviceQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationKHR; - getPhysicalDeviceMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementationKHR; - } else { - getPhysicalDevicePropertiesImplementation = DeviceProperties::getPropertiesImplementationDefault; - getPhysicalDeviceQueueFamilyPropertiesImplementation = &DeviceProperties::getQueueFamilyPropertiesImplementationDefault; - getPhysicalDeviceMemoryPropertiesImplementation = &DeviceProperties::getMemoryPropertiesImplementationDefault; - } -} +InstanceState::InstanceState(Instance&, Int argc, const char** argv): argc{argc}, argv{argv} {} }}} diff --git a/src/Magnum/Vk/Implementation/InstanceState.h b/src/Magnum/Vk/Implementation/InstanceState.h index b6821ea7f..9ab7c763a 100644 --- a/src/Magnum/Vk/Implementation/InstanceState.h +++ b/src/Magnum/Vk/Implementation/InstanceState.h @@ -26,7 +26,6 @@ */ #include "Magnum/Vk/Vk.h" -#include "Magnum/Vk/Vulkan.h" namespace Magnum { namespace Vk { namespace Implementation { @@ -36,9 +35,10 @@ struct InstanceState { Int argc; const char** argv; - void(*getPhysicalDevicePropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&); - void(*getPhysicalDeviceQueueFamilyPropertiesImplementation)(DeviceProperties&, UnsignedInt&, VkQueueFamilyProperties2*); - void(*getPhysicalDeviceMemoryPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceMemoryProperties2&); + /* There are currently no instance-level extension-dependent code paths. + Everything is currently in DeviceProperties internals, as + physical-device-level APIs depend on device version, not instance + version, and thus have to be wired up differently for each device. */ }; }}} diff --git a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp index 0cfc40fe4..5bc3d42e4 100644 --- a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp +++ b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp @@ -142,8 +142,11 @@ void DevicePropertiesVkTest::enumerate() { CORRADE_ITERATION(device.name()); CORRADE_VERIFY(device.handle()); - CORRADE_COMPARE_AS(device.apiVersion(), Version::Vk10, + CORRADE_COMPARE_AS(device.version(), Version::Vk10, TestSuite::Compare::GreaterOrEqual); + /* Device version is supported */ + CORRADE_VERIFY(device.isVersionSupported(device.version())); + CORRADE_VERIFY(!device.isVersionSupported(Version::None)); CORRADE_COMPARE_AS(device.driverVersion(), Version::Vk10, TestSuite::Compare::GreaterOrEqual); CORRADE_VERIFY(device.type() != DeviceType::Other); @@ -193,15 +196,12 @@ void DevicePropertiesVkTest::driverProperties() { Debug{} << "Driver ID:" << device->driver(); - ExtensionProperties extensions = device->enumerateExtensionProperties(); - if(!instance().isExtensionEnabled() || !extensions.isSupported()) { - CORRADE_COMPARE(device->driver(), DeviceDriver::Unknown); + if(device->driver() == DeviceDriver::Unknown) { CORRADE_COMPARE(device->driverName(), ""); CORRADE_COMPARE(device->driverInfo(), ""); CORRADE_SKIP("KHR_driver_properties not supported."); } - CORRADE_VERIFY(Int(device->driver())); CORRADE_VERIFY(!device->driverName().isEmpty()); { CORRADE_EXPECT_FAIL_IF(device->driver() == DeviceDriver::GoogleSwiftShader, diff --git a/src/Magnum/Vk/Test/DeviceVkTest.cpp b/src/Magnum/Vk/Test/DeviceVkTest.cpp index b6c8d43ba..0c4276940 100644 --- a/src/Magnum/Vk/Test/DeviceVkTest.cpp +++ b/src/Magnum/Vk/Test/DeviceVkTest.cpp @@ -284,9 +284,9 @@ void DeviceVkTest::construct() { /* Device function pointers should be populated */ CORRADE_VERIFY(device->CreateBuffer); CORRADE_COMPARE(device.handleFlags(), HandleFlag::DestroyOnDestruction); - CORRADE_COMPARE(device.version(), deviceProperties.apiVersion()); + CORRADE_COMPARE(device.version(), deviceProperties.version()); /* Device version is supported */ - CORRADE_VERIFY(device.isVersionSupported(deviceProperties.apiVersion())); + CORRADE_VERIFY(device.isVersionSupported(deviceProperties.version())); CORRADE_VERIFY(!device.isVersionSupported(Version::None)); /* No extensions are enabled by default ... */ CORRADE_VERIFY(!device.isExtensionEnabled()); @@ -397,14 +397,14 @@ void DeviceVkTest::constructExtensionsCommandLineDisable() { Extensions::KHR::maintenance1 >()}; CORRADE_VERIFY(device.handle()); - CORRADE_COMPARE(device.isVersionSupported(deviceProperties.apiVersion()), data.driverVersionSupported); + CORRADE_COMPARE(device.isVersionSupported(deviceProperties.version()), data.driverVersionSupported); CORRADE_COMPARE(device.isExtensionEnabled(), data.debugMarkerEnabled); CORRADE_COMPARE(device.isExtensionEnabled(), data.maintenance1Enabled); /** @todo cleanup when Debug::toString() or some similar utility exists */ - UnsignedInt major = versionMajor(deviceProperties.apiVersion()); - UnsignedInt minor = versionMinor(deviceProperties.apiVersion()); - UnsignedInt patch = versionPatch(deviceProperties.apiVersion()); + UnsignedInt major = versionMajor(deviceProperties.version()); + UnsignedInt minor = versionMinor(deviceProperties.version()); + UnsignedInt patch = versionPatch(deviceProperties.version()); /* SwiftShader reports just 1.1 with no patch version, special-case that */ CORRADE_COMPARE(out.str(), Utility::formatString(data.log, deviceProperties.name(), major, minor, patch ? Utility::formatString(".{}", patch) : "")); @@ -451,14 +451,14 @@ void DeviceVkTest::constructExtensionsCommandLineEnable() { /* Nothing enabled by the application */ }; CORRADE_VERIFY(device.handle()); - CORRADE_COMPARE(device.isVersionSupported(deviceProperties.apiVersion()), data.driverVersionSupported); + CORRADE_COMPARE(device.isVersionSupported(deviceProperties.version()), data.driverVersionSupported); CORRADE_COMPARE(device.isExtensionEnabled(), data.debugMarkerEnabled); CORRADE_COMPARE(device.isExtensionEnabled(), data.maintenance1Enabled); /** @todo cleanup when Debug::toString() or some similar utility exists */ - UnsignedInt major = versionMajor(deviceProperties.apiVersion()); - UnsignedInt minor = versionMinor(deviceProperties.apiVersion()); - UnsignedInt patch = versionPatch(deviceProperties.apiVersion()); + UnsignedInt major = versionMajor(deviceProperties.version()); + UnsignedInt minor = versionMinor(deviceProperties.version()); + UnsignedInt patch = versionPatch(deviceProperties.version()); /* SwiftShader reports just 1.1 with no patch version, special-case that */ CORRADE_COMPARE(out.str(), Utility::formatString(data.log, deviceProperties.name(), major, minor, patch ? Utility::formatString(".{}", patch) : "")); @@ -575,7 +575,7 @@ void DeviceVkTest::constructMove() { CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction); CORRADE_COMPARE(b.handle(), handle); CORRADE_COMPARE(b.version(), version); - CORRADE_COMPARE(b.properties().apiVersion(), version); + CORRADE_COMPARE(b.properties().version(), version); CORRADE_VERIFY(b.isExtensionEnabled()); /* Function pointers in a are left in whatever state they were before, as that doesn't matter */ @@ -588,7 +588,7 @@ void DeviceVkTest::constructMove() { CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction); CORRADE_COMPARE(c.handle(), handle); CORRADE_COMPARE(c.version(), version); - CORRADE_COMPARE(c.properties().apiVersion(), version); + CORRADE_COMPARE(c.properties().version(), version); CORRADE_VERIFY(c.isExtensionEnabled()); /* Everything is swapped, including function pointers */ CORRADE_VERIFY(!b->CreateBuffer); diff --git a/src/Magnum/Vk/vk-info.cpp b/src/Magnum/Vk/vk-info.cpp index 77e1b8420..dbad22f64 100644 --- a/src/Magnum/Vk/vk-info.cpp +++ b/src/Magnum/Vk/vk-info.cpp @@ -233,7 +233,7 @@ int main(int argc, char** argv) { Debug{} << "Found" << devices.size() << "devices:"; for(Vk::DeviceProperties& device: devices) { Debug{} << " " << device.name() << Debug::nospace << "," - << device.apiVersion() << Debug::newline + << device.version() << Debug::newline << " " << device.type() << Debug::nospace << ", driver" << Debug::packed << device.driverVersion(); } @@ -247,7 +247,7 @@ int main(int argc, char** argv) { Debug{} << "Picked device" << device.name() << Debug::newline; - const Vk::Version deviceVersion = device.apiVersion(); + const Vk::Version deviceVersion = device.version(); Debug{} << "Reported version:" << deviceVersion; /* Driver info. Print only if the device actually reports something,