From e9130dc1ff76d876e524b0f05c67716fd1609ef5 Mon Sep 17 00:00:00 2001
From: Laszlo Agocs <laszlo.agocs@qt.io>
Date: Thu, 3 Aug 2017 11:24:52 +0200
Subject: [PATCH] qtdiag: Add basic Vulkan info

Task-number: QTBUG-62282
Change-Id: Icf7aa9b6f5f4f21da2dacb99c9f4b8f6b9b9eca7
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
---
 src/qtdiag/main.cpp   |  4 ++++
 src/qtdiag/qtdiag.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++
 src/qtdiag/qtdiag.h   |  3 ++-
 3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/src/qtdiag/main.cpp b/src/qtdiag/main.cpp
index 14eae6be4..2f5e2e9ee 100644
--- a/src/qtdiag/main.cpp
+++ b/src/qtdiag/main.cpp
@@ -49,10 +49,12 @@ int main(int argc, char **argv)
     const QCommandLineOption noGlOption(QStringLiteral("no-gl"), QStringLiteral("Do not output GL information"));
     const QCommandLineOption glExtensionOption(QStringLiteral("gl-extensions"), QStringLiteral("List GL extensions"));
     const QCommandLineOption fontOption(QStringLiteral("fonts"), QStringLiteral("Output list of fonts"));
+    const QCommandLineOption noVkOption(QStringLiteral("no-vulkan"), QStringLiteral("Do not output Vulkan information"));
     commandLineParser.setApplicationDescription(QStringLiteral("Prints diagnostic output about the Qt library."));
     commandLineParser.addOption(noGlOption);
     commandLineParser.addOption(glExtensionOption);
     commandLineParser.addOption(fontOption);
+    commandLineParser.addOption(noVkOption);
     commandLineParser.addHelpOption();
     commandLineParser.process(app);
     unsigned flags = commandLineParser.isSet(noGlOption) ? 0u : unsigned(QtDiagGl);
@@ -60,6 +62,8 @@ int main(int argc, char **argv)
         flags |= QtDiagGlExtensions;
     if (commandLineParser.isSet(fontOption))
         flags |= QtDiagFonts;
+    if (!commandLineParser.isSet(noVkOption))
+        flags |= QtDiagVk;
 
     std::wcout << qtDiag(flags).toStdWString();
     return 0;
diff --git a/src/qtdiag/qtdiag.cpp b/src/qtdiag/qtdiag.cpp
index 27db9de03..0d351b256 100644
--- a/src/qtdiag/qtdiag.cpp
+++ b/src/qtdiag/qtdiag.cpp
@@ -39,6 +39,10 @@
 #  include <QtGui/QOpenGLFunctions>
 #  include <QtGui/QOpenGLVersionProfile>
 #endif // QT_NO_OPENGL
+#if QT_CONFIG(vulkan)
+#  include <QtGui/QVulkanInstance>
+#  include <QtGui/QVulkanWindow>
+#endif // vulkan
 #include <QtGui/QWindow>
 #include <QtGui/QTouchDevice>
 
@@ -59,6 +63,7 @@
 #include <QtCore/QDir>
 #include <QtCore/QFileSelector>
 #include <QtCore/QDebug>
+#include <QtCore/QVersionNumber>
 
 #include <private/qsimd_p.h>
 #include <private/qguiapplication_p.h>
@@ -215,6 +220,44 @@ void dumpGlInfo(QTextStream &str, bool listExtensions)
 
 #endif // !QT_NO_OPENGL
 
+#if QT_CONFIG(vulkan)
+QVersionNumber vulkanVersion(uint32_t v)
+{
+    return QVersionNumber(VK_VERSION_MAJOR(v), VK_VERSION_MINOR(v), VK_VERSION_PATCH(v));
+}
+
+void dumpVkInfo(QTextStream &str)
+{
+    QVulkanInstance inst;
+    if (inst.create()) {
+        str << "Vulkan instance available\n";
+        str << "Supported instance extensions:\n";
+        for (const QVulkanExtension &ext : inst.supportedExtensions())
+            str << "  " << ext.name << ", version " << ext.version << "\n";
+        str << "Supported layers:\n";
+        for (const QVulkanLayer &layer : inst.supportedLayers())
+            str << "  " << layer.name << ", version " << layer.version
+                << ", spec version " << layer.specVersion.toString()
+                << ", " << layer.description << "\n";
+        // Show at least the available physical devices. Anything additional
+        // needs lots of initialization, or, if done through QVulkanWindow, an
+        // exposed window. None of these are very tempting right now.
+        str << "Available physical devices:\n";
+        QVulkanWindow window;
+        window.setVulkanInstance(&inst);
+        for (const VkPhysicalDeviceProperties &props : window.availablePhysicalDevices()) {
+            str << "  API version " << vulkanVersion(props.apiVersion).toString()
+                << hex << ", vendor 0x" << props.vendorID
+                << ", device 0x" << props.deviceID << ", " << props.deviceName
+                << dec << ", type " << props.deviceType
+                << ", driver version " << vulkanVersion(props.driverVersion).toString();
+        }
+    } else {
+        str << "Unable to create a Vulkan instance, error code is" << inst.errorCode() << "\n";
+    }
+}
+#endif // vulkan
+
 #define DUMP_CAPABILITY(str, integration, capability) \
     if (platformIntegration->hasCapability(QPlatformIntegration::capability)) \
         str << ' ' << #capability;
@@ -627,6 +670,13 @@ QString qtDiag(unsigned flags)
     Q_UNUSED(flags)
 #endif // !QT_NO_OPENGL
 
+#if QT_CONFIG(vulkan)
+    if (flags & QtDiagVk) {
+        dumpVkInfo(str);
+        str << "\n\n";
+    }
+#endif // vulkan
+
     // On Windows, this will provide addition GPU info similar to the output of dxdiag.
     if (const QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) {
         const QVariant gpuInfoV = ni->property("gpu");
diff --git a/src/qtdiag/qtdiag.h b/src/qtdiag/qtdiag.h
index b073297ef..359840647 100644
--- a/src/qtdiag/qtdiag.h
+++ b/src/qtdiag/qtdiag.h
@@ -36,7 +36,8 @@ QT_BEGIN_NAMESPACE
 enum QtDiagFlags {
     QtDiagGl = 0x1,
     QtDiagGlExtensions = 0x2,
-    QtDiagFonts = 0x4
+    QtDiagFonts = 0x4,
+    QtDiagVk = 0x8
 };
 
 QString qtDiag(unsigned flags = 0);
-- 
GitLab