mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
13 KiB
327 lines
13 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
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 <Corrade/Utility/Arguments.h> |
|
|
|
#include "Magnum/Vk/Extensions.h" |
|
#include "Magnum/Vk/ExtensionProperties.h" |
|
#include "Magnum/Vk/InstanceCreateInfo.h" |
|
#include "Magnum/Vk/LayerProperties.h" |
|
#include "Magnum/Vk/Memory.h" |
|
#include "Magnum/Vk/DeviceProperties.h" |
|
#include "Magnum/Vk/Version.h" |
|
|
|
namespace Magnum { |
|
|
|
/** @page magnum-vk-info Magnum Vulkan Info |
|
@brief Displays information about Magnum engine Vulkan capabilities |
|
@m_since_latest |
|
|
|
@m_footernavigation |
|
@m_keywords{magnum-vk-info vk-info} |
|
|
|
This utility is built if both `WITH_VK` and `WITH_VK_INFO` is enabled when |
|
building Magnum. To use this utility with CMake, you need to request the |
|
`vk-info` component of the `Magnum` package and use the `Magnum::vk-info` |
|
target for example in a custom command: |
|
|
|
@code{.cmake} |
|
find_package(Magnum REQUIRED vk-info) |
|
|
|
add_custom_command(OUTPUT ... COMMAND Magnum::vk-info ...) |
|
@endcode |
|
|
|
See @ref building, @ref cmake and the @ref Vk namespace for more information. |
|
*/ |
|
|
|
} |
|
|
|
using namespace Magnum; |
|
|
|
int main(int argc, char** argv) { |
|
Utility::Arguments args; |
|
args.addBooleanOption("extension-strings").setHelp("extension-strings", "list all extension strings provided by the driver") |
|
.addBooleanOption("all-extensions").setHelp("all-extensions", "display extensions also for fully supported versions") |
|
.addSkippedPrefix("magnum", "engine-specific options") |
|
.setGlobalHelp("Displays information about Magnum engine and Vulkan capabilities.") |
|
.parse(argc, argv); |
|
|
|
/* Setup InstanceCreateInfo before printing anything so --magnum-help has |
|
uncluttered output */ |
|
/** @todo add a NoCreate InstanceInfo that just populates internal state |
|
without querying vulkan for anything? or that's stupid? */ |
|
Vk::LayerProperties layerProperties = Vk::enumerateLayerProperties(); |
|
Vk::InstanceExtensionProperties instanceExtensionProperties = Vk::enumerateInstanceExtensionProperties({layerProperties.names()}); |
|
|
|
Vk::InstanceCreateInfo instanceCreateInfo{argc, argv, &layerProperties, &instanceExtensionProperties}; |
|
|
|
Debug{} << ""; |
|
Debug{} << " +---------------------------------------------------------+"; |
|
Debug{} << " | Information about Magnum engine Vulkan capabilities |"; |
|
Debug{} << " +---------------------------------------------------------+"; |
|
Debug{} << ""; |
|
|
|
Debug{} << "Compilation flags:"; |
|
#ifdef CORRADE_BUILD_DEPRECATED |
|
Debug{} << " CORRADE_BUILD_DEPRECATED"; |
|
#endif |
|
#ifdef CORRADE_BUILD_STATIC |
|
Debug{} << " CORRADE_BUILD_STATIC"; |
|
#endif |
|
#ifdef CORRADE_BUILD_MULTITHREADED |
|
Debug{} << " CORRADE_BUILD_MULTITHREADED"; |
|
#endif |
|
#ifdef CORRADE_TARGET_UNIX |
|
Debug{} << " CORRADE_TARGET_UNIX"; |
|
#endif |
|
#ifdef CORRADE_TARGET_APPLE |
|
Debug{} << " CORRADE_TARGET_APPLE"; |
|
#endif |
|
#ifdef CORRADE_TARGET_IOS |
|
Debug{} << " CORRADE_TARGET_IOS"; |
|
#endif |
|
#ifdef CORRADE_TARGET_WINDOWS |
|
Debug{} << " CORRADE_TARGET_WINDOWS"; |
|
#endif |
|
#ifdef CORRADE_TARGET_WINDOWS_RT |
|
Debug{} << " CORRADE_TARGET_WINDOWS_RT"; |
|
#endif |
|
#ifdef CORRADE_TARGET_ANDROID |
|
Debug{} << " CORRADE_TARGET_ANDROID"; |
|
#endif |
|
#ifdef CORRADE_TARGET_X86 |
|
Debug{} << " CORRADE_TARGET_X86"; |
|
#endif |
|
#ifdef CORRADE_TARGET_ARM |
|
Debug{} << " CORRADE_TARGET_ARM"; |
|
#endif |
|
#ifdef CORRADE_TARGET_POWERPC |
|
Debug{} << " CORRADE_TARGET_POWERPC"; |
|
#endif |
|
#ifdef CORRADE_TARGET_BIG_ENDIAN |
|
Debug{} << " CORRADE_TARGET_BIG_ENDIAN"; |
|
#endif |
|
#ifdef CORRADE_TARGET_GCC |
|
Debug{} << " CORRADE_TARGET_GCC"; |
|
#endif |
|
#ifdef CORRADE_TARGET_CLANG |
|
Debug{} << " CORRADE_TARGET_CLANG"; |
|
#endif |
|
#ifdef CORRADE_TARGET_APPLE_CLANG |
|
Debug{} << " CORRADE_TARGET_APPLE_CLANG"; |
|
#endif |
|
#ifdef CORRADE_TARGET_CLANG_CL |
|
Debug{} << " CORRADE_TARGET_CLANG_CL"; |
|
#endif |
|
#ifdef CORRADE_TARGET_MSVC |
|
Debug{} << " CORRADE_TARGET_MSVC"; |
|
#endif |
|
#ifdef CORRADE_TARGET_MINGW |
|
Debug{} << " CORRADE_TARGET_MINGW"; |
|
#endif |
|
#ifdef CORRADE_TARGET_LIBCXX |
|
Debug{} << " CORRADE_TARGET_LIBCXX"; |
|
#endif |
|
#ifdef CORRADE_TARGET_LIBSTDCXX |
|
Debug{} << " CORRADE_TARGET_LIBSTDCXX"; |
|
#endif |
|
#ifdef CORRADE_TARGET_DINKUMWARE |
|
Debug{} << " CORRADE_TARGET_DINKUMWARE"; |
|
#endif |
|
#ifdef CORRADE_TARGET_SSE2 |
|
Debug{} << " CORRADE_TARGET_SSE2"; |
|
#endif |
|
#ifdef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT |
|
Debug{} << " CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT"; |
|
#endif |
|
#ifdef CORRADE_TESTSUITE_TARGET_XCTEST |
|
Debug{} << " CORRADE_TESTSUITE_TARGET_XCTEST"; |
|
#endif |
|
#ifdef CORRADE_UTILITY_USE_ANSI_COLORS |
|
Debug{} << " CORRADE_UTILITY_USE_ANSI_COLORS"; |
|
#endif |
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
Debug{} << " MAGNUM_BUILD_DEPRECATED"; |
|
#endif |
|
#ifdef MAGNUM_BUILD_STATIC |
|
Debug{} << " MAGNUM_BUILD_STATIC"; |
|
#endif |
|
Debug{} << ""; |
|
|
|
const Vk::Version instanceVersion = Vk::enumerateInstanceVersion(); |
|
Debug{} << "Reported instance version:" << instanceVersion; |
|
Debug{} << "Reported instance layers:"; |
|
for(UnsignedInt i = 0, max = layerProperties.count(); i != max; ++i) { |
|
Debug{} << " " << layerProperties.name(i) << "(r" << Debug::nospace << layerProperties.revision(i) << Debug::nospace << ", written against" << layerProperties.version(i) << Debug::nospace << ")"; |
|
Debug{} << " " << layerProperties.description(i); |
|
} |
|
|
|
constexpr Vk::Version versions[]{ |
|
Vk::Version::Vk11, |
|
Vk::Version::Vk12, |
|
Vk::Version::None |
|
}; |
|
std::size_t instanceFuture = 0; |
|
|
|
if(!args.isSet("all-extensions")) |
|
while(versions[instanceFuture] != Vk::Version::None && instanceVersion >= versions[instanceFuture]) |
|
++instanceFuture; |
|
|
|
/** @todo do better once implemented in format() */ |
|
using namespace Containers::Literals; |
|
constexpr Containers::StringView sixtyfourSpaces = " "_s; |
|
|
|
if(args.isSet("extension-strings")) { |
|
Debug{} << "Reported instance extension strings:"; |
|
for(std::size_t i = 0, max = instanceExtensionProperties.count(); i != max; ++i) { |
|
Debug d; |
|
d << " " << instanceExtensionProperties.name(i) << "(r" << Debug::nospace << instanceExtensionProperties.revision(i) << Debug::nospace; |
|
const UnsignedInt layer = instanceExtensionProperties.layer(i); |
|
if(layer != 0) |
|
d << ", from" << layerProperties.names()[layer - 1] << Debug::nospace; |
|
d << ")"; |
|
} |
|
|
|
} else for(std::size_t i = instanceFuture; i != Containers::arraySize(versions); ++i) { |
|
Containers::ArrayView<const Vk::InstanceExtension> extensions = Vk::InstanceExtension::extensions(versions[i]); |
|
if(extensions.empty()) continue; |
|
|
|
if(versions[i] != Vk::Version::None) |
|
Debug{} << versions[i] << "instance extension support:"; |
|
else Debug{} << "Vendor instance extension support:"; |
|
|
|
for(const Vk::InstanceExtension& extension: extensions) { |
|
Debug d; |
|
d << " " << extension.string() << sixtyfourSpaces.prefix(64 - extension.string().size()); |
|
|
|
if(instanceExtensionProperties.isSupported(extension)) |
|
d << "REV." << Debug::nospace << instanceExtensionProperties.revision(extension); |
|
else if(instanceVersion >= extension.requiredVersion()) |
|
d << " -"; |
|
else |
|
d << " n/a"; |
|
} |
|
} |
|
|
|
Debug{} << ""; |
|
|
|
Vk::Instance instance{instanceCreateInfo}; |
|
|
|
{ |
|
Containers::Array<Vk::DeviceProperties> devices = Vk::enumerateDevices(instance); |
|
Debug{} << "Found" << devices.size() << "devices:"; |
|
for(Vk::DeviceProperties& device: devices) { |
|
Debug{} << " " << device.name() << Debug::nospace << "," |
|
<< device.version() << Debug::newline |
|
<< " " << device.type() << Debug::nospace << ", driver" |
|
<< Debug::packed << device.driverVersion(); |
|
} |
|
|
|
if(devices.empty()) return 0; |
|
} |
|
|
|
Debug{} << ""; |
|
|
|
Vk::DeviceProperties device = Vk::pickDevice(instance); |
|
|
|
Debug{} << "Picked device" << device.name() << Debug::newline; |
|
|
|
const Vk::Version deviceVersion = device.version(); |
|
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")) |
|
while(versions[deviceFuture] != Vk::Version::None && deviceVersion >= versions[deviceFuture]) |
|
++deviceFuture; |
|
|
|
Vk::ExtensionProperties extensionProperties = device.enumerateExtensionProperties(layerProperties.names()); |
|
|
|
if(args.isSet("extension-strings")) { |
|
Debug{} << "Reported extension strings:"; |
|
for(std::size_t i = 0, max = extensionProperties.count(); i != max; ++i) { |
|
Debug d; |
|
d << " " << extensionProperties.name(i) << "(r" << Debug::nospace << extensionProperties.revision(i) << Debug::nospace; |
|
const UnsignedInt layer = extensionProperties.layer(i); |
|
if(layer != 0) |
|
d << ", from" << layerProperties.names()[layer - 1] << Debug::nospace; |
|
d << ")"; |
|
} |
|
|
|
} else for(std::size_t i = deviceFuture; i != Containers::arraySize(versions); ++i) { |
|
Containers::ArrayView<const Vk::Extension> extensions = Vk::Extension::extensions(versions[i]); |
|
if(extensions.empty()) continue; |
|
|
|
if(versions[i] != Vk::Version::None) |
|
Debug{} << versions[i] << "extension support:"; |
|
else Debug{} << "Vendor extension support:"; |
|
|
|
for(const Vk::Extension& extension: extensions) { |
|
Debug d; |
|
d << " " << extension.string() << sixtyfourSpaces.prefix(64 - extension.string().size()); |
|
|
|
if(extensionProperties.isSupported(extension)) |
|
d << "REV." << Debug::nospace << extensionProperties.revision(extension); |
|
else if(deviceVersion >= extension.requiredVersion()) |
|
d << " -"; |
|
else |
|
d << " n/a"; |
|
} |
|
} |
|
|
|
/* If we wanted only extension strings, exit now */ |
|
if(args.isSet("extension-strings")) return 0; |
|
|
|
Debug{} << "Queue families:"; |
|
for(UnsignedInt i = 0; i != device.queueFamilyCount(); ++i) { |
|
Debug{} << " " << i << Debug::nospace << ":" << device.queueFamilyFlags(i); |
|
Debug{} << " " << device.queueFamilySize(i) << "queues"; |
|
} |
|
|
|
Debug{} << "Memory heaps:"; |
|
for(UnsignedInt i = 0; i != device.memoryHeapCount(); ++i) { |
|
Debug{} << " " << i << Debug::nospace << ":" << device.memoryHeapFlags(i); |
|
Debug{} << " size:" << device.memoryHeapSize(i)/1024/1024 << "MB"; |
|
} |
|
|
|
Debug{} << "Memory types:"; |
|
for(UnsignedInt i = 0; i != device.memoryCount(); ++i) { |
|
Debug{} << " " << i << Debug::nospace << ":" << device.memoryFlags(i); |
|
Debug{} << " heap index:" << device.memoryHeapIndex(i); |
|
} |
|
}
|
|
|