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.

328 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
6 years ago
@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);
}
}