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.
457 lines
19 KiB
457 lines
19 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022 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/Cpu.h> |
|
#include <Corrade/Containers/StringIterable.h> |
|
#include <Corrade/Utility/Arguments.h> |
|
|
|
#include "Magnum/Vk/DeviceFeatures.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 `MAGNUM_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. |
|
|
|
@section magnum-vk-info-usage Usage |
|
|
|
@code{.sh} |
|
magnum-vk-info [--magnum-...] [-h|--help] [--extension-strings] |
|
[--all-extensions] [--features] |
|
@endcode |
|
|
|
Arguments: |
|
|
|
- `-h`, `--help` --- display this help message and exit |
|
- `--extension-strings` --- list all extension strings provided by the driver |
|
- `--all-extensions` --- display extensions also for fully supported versions |
|
- `--features` -- display also features supported by the device |
|
- `--magnum-...` --- engine-specific options (see |
|
@ref Vk-Instance-command-line for details) |
|
|
|
@section magnum-vk-info-example Example output |
|
|
|
@code{.shell-session} |
|
|
|
+---------------------------------------------------------+ |
|
| Information about Magnum engine Vulkan capabilities | |
|
+---------------------------------------------------------+ |
|
|
|
Compilation flags: |
|
CORRADE_BUILD_DEPRECATED |
|
CORRADE_BUILD_MULTITHREADED |
|
CORRADE_TARGET_UNIX |
|
CORRADE_TARGET_X86 |
|
CORRADE_TARGET_GCC |
|
CORRADE_TARGET_LIBSTDCXX |
|
MAGNUM_BUILD_DEPRECATED |
|
Compiled CPU features: |
|
Sse2|Sse3|Ssse3|Sse41|Sse42 |
|
Detected CPU features: |
|
Sse2|Sse3|Ssse3|Sse41|Sse42|Avx|Avx2|Popcnt|Lzcnt|Bmi1|AvxF16c|AvxFma |
|
|
|
Reported instance version: Vulkan 1.2.203 |
|
Reported instance layers: |
|
… |
|
VK_LAYER_KHRONOS_validation (r1, written against Vulkan 1.2.203) |
|
Khronos Validation Layer |
|
Vendor instance extension support: |
|
VK_EXT_debug_report REV.9 |
|
VK_EXT_debug_utils REV.1 |
|
VK_EXT_validation_features REV.2 |
|
|
|
Instance version: Vulkan 1.2.203 |
|
Found 2 devices: |
|
Intel(R) HD Graphics 630 (KBL GT2), Vulkan 1.2.195 |
|
Vk::DeviceType::IntegratedGpu, driver 21.3.5 |
|
llvmpipe (LLVM 13.0.0, 256 bits), Vulkan 1.2.195 |
|
Vk::DeviceType::Cpu, driver 0.0.1 |
|
|
|
Picked device Intel(R) HD Graphics 630 (KBL GT2) |
|
|
|
Reported version: Vulkan 1.2.195 |
|
Driver: Intel open-source Mesa driver (Vk::DeviceDriver::IntelOpenSourceMesa) |
|
Driver info: Mesa 21.3.5 (version 21.3.5) |
|
Vendor extension support: |
|
VK_EXT_debug_marker REV.4 |
|
VK_EXT_extended_dynamic_state REV.1 |
|
VK_EXT_image_robustness REV.1 |
|
VK_EXT_index_type_uint8 REV.1 |
|
VK_EXT_robustness2 REV.1 |
|
VK_EXT_texture_compression_astc_hdr - |
|
VK_EXT_vertex_attribute_divisor REV.3 |
|
VK_IMG_format_pvrtc - |
|
VK_KHR_acceleration_structure - |
|
… |
|
@endcode |
|
|
|
*/ |
|
|
|
} |
|
|
|
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") |
|
.addBooleanOption("features").setHelp("features", "display also features supported by the device") |
|
.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_IOS_SIMULATOR |
|
Debug{} << " CORRADE_TARGET_IOS_SIMULATOR"; |
|
#endif |
|
#ifdef CORRADE_TARGET_WINDOWS |
|
Debug{} << " CORRADE_TARGET_WINDOWS"; |
|
#endif |
|
#ifdef CORRADE_TARGET_WINDOWS_RT |
|
Debug{} << " CORRADE_TARGET_WINDOWS_RT"; |
|
#endif |
|
/* CORRADE_TARGET_EMSCRIPTEN omitted */ |
|
#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 |
|
/* CORRADE_TARGET_WASM omitted */ |
|
#ifdef CORRADE_TARGET_32BIT |
|
Debug{} << " CORRADE_TARGET_32BIT"; |
|
#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_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{} << "Compiled CPU features:"; |
|
Debug{} << " " << Debug::packed << Cpu::compiledFeatures(); |
|
#ifdef CORRADE_BUILD_CPU_RUNTIME_DISPATCH |
|
Debug{} << "Detected CPU features:"; |
|
Debug{} << " " << Debug::packed << Cpu::runtimeFeatures(); |
|
#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.isEmpty()) 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.isEmpty()) 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.isEmpty()) 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; |
|
|
|
if(args.isSet("features")) { |
|
Debug{} << "Feature support:"; |
|
#ifndef DOXYGEN_GENERATING_OUTPUT /* It gets really confused */ |
|
const Vk::DeviceFeatures features = device.features(); |
|
#define _c(value, field) \ |
|
{ \ |
|
Debug d; \ |
|
d << " " << #value << sixtyfourSpaces.prefix(63 - sizeof(#value)); \ |
|
if(features & Vk::DeviceFeature::value) \ |
|
d << "SUPPORTED"; \ |
|
else \ |
|
d << " - "; \ |
|
} |
|
#define _cver(value, field, suffix, version) \ |
|
{ \ |
|
Debug d; \ |
|
d << " " << #value << sixtyfourSpaces.prefix(63 - sizeof(#value)); \ |
|
if(features & Vk::DeviceFeature::value) \ |
|
d << "SUPPORTED"; \ |
|
else if(device.isVersionSupported(Vk::Version::version)) \ |
|
d << " - "; \ |
|
else \ |
|
d << " n/a "; \ |
|
} |
|
#define _cext(value, field, suffix, extension) \ |
|
{ \ |
|
Debug d; \ |
|
d << " " << #value << sixtyfourSpaces.prefix(63 - sizeof(#value)); \ |
|
if(features & Vk::DeviceFeature::value) \ |
|
d << "SUPPORTED"; \ |
|
else if(device.isVersionSupported(Vk::Extensions::extension::coreVersion()) || extensionProperties.isSupported<Vk::Extensions::extension>()) \ |
|
d << " - "; \ |
|
else \ |
|
d << " n/a "; \ |
|
} |
|
#include "Magnum/Vk/Implementation/deviceFeatureMapping.hpp" |
|
#undef _c |
|
#undef _cver |
|
#undef _cext |
|
#endif |
|
} |
|
|
|
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); |
|
} |
|
}
|
|
|