diff --git a/doc/vulkan-support.dox b/doc/vulkan-support.dox index 95309a5db..f7ceb2bfc 100644 --- a/doc/vulkan-support.dox +++ b/doc/vulkan-support.dox @@ -96,7 +96,7 @@ Extension | Status @vk_extension{KHR,shader_subgroup_extended_types} | | @vk_extension{KHR,8bit_storage} | | @vk_extension{KHR,shader_atomic_int64} | | -@vk_extension{KHR,driver_properties} | | +@vk_extension{KHR,driver_properties} | mostly @vk_extension{KHR,shader_float_controls} | | @vk_extension{KHR,depth_stencil_resolve} | | @vk_extension{KHR,timeline_semaphore} | | diff --git a/src/Magnum/Vk/DeviceProperties.cpp b/src/Magnum/Vk/DeviceProperties.cpp index 0417e993a..e6b0d27bc 100644 --- a/src/Magnum/Vk/DeviceProperties.cpp +++ b/src/Magnum/Vk/DeviceProperties.cpp @@ -33,11 +33,13 @@ #include #include "Magnum/Math/Functions.h" -#include "Magnum/Vk/Instance.h" #include "Magnum/Vk/ExtensionProperties.h" +#include "Magnum/Vk/Extensions.h" +#include "Magnum/Vk/Instance.h" #include "Magnum/Vk/LayerProperties.h" #include "Magnum/Vk/Memory.h" #include "Magnum/Vk/Result.h" +#include "Magnum/Vk/Version.h" #include "Magnum/Vk/Implementation/Arguments.h" #include "Magnum/Vk/Implementation/InstanceState.h" @@ -45,6 +47,7 @@ namespace Magnum { namespace Vk { struct DeviceProperties::State { VkPhysicalDeviceProperties2 properties{}; + VkPhysicalDeviceDriverProperties driverProperties{}; VkPhysicalDeviceMemoryProperties2 memoryProperties{}; Containers::Array queueFamilyProperties; }; @@ -65,6 +68,21 @@ Containers::StringView DeviceProperties::name() { return properties().properties.deviceName; } +DeviceDriver DeviceProperties::driver() { + /* Ensure the values are populated first */ + return properties(), DeviceDriver(_state->driverProperties.driverID); +} + +Containers::StringView DeviceProperties::driverName() { + /* Ensure the values are populated first */ + return properties(), _state->driverProperties.driverName; +} + +Containers::StringView DeviceProperties::driverInfo() { + /* Ensure the values are populated first */ + return properties(), _state->driverProperties.driverInfo; +} + const VkPhysicalDeviceProperties2& DeviceProperties::properties() { if(!_state) _state.emplace(); @@ -72,6 +90,18 @@ const VkPhysicalDeviceProperties2& DeviceProperties::properties() { if(!_state->properties.sType) { _state->properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + 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()) { + *next = &_state->driverProperties; + next = _state->driverProperties.pNext; + _state->driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + } + _instance->state().getPhysicalDevicePropertiesImplementation(*this, _state->properties); } @@ -378,6 +408,35 @@ Debug& operator<<(Debug& debug, const DeviceType value) { return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; } +Debug& operator<<(Debug& debug, const DeviceDriver value) { + debug << "Vk::DeviceDriver" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::DeviceDriver::value: return debug << "::" << Debug::nospace << #value; + _c(Unknown) + _c(AmdOpenSource) + _c(AmdProprietary) + _c(ArmProprietary) + _c(BroadcomProprietary) + _c(GgpProprietary) + _c(GoogleSwiftShader) + _c(ImaginationProprietary) + _c(IntelOpenSourceMesa) + _c(IntelProprietaryWindows) + _c(MesaLlvmpipe) + _c(MesaRadv) + _c(MoltenVk) + _c(NVidiaProprietary) + _c(QualcommProprietary) + #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 << ")"; +} + Debug& operator<<(Debug& debug, const QueueFlag value) { debug << "Vk::QueueFlag" << Debug::nospace; diff --git a/src/Magnum/Vk/DeviceProperties.h b/src/Magnum/Vk/DeviceProperties.h index 2fcb09f42..ebd5f4165 100644 --- a/src/Magnum/Vk/DeviceProperties.h +++ b/src/Magnum/Vk/DeviceProperties.h @@ -80,6 +80,75 @@ enum class DeviceType: Int { */ MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DeviceType value); +/** +@brief Physical device driver ID +@m_since_latest + +Wraps a @type_vk_keyword{DriverId}. +@see @ref DeviceProperties::driver() +@requires_vk12 Extension @vk_extension{KHR,driver_properties} +@m_enum_values_as_keywords +*/ +enum class DeviceDriver: Int { + /** + * Unknown. Returned from @ref DeviceProperties::driver() in case Vulkan + * 1.2 or the @vk_extension{KHR,driver_properties} extension isn't + * supported. + */ + Unknown = 0, + + /* Unlike with VkDriverId, which gets allocated sequentially, the rest of + this list is sorted alphabetically for easier lookup. */ + + /** Open-source AMD */ + AmdOpenSource = VK_DRIVER_ID_AMD_OPEN_SOURCE, + + /** Proprietary AMD */ + AmdProprietary = VK_DRIVER_ID_AMD_PROPRIETARY, + + /** Proprietary ARM */ + ArmProprietary = VK_DRIVER_ID_ARM_PROPRIETARY, + + /** Proprietary Broadcom */ + BroadcomProprietary = VK_DRIVER_ID_BROADCOM_PROPRIETARY, + + /** Proprietary GGP */ + GgpProprietary = VK_DRIVER_ID_GGP_PROPRIETARY, + + /** Google SwiftShader */ + GoogleSwiftShader = VK_DRIVER_ID_GOOGLE_SWIFTSHADER, + + /** Proprietary Imagination */ + ImaginationProprietary = VK_DRIVER_ID_IMAGINATION_PROPRIETARY, + + /** Open-source Intel Mesa drivers */ + IntelOpenSourceMesa = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA, + + /** Proprietary Intel driver on Windows */ + IntelProprietaryWindows = VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, + + /** Mesa LLVMpipe */ + MesaLlvmpipe = VK_DRIVER_ID_MESA_LLVMPIPE, + + /** Mesa RADV */ + MesaRadv = VK_DRIVER_ID_MESA_RADV, + + /** MoltenVK */ + MoltenVk = VK_DRIVER_ID_MOLTENVK, + + /** Proprietary NVidia */ + NVidiaProprietary = VK_DRIVER_ID_NVIDIA_PROPRIETARY, + + /** Proprietary Qualcomm */ + QualcommProprietary = VK_DRIVER_ID_QUALCOMM_PROPRIETARY, +}; + +/** +@debugoperatorclassenum{DeviceProperties,DeviceDriver} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DeviceDriver value); + /** @brief Queue flag @m_since_latest @@ -236,11 +305,19 @@ class MAGNUM_VK_EXPORT DeviceProperties { /** * @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. + * Populated lazily on first request. If Vulkan 1.1 is not supported + * and 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. Otherwise: + * + * - If Vulkan 1.2 is supported or the + * @vk_extension{KHR,driver_properties} extension is supported by + * the device, the `pNext` chain contains a + * @type_vk{PhysicalDeviceDriverProperties} structure and the + * @ref driver(), @ref driverName() and @ref driverInfo() + * properties are populated. + * * @see @fn_vk_keyword{GetPhysicalDeviceProperties2}, * @fn_vk_keyword{GetPhysicalDeviceProperties} */ @@ -256,6 +333,37 @@ class MAGNUM_VK_EXPORT DeviceProperties { return Version(properties().properties.apiVersion); } + /** + * @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(); + + /** + * @brief Driver ID + * + * Convenience access to @ref properties() internals, populated lazily + * on first request. Only present if Vulkan 1.2 is supported or the + * @vk_extension{KHR,driver_properties} extension is supported by the + * device, otherwise returns @ref DeviceDriver::Unknown. Note that + * there might be driver IDs not yet listed in the @ref DeviceDriver + * enum, moreover drivers are allowed to return unregistered IDs as + * well. + */ + DeviceDriver driver(); + /** * @brief Driver version * @@ -267,22 +375,24 @@ class MAGNUM_VK_EXPORT DeviceProperties { } /** - * @brief Device type + * @brief Driver name * * Convenience access to @ref properties() internals, populated lazily - * on first request. + * on first request. Only present if Vulkan 1.2 is supported or the + * @vk_extension{KHR,driver_properties} extension is supported by the + * device, otherwise returns an empty string. */ - DeviceType type() { - return DeviceType(properties().properties.deviceType); - } + Containers::StringView driverName(); /** - * @brief Device name + * @brief Driver info * * Convenience access to @ref properties() internals, populated lazily - * on first request. + * on first request. Only present if Vulkan 1.2 is supported or the + * @vk_extension{KHR,driver_properties} extension is supported by the + * device, otherwise returns an empty string. */ - Containers::StringView name(); + Containers::StringView driverInfo(); /** * @brief Enumerate device extensions diff --git a/src/Magnum/Vk/Test/DevicePropertiesTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesTest.cpp index 72f09eefc..cdf66a460 100644 --- a/src/Magnum/Vk/Test/DevicePropertiesTest.cpp +++ b/src/Magnum/Vk/Test/DevicePropertiesTest.cpp @@ -38,6 +38,7 @@ struct DevicePropertiesTest: TestSuite::Tester { void constructCopy(); void debugDeviceType(); + void debugDeviceDriver(); void debugQueueFamilyPropertiesFlag(); void debugQueueFamilyPropertiesFlags(); void debugMemoryHeapFlag(); @@ -49,6 +50,7 @@ DevicePropertiesTest::DevicePropertiesTest() { &DevicePropertiesTest::constructCopy, &DevicePropertiesTest::debugDeviceType, + &DevicePropertiesTest::debugDeviceDriver, &DevicePropertiesTest::debugQueueFamilyPropertiesFlag, &DevicePropertiesTest::debugQueueFamilyPropertiesFlags, &DevicePropertiesTest::debugMemoryHeapFlag, @@ -76,6 +78,12 @@ void DevicePropertiesTest::debugDeviceType() { CORRADE_COMPARE(out.str(), "Vk::DeviceType::DiscreteGpu Vk::DeviceType(-10007655)\n"); } +void DevicePropertiesTest::debugDeviceDriver() { + std::ostringstream out; + Debug{&out} << DeviceDriver::MesaLlvmpipe << DeviceDriver(-10007655); + CORRADE_COMPARE(out.str(), "Vk::DeviceDriver::MesaLlvmpipe Vk::DeviceDriver(-10007655)\n"); +} + void DevicePropertiesTest::debugQueueFamilyPropertiesFlag() { std::ostringstream out; Debug{&out} << QueueFlag::SparseBinding << QueueFlag(0xdeadcafe); diff --git a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp index 624f5a433..0cfc40fe4 100644 --- a/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp +++ b/src/Magnum/Vk/Test/DevicePropertiesVkTest.cpp @@ -61,6 +61,8 @@ struct DevicePropertiesVkTest: VulkanTester { void extensionIsSupported(); void extensionNamedRevision(); + void driverProperties(); + void queueFamilies(); void queueFamiliesOutOfRange(); void queueFamiliesPick(); @@ -107,6 +109,8 @@ DevicePropertiesVkTest::DevicePropertiesVkTest(): VulkanTester{NoCreate} { &DevicePropertiesVkTest::extensionIsSupported, &DevicePropertiesVkTest::extensionNamedRevision, + &DevicePropertiesVkTest::driverProperties, + &DevicePropertiesVkTest::queueFamilies, &DevicePropertiesVkTest::queueFamiliesOutOfRange, &DevicePropertiesVkTest::queueFamiliesPick, @@ -183,6 +187,29 @@ void DevicePropertiesVkTest::wrap() { CORRADE_COMPARE(wrapped.name(), devices[0].name()); } +void DevicePropertiesVkTest::driverProperties() { + Containers::Optional device = tryPickDevice(instance()); + CORRADE_VERIFY(device); + + Debug{} << "Driver ID:" << device->driver(); + + ExtensionProperties extensions = device->enumerateExtensionProperties(); + if(!instance().isExtensionEnabled() || !extensions.isSupported()) { + CORRADE_COMPARE(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, + "SwiftShader reports empty driver info."); + CORRADE_VERIFY(!device->driverInfo().isEmpty()); + } +} + void DevicePropertiesVkTest::enumerateExtensions() { Containers::Array devices = enumerateDevices(instance()); CORRADE_VERIFY(!devices.empty()); diff --git a/src/Magnum/Vk/vk-info.cpp b/src/Magnum/Vk/vk-info.cpp index 98ae245d5..77e1b8420 100644 --- a/src/Magnum/Vk/vk-info.cpp +++ b/src/Magnum/Vk/vk-info.cpp @@ -250,6 +250,19 @@ int main(int argc, char** argv) { const Vk::Version deviceVersion = device.apiVersion(); Debug{} << "Reported version:" << deviceVersion; + /* Driver info. Print only if the device actually reports something, + otherwise assume VK_KHR_driver_properties are not supported. Due to the + mess that's VK_KHR_get_physical_device_properties2 and the interactions + between instance and driver version it's not possible to easily check + for extension presence. */ + if(Int(device.driver())) { + Debug{} << "Driver:" << device.driverName() << "(" << Debug::nospace << device.driver() << Debug::nospace << ")"; + Debug{} << "Driver info:" << device.driverInfo() << "(version" << Debug::packed << device.driverVersion() << Debug::nospace << ")"; + + /* Otherwise just print an Unknown placeholder, indicating the extension + is not supported */ + } else Debug{} << "Driver:" << device.driver(); + std::size_t deviceFuture = 0; if(!args.isSet("all-extensions"))