Browse Source

Vk: rework device property fetching.

Today I spent six hours wrongly convincing myself that it's a driver bug
when vkGetPhysicalDeviceProperties2() is null on a 1.1 instance for a
1.0 physical device. It's not a bug, it's me not reading specs
carefully.

This commit thus basically moves all Instance-level extension-dependent
state to DeviceProperties, because it's actually device-dependent. Which
makes the DeviceProperties class quite heavy and thus it's good it was
readied to be transferred all the way to a Device instance a few commits
back -- I don't really want to do all the dispatch, string processing,
sorting and other mess more times than strictly necessary.

In addition, DeviceProperties::apiVersion() got renamed to version() and
a new isVersionSupported() API got added, mirroring what's on Device
itself; plus thanks to the chicken-and-egg problem of having to call
vkGetPhysicalDeviceProperties() twice, the device version and other
things can now be retrieved in a slightly more efficient way.
pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
022ba3c291
  1. 4
      src/Magnum/Vk/Device.cpp
  2. 2
      src/Magnum/Vk/Device.h
  3. 125
      src/Magnum/Vk/DeviceProperties.cpp
  4. 37
      src/Magnum/Vk/DeviceProperties.h
  5. 20
      src/Magnum/Vk/Implementation/InstanceState.cpp
  6. 8
      src/Magnum/Vk/Implementation/InstanceState.h
  7. 10
      src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp
  8. 24
      src/Magnum/Vk/Test/DeviceVkTest.cpp
  9. 4
      src/Magnum/Vk/vk-info.cpp

4
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) {

2
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; }

125
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<ExtensionProperties> extensions;
void(*getPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceProperties2&);
void(*getQueueFamilyPropertiesImplementation)(DeviceProperties&, UnsignedInt&, VkQueueFamilyProperties2*);
void(*getMemoryPropertiesImplementation)(DeviceProperties&, VkPhysicalDeviceMemoryProperties2&);
VkPhysicalDeviceProperties2 properties{};
VkPhysicalDeviceDriverProperties driverProperties{};
VkPhysicalDeviceMemoryProperties2 memoryProperties{};
Containers::Array<VkQueueFamilyProperties2> 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<Extensions::KHR::get_physical_device_properties2>()) {
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<void*> 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<Extensions::KHR::driver_properties>()) {
if(isVersionSupported(Version::Vk12) || extensionPropertiesInternal().isSupported<Extensions::KHR::driver_properties>()) {
*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<const VkQueueFamilyProperties2> 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<VkQueueFamilyProperties2>{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<UnsignedInt> 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;

37
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);

20
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<Extensions::KHR::get_physical_device_properties2>()) {
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} {}
}}}

8
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. */
};
}}}

10
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::KHR::get_physical_device_properties2>() || !extensions.isSupported<Extensions::KHR::driver_properties>()) {
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,

24
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<Extensions::EXT::debug_marker>());
@ -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<Extensions::EXT::debug_marker>(), data.debugMarkerEnabled);
CORRADE_COMPARE(device.isExtensionEnabled<Extensions::KHR::maintenance1>(), 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<Extensions::EXT::debug_marker>(), data.debugMarkerEnabled);
CORRADE_COMPARE(device.isExtensionEnabled<Extensions::KHR::maintenance1>(), 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<Extensions::KHR::maintenance1>());
/* 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<Extensions::KHR::maintenance1>());
/* Everything is swapped, including function pointers */
CORRADE_VERIFY(!b->CreateBuffer);

4
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,

Loading…
Cancel
Save