diff --git a/README.md b/README.md index cf5fcd8..8970959 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Vulkan Hardware Capability Viewer -![Vulkan Logo](./images/vulkanlogo.png) + -Client application to display hardware implementation details for GPUs supporting the new [Vulkan(tm)](https://www.khronos.org/vulkan/) API by Khronos. +Client application to display hardware implementation details for GPUs supporting the [Vulkan](https://www.khronos.org/vulkan/) API by Khronos. The hardware reports can be submitted to a public [online database](http://vulkan.gpuinfo.org/) that allows comparing different devices, browsing available features, extensions, formats, etc. @@ -11,20 +11,17 @@ The hardware reports can be submitted to a public [online database](http://vulka # Supported platforms -**A Vulkan compatible driver (or on Android image) is required** +**A Vulkan compatible device is required** - Windows (x64) - Linux (x64) - Android (Including Android TV) - Mac OS X -# API version -Due to the explicit nature of Vulkan, the API version of the Vulkan driver (or Android image) must fit the API level against which the application was build. - # Building ![Build Project](https://github.com/SaschaWillems/VulkanCapsViewer/workflows/Build%20Project/badge.svg) -The repository includes a project file for the [Qt Creator IDE](https://www.qt.io/ide/) that has been tested to work with Windows, Linux and Android. This is the preferred (and easiest) way of building the application if you want to build it yourself. +The repository includes a project file for the [Qt Creator IDE](https://www.qt.io/ide/) that has been tested to work with Windows, Linux and Android. This is the preferred (and easiest) way of building the application if you want to build it yourself. Using the [Qt Visual Studio Tools](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019), it's also possible to use a current Visual Studio version. Alternatively, you can simply run `qmake` followed by `make` in the source directory. # Releases diff --git a/Resources/vulkan32.png b/Resources/vulkan32.png index 5dc85e8..a076edb 100644 Binary files a/Resources/vulkan32.png and b/Resources/vulkan32.png differ diff --git a/Resources/vulkan48.png b/Resources/vulkan48.png index fb7d7d4..05738fb 100644 Binary files a/Resources/vulkan48.png and b/Resources/vulkan48.png differ diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 362b325..a6dfbec 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + > diff --git a/images/vulkanlogo.png b/images/vulkanlogo.png index c31b340..09bbb86 100644 Binary files a/images/vulkanlogo.png and b/images/vulkanlogo.png differ diff --git a/libs/vulkan/vulkan-1.lib b/libs/vulkan/vulkan-1.lib index 755930e..a3b0bbd 100644 Binary files a/libs/vulkan/vulkan-1.lib and b/libs/vulkan/vulkan-1.lib differ diff --git a/submitDialog.cpp b/submitDialog.cpp index 6e438d7..8e0b3ee 100644 --- a/submitDialog.cpp +++ b/submitDialog.cpp @@ -1,10 +1,10 @@ /* * -* OpenGL hardware capability viewer and database +* Vulkan hardware capability viewer * * Submit report dialog * -* Copyright (C) 2011-2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,14 +30,14 @@ #include #include -submitDialog::submitDialog(QString submitter) +submitDialog::submitDialog(QString submitter, QString caption) { QFormLayout *formLayout = new QFormLayout; // QDialogBox doesn't appear modal on Android which makes it hard to see #ifdef ANDROID QLabel *labelCaption = new QLabel(); - labelCaption->setText("Submit report to database"); + labelCaption->setText(caption); formLayout->addRow(labelCaption); setStyleSheet("QDialog{ border: 2px solid black; border-style: solid; border-radius: 4px; }"); #endif @@ -63,7 +63,7 @@ submitDialog::submitDialog(QString submitter) formLayout->addWidget(buttonBox); setLayout(formLayout); - setWindowTitle("Submit report"); + setWindowTitle(caption); } diff --git a/submitDialog.h b/submitDialog.h index 304b019..3abf9bb 100644 --- a/submitDialog.h +++ b/submitDialog.h @@ -4,7 +4,7 @@ * * Submit report dialog * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,7 +34,7 @@ class submitDialog : public QDialog public: std::string submitter; std::string comment; - submitDialog(QString submitter); + submitDialog(QString submitter, QString caption = "Submit new report"); ~submitDialog(); std::string getSubmitter(); std::string getComment(); diff --git a/vulkanCapsViewer.vcxproj b/vulkanCapsViewer.vcxproj index cd1e278..4751ba1 100644 --- a/vulkanCapsViewer.vcxproj +++ b/vulkanCapsViewer.vcxproj @@ -1,220 +1,292 @@  - + - - Debug - x64 - Release x64 + + Debug + x64 + - {B12702AD-ABFB-343A-A199-8E24837244A3} - Qt4VSv1.0 + {560F3AD5-17F2-395D-B675-082A25172590} + vulkanCapsViewer + QtVS_v303 + 10.0 + 10.0.19041.0 + $(MSBuildProjectDirectory)\QtMsBuild - - Application - v142 - Unicode - + v142 + Win32\Release\ + false + NotSet Application + release\ + vulkanCapsViewer + + v142 - Unicode + Win32\Release\ + false + NotSet + Application + debug\ + vulkanCapsViewer - + + + + + + - - - - + - - <_ProjectFileVersion>12.0.30501.0 - + + + - $(SolutionDir)$(Platform)\$(Configuration)\ + Win32\Release\ + debug\ + vulkanCapsViewer + true - $(SolutionDir)$(Platform)\$(Configuration)\ + Win32\Release\ + release\ + vulkanCapsViewer + true + false - + + 5.13.2 + core;network;gui;widgets + + + 5.13.2 + core;network;gui;widgets + + + + + - VK_USE_PLATFORM_WIN32_KHR;WIN32;WIN64;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;QT_NO_SIGNALS_SLOTS_KEYWORDS;VK_PROTOTYPES;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;.\Vulkan-Headers\include;%(AdditionalIncludeDirectories) - Disabled - ProgramDatabase - MultiThreadedDebugDLL + GeneratedFiles\$(ConfigurationName);GeneratedFiles;.;GeneratedFiles\Release;Vulkan-Headers\include;/Vulkan-Headers/include;GeneratedFiles\release;1.2.154.0/include;%(AdditionalIncludeDirectories) + -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) + release\ + false + None + 4577;4467;%(DisableSpecificWarnings) + Sync + release\ + MaxSpeed + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_DLL;VK_ENABLE_BETA_EXTENSIONS;WIN64;VK_USE_PLATFORM_WIN32_KHR;QT_NO_DEBUG;%(PreprocessorDefinitions) + false + + + MultiThreadedDLL + true true Level3 - true - stdcpp14 + true + .\libs\vulkan\vulkan-1.lib;Advapi32.lib;shell32.lib;%(AdditionalDependencies) + C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories) + "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) + true + false + true + false + $(OutDir)\vulkanCapsViewer.exe + true Windows - $(OutDir)\$(ProjectName).exe - $(VULKAN_SDK)\Lib;$(QTDIR)\lib;libs\vulkan;%(AdditionalLibraryDirectories) - true - vulkan-1.lib;qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Networkd.lib;Qt5Widgetsd.lib;libs\vulkan\vulkan-1.lib;%(AdditionalDependencies) + true + + Unsigned + None + 0 + + + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;NDEBUG;QT_DLL;QT_NETWORK_LIB;QT_WIDGETS_LIB;VK_ENABLE_BETA_EXTENSIONS;WIN64;VK_USE_PLATFORM_WIN32_KHR;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + + + msvc + ./GeneratedFiles/$(Configuration)/moc_predefs.h + Moc'ing %(Identity)... + output + GeneratedFiles\$(Configuration) + moc_%(Filename).cpp + + + vulkancapsviewer + default + Rcc'ing %(Identity)... + GeneratedFiles + qrc_%(Filename).cpp + + + Uic'ing %(Identity)... + GeneratedFiles + ui_%(Filename).h + - + - VK_USE_PLATFORM_WIN32_KHR;WIN32;WIN64;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_WIDGETS_LIB;VK_PROTOTYPES;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtNetwork;$(QTDIR)\include\QtWidgets;.\Vulkan-Headers\include;%(AdditionalIncludeDirectories) - - MultiThreadedDLL + GeneratedFiles\$(ConfigurationName);GeneratedFiles;.;GeneratedFiles\Release;Vulkan-Headers\include;/Vulkan-Headers/include;GeneratedFiles\debug;1.2.154.0/include;%(AdditionalIncludeDirectories) + -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) + debug\ + false + ProgramDatabase + 4577;4467;%(DisableSpecificWarnings) + Sync + debug\ + Disabled + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;VK_ENABLE_BETA_EXTENSIONS;WIN64;VK_USE_PLATFORM_WIN32_KHR;%(PreprocessorDefinitions) + false + MultiThreadedDebugDLL + true true Level3 - true - stdcpp14 + true + .\libs\vulkan\vulkan-1.lib;Advapi32.lib;shell32.lib;%(AdditionalDependencies) + C:\openssl\lib;C:\Utils\my_sql\mysql-5.7.25-winx64\lib;C:\Utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories) + "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) + true + true + true + $(OutDir)\vulkanCapsViewer.exe + true Windows - $(OutDir)\$(ProjectName).exe - $(VULKAN_SDK)\Lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories) - false - vulkan-1.lib;qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Network.lib;Qt5Widgets.lib;libs\vulkan\vulkan-1.lib;%(AdditionalDependencies) + true + + Unsigned + None + 0 + + + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_NETWORK_LIB;QT_WIDGETS_LIB;VK_ENABLE_BETA_EXTENSIONS;WIN64;VK_USE_PLATFORM_WIN32_KHR;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + + + msvc + ./GeneratedFiles/$(Configuration)/moc_predefs.h + Moc'ing %(Identity)... + output + GeneratedFiles\$(Configuration) + moc_%(Filename).cpp + + + vulkancapsviewer + default + Rcc'ing %(Identity)... + GeneratedFiles + qrc_%(Filename).cpp + + + Uic'ing %(Identity)... + GeneratedFiles + ui_%(Filename).h + - - true - - - true - - - true - - - true - - - - - - - - - true - - - true - - - true - - - true - + + - - - - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing vulkancapsviewer.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing vulkancapsviewer.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" - - - - - $(QTDIR)\bin\uic.exe;%(AdditionalInputs) - Uic%27ing %(Identity)... - .\GeneratedFiles\ui_%(Filename).h;%(Outputs) - "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" - $(QTDIR)\bin\uic.exe;%(AdditionalInputs) - Uic%27ing %(Identity)... - .\GeneratedFiles\ui_%(Filename).h;%(Outputs) - "$(QTDIR)\bin\uic.exe" -o ".\GeneratedFiles\ui_%(Filename).h" "%(FullPath)" - - - - + + - - - - - - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing submitDialog.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing submitDialog.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" - + + + + - + - - - - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing vulkandatabase.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing vulkandatabase.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" + + + + + + + + + + + Document + true + $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) + cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >GeneratedFiles\debug\moc_predefs.h + Generate moc_predefs.h + GeneratedFiles\debug\moc_predefs.h;%(Outputs) - - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing settingsDialog.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" - $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing settingsDialog.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DVK_USE_PLATFORM_WIN32_KHR -DWIN32 -DWIN64 -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_WIDGETS_LIB -DVK_PROTOTYPES -D%(PreprocessorDefinitions) "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtWidgets" "-I.\Vulkan-Headers\include" + + Document + $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) + cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >GeneratedFiles\release\moc_predefs.h + Generate moc_predefs.h + GeneratedFiles\release\moc_predefs.h;%(Outputs) + true - - %(FullPath);%(AdditionalInputs) - Rcc%27ing %(Identity)... - .\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) - "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp - %(FullPath);%(AdditionalInputs) - Rcc%27ing %(Identity)... - .\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) - "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - + \ No newline at end of file diff --git a/vulkanCapsViewer.vcxproj.filters b/vulkanCapsViewer.vcxproj.filters index c071ad4..e5e7565 100644 --- a/vulkanCapsViewer.vcxproj.filters +++ b/vulkanCapsViewer.vcxproj.filters @@ -1,95 +1,90 @@  - + - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;cxx;c;def - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h + + {99349809-55BA-4b9d-BF79-8FDBB0286EB3} + ui + false {99349809-55BA-4b9d-BF79-8FDBB0286EB3} ui + false + + + {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11} + cpp;c;cxx;moc;h;def;odl;idl;res; + + + {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11} + cpp;c;cxx;moc;h;def;odl;idl;res; + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} qrc;* false - - {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11} - moc;h;cpp - False + + {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} + qrc;* + false + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - - {760a2d73-3f6e-4039-9618-7de4faa56424} - cpp;moc - False + + {B83CAF91-C7BF-462F-B76C-EA11631F866C} + * + false - - {2eff770d-359a-4717-b7d0-3e4bae13e6f3} - cpp;moc - False + + {B83CAF91-C7BF-462F-B76C-EA11631F866C} + * + false - + Source Files - + Source Files - - Generated Files\Debug - - - Generated Files\Release - - - Generated Files - - - Generated Files\Debug - - - Generated Files\Release - Source Files Source Files - - Source Files - - - Generated Files\Debug - - - Generated Files\Release - - - Generated Files\Debug - - - Generated Files\Release - Source Files Source Files + + Source Files + Source Files - + Source Files - + Source Files @@ -97,63 +92,142 @@ - - Header Files - - - Form Files - - - Resource Files - - - Header Files - - + Header Files - - + + Header Files - - - - - Generated Files Header Files - + Header Files - - + + Header Files - + Header Files - + Header Files Header Files - + Header Files - + Header Files - + Header Files - - + + + Header Files + + Header Files - + Header Files + + + Generated Files + + + Generated Files + + + + + + + + + + + + + + + Form Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Distribution Files + + + Distribution Files + + + Distribution Files + + + Distribution Files + + + Distribution Files + + + Distribution Files + + + Distribution Files + + diff --git a/vulkanDeviceInfo.cpp b/vulkanDeviceInfo.cpp index 075f715..a17041a 100644 --- a/vulkanDeviceInfo.cpp +++ b/vulkanDeviceInfo.cpp @@ -4,7 +4,7 @@ * * Device information class * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,6 +34,13 @@ bool VulkanDeviceInfo::vulkan_1_1() return ((major > 1) || ((major == 1) && (minor >= 1))); } +bool VulkanDeviceInfo::vulkan_1_2() +{ + uint32_t major = VK_VERSION_MAJOR(props.apiVersion); + uint32_t minor = VK_VERSION_MINOR(props.apiVersion); + return ((major > 1) || ((major == 1) && (minor >= 2))); +} + void VulkanDeviceInfo::readExtensions() { assert(device != NULL); @@ -188,6 +195,15 @@ std::string VulkanDeviceInfo::getDriverVersion() } } +QJsonArray UUIDToJson(uint8_t* UUID) +{ + QJsonArray jsonArray; + for (uint32_t i = 0; i < VK_UUID_SIZE; i++) { + jsonArray.append(UUID[i]); + } + return jsonArray; +} + void VulkanDeviceInfo::readPhysicalProperties() { assert(device != NULL); @@ -221,9 +237,9 @@ void VulkanDeviceInfo::readPhysicalProperties() // VK 1.1 core if (vulkan_1_1()) { VkPhysicalDeviceProperties2KHR deviceProps2{}; + deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; VkPhysicalDeviceSubgroupProperties extProps{}; extProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; - deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; deviceProps2.pNext = &extProps; pfnGetPhysicalDeviceProperties2KHR(device, &deviceProps2); hasSubgroupProperties = true; @@ -245,6 +261,100 @@ void VulkanDeviceInfo::readPhysicalProperties() properties2.push_back(Property2("maxMemoryAllocationSize", QVariant::fromValue(extProps.maxMemoryAllocationSize), extName)); } } + + // VK 1.2 core + if (vulkan_1_2()) { + // Vulkan 1.2 introduced dedicated structures for properties promoted to core in 1.1 and 1.2 + // Fetching the core 1.1 properties also requires a Vulkan 1.2 (or later) implementation + + VkPhysicalDeviceProperties2KHR deviceProps2{}; + deviceProps2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; + + // Core 1.1 + VkPhysicalDeviceVulkan11Properties coreProps11{}; + coreProps11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; + deviceProps2.pNext = &coreProps11; + pfnGetPhysicalDeviceProperties2KHR(device, &deviceProps2); + + core11Properties.clear(); + core11Properties["deviceUUID"] = UUIDToJson(coreProps11.deviceUUID); + core11Properties["driverUUID"] = UUIDToJson(coreProps11.driverUUID); + core11Properties["deviceLUID"] = UUIDToJson(coreProps11.deviceLUID); + core11Properties["deviceNodeMask"] = coreProps11.deviceNodeMask; + core11Properties["deviceLUIDValid"] = coreProps11.deviceLUIDValid; + core11Properties["subgroupSize"] = coreProps11.subgroupSize; + core11Properties["subgroupSupportedStages"] = coreProps11.subgroupSupportedStages; + core11Properties["subgroupSupportedOperations"] = coreProps11.subgroupSupportedOperations; + core11Properties["subgroupQuadOperationsInAllStages"] = coreProps11.subgroupQuadOperationsInAllStages; + core11Properties["pointClippingBehavior"] = coreProps11.pointClippingBehavior; + core11Properties["maxMultiviewViewCount"] = coreProps11.maxMultiviewViewCount; + core11Properties["maxMultiviewInstanceIndex"] = coreProps11.maxMultiviewInstanceIndex; + core11Properties["protectedNoFault"] = coreProps11.protectedNoFault; + core11Properties["maxPerSetDescriptors"] = coreProps11.maxPerSetDescriptors; + core11Properties["maxMemoryAllocationSize"] = QVariant::fromValue(coreProps11.maxMemoryAllocationSize); + + + // Core 1.2 + VkPhysicalDeviceVulkan12Properties coreProps12{}; + coreProps12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES; + deviceProps2.pNext = &coreProps12; + pfnGetPhysicalDeviceProperties2KHR(device, &deviceProps2); + + core12Properties.clear(); + core12Properties["driverID"] = coreProps12.driverID; + core12Properties["driverName"] = QString(coreProps12.driverName); + core12Properties["driverInfo"] = QString(coreProps12.driverInfo); + core12Properties["conformanceVersion"] = QString::fromStdString(vulkanResources::conformanceVersionKHRString(coreProps12.conformanceVersion)); + core12Properties["denormBehaviorIndependence"] = coreProps12.denormBehaviorIndependence; + core12Properties["roundingModeIndependence"] = coreProps12.roundingModeIndependence; + core12Properties["shaderSignedZeroInfNanPreserveFloat16"] = coreProps12.shaderSignedZeroInfNanPreserveFloat16; + core12Properties["shaderSignedZeroInfNanPreserveFloat32"] = coreProps12.shaderSignedZeroInfNanPreserveFloat32; + core12Properties["shaderSignedZeroInfNanPreserveFloat64"] = coreProps12.shaderSignedZeroInfNanPreserveFloat64; + core12Properties["shaderDenormPreserveFloat16"] = coreProps12.shaderDenormPreserveFloat16; + core12Properties["shaderDenormPreserveFloat32"] = coreProps12.shaderDenormPreserveFloat32; + core12Properties["shaderDenormPreserveFloat64"] = coreProps12.shaderDenormPreserveFloat64; + core12Properties["shaderDenormFlushToZeroFloat16"] = coreProps12.shaderDenormFlushToZeroFloat16; + core12Properties["shaderDenormFlushToZeroFloat32"] = coreProps12.shaderDenormFlushToZeroFloat32; + core12Properties["shaderDenormFlushToZeroFloat64"] = coreProps12.shaderDenormFlushToZeroFloat64; + core12Properties["shaderRoundingModeRTEFloat16"] = coreProps12.shaderRoundingModeRTEFloat16; + core12Properties["shaderRoundingModeRTEFloat32"] = coreProps12.shaderRoundingModeRTEFloat32; + core12Properties["shaderRoundingModeRTEFloat64"] = coreProps12.shaderRoundingModeRTEFloat64; + core12Properties["shaderRoundingModeRTZFloat16"] = coreProps12.shaderRoundingModeRTZFloat16; + core12Properties["shaderRoundingModeRTZFloat32"] = coreProps12.shaderRoundingModeRTZFloat32; + core12Properties["shaderRoundingModeRTZFloat64"] = coreProps12.shaderRoundingModeRTZFloat64; + core12Properties["maxUpdateAfterBindDescriptorsInAllPools"] = coreProps12.maxUpdateAfterBindDescriptorsInAllPools; + core12Properties["shaderUniformBufferArrayNonUniformIndexingNative"] = coreProps12.shaderUniformBufferArrayNonUniformIndexingNative; + core12Properties["shaderSampledImageArrayNonUniformIndexingNative"] = coreProps12.shaderSampledImageArrayNonUniformIndexingNative; + core12Properties["shaderStorageBufferArrayNonUniformIndexingNative"] = coreProps12.shaderStorageBufferArrayNonUniformIndexingNative; + core12Properties["shaderStorageImageArrayNonUniformIndexingNative"] = coreProps12.shaderStorageImageArrayNonUniformIndexingNative; + core12Properties["shaderInputAttachmentArrayNonUniformIndexingNative"] = coreProps12.shaderInputAttachmentArrayNonUniformIndexingNative; + core12Properties["robustBufferAccessUpdateAfterBind"] = coreProps12.robustBufferAccessUpdateAfterBind; + core12Properties["quadDivergentImplicitLod"] = coreProps12.quadDivergentImplicitLod; + core12Properties["maxPerStageDescriptorUpdateAfterBindSamplers"] = coreProps12.maxPerStageDescriptorUpdateAfterBindSamplers; + core12Properties["maxPerStageDescriptorUpdateAfterBindUniformBuffers"] = coreProps12.maxPerStageDescriptorUpdateAfterBindUniformBuffers; + core12Properties["maxPerStageDescriptorUpdateAfterBindStorageBuffers"] = coreProps12.maxPerStageDescriptorUpdateAfterBindStorageBuffers; + core12Properties["maxPerStageDescriptorUpdateAfterBindSampledImages"] = coreProps12.maxPerStageDescriptorUpdateAfterBindSampledImages; + core12Properties["maxPerStageDescriptorUpdateAfterBindStorageImages"] = coreProps12.maxPerStageDescriptorUpdateAfterBindStorageImages; + core12Properties["maxPerStageDescriptorUpdateAfterBindInputAttachments"] = coreProps12.maxPerStageDescriptorUpdateAfterBindInputAttachments; + core12Properties["maxPerStageUpdateAfterBindResources"] = coreProps12.maxPerStageUpdateAfterBindResources; + core12Properties["maxDescriptorSetUpdateAfterBindSamplers"] = coreProps12.maxDescriptorSetUpdateAfterBindSamplers; + core12Properties["maxDescriptorSetUpdateAfterBindUniformBuffers"] = coreProps12.maxDescriptorSetUpdateAfterBindUniformBuffers; + core12Properties["maxDescriptorSetUpdateAfterBindUniformBuffersDynamic"] = coreProps12.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic; + core12Properties["maxDescriptorSetUpdateAfterBindStorageBuffers"] = coreProps12.maxDescriptorSetUpdateAfterBindStorageBuffers; + core12Properties["maxDescriptorSetUpdateAfterBindStorageBuffersDynamic"] = coreProps12.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic; + core12Properties["maxDescriptorSetUpdateAfterBindSampledImages"] = coreProps12.maxDescriptorSetUpdateAfterBindSampledImages; + core12Properties["maxDescriptorSetUpdateAfterBindStorageImages"] = coreProps12.maxDescriptorSetUpdateAfterBindStorageImages; + core12Properties["maxDescriptorSetUpdateAfterBindInputAttachments"] = coreProps12.maxDescriptorSetUpdateAfterBindInputAttachments; + core12Properties["supportedDepthResolveModes"] = coreProps12.supportedDepthResolveModes; + core12Properties["supportedStencilResolveModes"] = coreProps12.supportedStencilResolveModes; + core12Properties["independentResolveNone"] = coreProps12.independentResolveNone; + core12Properties["independentResolve"] = coreProps12.independentResolve; + core12Properties["filterMinmaxSingleComponentFormats"] = coreProps12.filterMinmaxSingleComponentFormats; + core12Properties["filterMinmaxImageComponentMapping"] = coreProps12.filterMinmaxImageComponentMapping; + core12Properties["maxTimelineSemaphoreValueDifference"] = QVariant::fromValue(coreProps12.maxTimelineSemaphoreValueDifference); + core12Properties["framebufferIntegerColorSampleCounts"] = coreProps12.framebufferIntegerColorSampleCounts; + + } } } @@ -315,20 +425,105 @@ void VulkanDeviceInfo::readPhysicalFeatures() readExtendedFeatures(); - // VK 1.1 Core + // Vulkan 1.1 if (vulkan_1_1()) { + VkPhysicalDeviceFeatures2KHR deviceFeatures2{}; + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + // VK_KHR_shader_draw_parameters if (extensionSupported(VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME)) { - VkPhysicalDeviceFeatures2KHR deviceFeatures2{}; VkPhysicalDeviceShaderDrawParameterFeatures extFeatures{}; extFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; - deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; deviceFeatures2.pNext = &extFeatures; pfnGetPhysicalDeviceFeatures2KHR(device, &deviceFeatures2); features2.push_back(Feature2("shaderDrawParameters", extFeatures.shaderDrawParameters, VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME)); } } + // Vulkan 1.2 + if (vulkan_1_2()) { + // Vulkan 1.2 introduced dedicated structures for features promoted to core in 1.1 and 1.2 + // Fetching the core 1.1 features also requires a Vulkan 1.2 (or later) implementation + + VkPhysicalDeviceFeatures2KHR deviceFeatures2{}; + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + + // Core 1.1 + VkPhysicalDeviceVulkan11Features coreFeatures11{}; + coreFeatures11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + deviceFeatures2.pNext = &coreFeatures11; + pfnGetPhysicalDeviceFeatures2KHR(device, &deviceFeatures2); + + core11Features.clear(); + core11Features["storageBuffer16BitAccess"] = coreFeatures11.storageBuffer16BitAccess; + core11Features["uniformAndStorageBuffer16BitAccess"] = coreFeatures11.uniformAndStorageBuffer16BitAccess; + core11Features["storagePushConstant16"] = coreFeatures11.storagePushConstant16; + core11Features["storageInputOutput16"] = coreFeatures11.storageInputOutput16; + core11Features["multiview"] = coreFeatures11.multiview; + core11Features["multiviewGeometryShader"] = coreFeatures11.multiviewGeometryShader; + core11Features["multiviewTessellationShader"] = coreFeatures11.multiviewTessellationShader; + core11Features["variablePointersStorageBuffer"] = coreFeatures11.variablePointersStorageBuffer; + core11Features["variablePointers"] = coreFeatures11.variablePointers; + core11Features["protectedMemory"] = coreFeatures11.protectedMemory; + core11Features["samplerYcbcrConversion"] = coreFeatures11.samplerYcbcrConversion; + core11Features["shaderDrawParameters"] = coreFeatures11.shaderDrawParameters; + + // Core 1.2 + VkPhysicalDeviceVulkan12Features coreFeatures12{}; + coreFeatures12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + deviceFeatures2.pNext = &coreFeatures12; + pfnGetPhysicalDeviceFeatures2KHR(device, &deviceFeatures2); + + core12Features.clear(); + core12Features["samplerMirrorClampToEdge"] = coreFeatures12.samplerMirrorClampToEdge; + core12Features["drawIndirectCount"] = coreFeatures12.drawIndirectCount; + core12Features["storageBuffer8BitAccess"] = coreFeatures12.storageBuffer8BitAccess; + core12Features["uniformAndStorageBuffer8BitAccess"] = coreFeatures12.uniformAndStorageBuffer8BitAccess; + core12Features["storagePushConstant8"] = coreFeatures12.storagePushConstant8; + core12Features["shaderBufferInt64Atomics"] = coreFeatures12.shaderBufferInt64Atomics; + core12Features["shaderSharedInt64Atomics"] = coreFeatures12.shaderSharedInt64Atomics; + core12Features["shaderFloat16"] = coreFeatures12.shaderFloat16; + core12Features["shaderInt8"] = coreFeatures12.shaderInt8; + core12Features["descriptorIndexing"] = coreFeatures12.descriptorIndexing; + core12Features["shaderInputAttachmentArrayDynamicIndexing"] = coreFeatures12.shaderInputAttachmentArrayDynamicIndexing; + core12Features["shaderUniformTexelBufferArrayDynamicIndexing"] = coreFeatures12.shaderUniformTexelBufferArrayDynamicIndexing; + core12Features["shaderStorageTexelBufferArrayDynamicIndexing"] = coreFeatures12.shaderStorageTexelBufferArrayDynamicIndexing; + core12Features["shaderUniformBufferArrayNonUniformIndexing"] = coreFeatures12.shaderUniformBufferArrayNonUniformIndexing; + core12Features["shaderSampledImageArrayNonUniformIndexing"] = coreFeatures12.shaderSampledImageArrayNonUniformIndexing; + core12Features["shaderStorageBufferArrayNonUniformIndexing"] = coreFeatures12.shaderStorageBufferArrayNonUniformIndexing; + core12Features["shaderStorageImageArrayNonUniformIndexing"] = coreFeatures12.shaderStorageImageArrayNonUniformIndexing; + core12Features["shaderInputAttachmentArrayNonUniformIndexing"] = coreFeatures12.shaderInputAttachmentArrayNonUniformIndexing; + core12Features["shaderUniformTexelBufferArrayNonUniformIndexing"] = coreFeatures12.shaderUniformTexelBufferArrayNonUniformIndexing; + core12Features["shaderStorageTexelBufferArrayNonUniformIndexing"] = coreFeatures12.shaderStorageTexelBufferArrayNonUniformIndexing; + core12Features["descriptorBindingUniformBufferUpdateAfterBind"] = coreFeatures12.descriptorBindingUniformBufferUpdateAfterBind; + core12Features["descriptorBindingSampledImageUpdateAfterBind"] = coreFeatures12.descriptorBindingSampledImageUpdateAfterBind; + core12Features["descriptorBindingStorageImageUpdateAfterBind"] = coreFeatures12.descriptorBindingStorageImageUpdateAfterBind; + core12Features["descriptorBindingStorageBufferUpdateAfterBind"] = coreFeatures12.descriptorBindingStorageBufferUpdateAfterBind; + core12Features["descriptorBindingUniformTexelBufferUpdateAfterBind"] = coreFeatures12.descriptorBindingUniformTexelBufferUpdateAfterBind; + core12Features["descriptorBindingStorageTexelBufferUpdateAfterBind"] = coreFeatures12.descriptorBindingStorageTexelBufferUpdateAfterBind; + core12Features["descriptorBindingUpdateUnusedWhilePending"] = coreFeatures12.descriptorBindingUpdateUnusedWhilePending; + core12Features["descriptorBindingPartiallyBound"] = coreFeatures12.descriptorBindingPartiallyBound; + core12Features["descriptorBindingVariableDescriptorCount"] = coreFeatures12.descriptorBindingVariableDescriptorCount; + core12Features["runtimeDescriptorArray"] = coreFeatures12.runtimeDescriptorArray; + core12Features["samplerFilterMinmax"] = coreFeatures12.samplerFilterMinmax; + core12Features["scalarBlockLayout"] = coreFeatures12.scalarBlockLayout; + core12Features["imagelessFramebuffer"] = coreFeatures12.imagelessFramebuffer; + core12Features["uniformBufferStandardLayout"] = coreFeatures12.uniformBufferStandardLayout; + core12Features["shaderSubgroupExtendedTypes"] = coreFeatures12.shaderSubgroupExtendedTypes; + core12Features["separateDepthStencilLayouts"] = coreFeatures12.separateDepthStencilLayouts; + core12Features["hostQueryReset"] = coreFeatures12.hostQueryReset; + core12Features["timelineSemaphore"] = coreFeatures12.timelineSemaphore; + core12Features["bufferDeviceAddress"] = coreFeatures12.bufferDeviceAddress; + core12Features["bufferDeviceAddressCaptureReplay"] = coreFeatures12.bufferDeviceAddressCaptureReplay; + core12Features["bufferDeviceAddressMultiDevice"] = coreFeatures12.bufferDeviceAddressMultiDevice; + core12Features["vulkanMemoryModel"] = coreFeatures12.vulkanMemoryModel; + core12Features["vulkanMemoryModelDeviceScope"] = coreFeatures12.vulkanMemoryModelDeviceScope; + core12Features["vulkanMemoryModelAvailabilityVisibilityChains"] = coreFeatures12.vulkanMemoryModelAvailabilityVisibilityChains; + core12Features["shaderOutputViewportIndex"] = coreFeatures12.shaderOutputViewportIndex; + core12Features["shaderOutputLayer"] = coreFeatures12.shaderOutputLayer; + core12Features["subgroupBroadcastDynamicId"] = coreFeatures12.subgroupBroadcastDynamicId; + } + } } @@ -480,6 +675,7 @@ void VulkanDeviceInfo::readPlatformDetails() platformdetails["android.ProductManufacturer"] = getSystemProperty("ro.product.manufacturer"); platformdetails["android.BuildID"] = getSystemProperty("ro.build.id"); platformdetails["android.BuildVersionIncremental"] = getSystemProperty("ro.build.version.incremental"); + properties["displayName"] = QString::fromStdString(platformdetails["android.ProductManufacturer"] + " " + platformdetails["android.ProductModel"]); #endif } @@ -501,12 +697,40 @@ QJsonObject VulkanDeviceInfo::toJson(std::string submitter, std::string comment) jsonPipelineCache.append(jsonVal); } jsonProperties["pipelineCacheUUID"] = jsonPipelineCache; - root["properties"] = jsonProperties; + if (!core12Properties.empty()) { + root["propertiesCore12"] = QJsonObject::fromVariantMap(core12Properties); + } + // Device features + QJsonObject jsonFeatures; root["features"] = QJsonObject::fromVariantMap(features); + // Core 1.1 + if ((!core11Properties.empty()) || (!core11Features.empty())) { + QJsonObject jsonCore11; + if (!core11Properties.empty()) { + jsonCore11["properties"] = QJsonObject::fromVariantMap(core11Properties); + } + if (!core11Features.empty()) { + jsonCore11["features"] = QJsonObject::fromVariantMap(core11Features); + } + root["core11"] = jsonCore11; + } + + // Core 1.2 + if ((!core12Properties.empty()) || (!core12Features.empty())) { + QJsonObject jsonCore12; + if (!core12Properties.empty()) { + jsonCore12["properties"] = QJsonObject::fromVariantMap(core12Properties); + } + if (!core12Features.empty()) { + jsonCore12["features"] = QJsonObject::fromVariantMap(core12Features); + } + root["core12"] = jsonCore12; + } + // Extensions QJsonArray jsonExtensions; for (auto& ext : extensions) @@ -659,8 +883,6 @@ QJsonObject VulkanDeviceInfo::toJson(std::string submitter, std::string comment) jsonEnv["appversion"] = QString::fromStdString(appVersion); root["environment"] = jsonEnv; -#define EXTENDED_PROPS -#if defined(EXTENDED_PROPS) QJsonObject jsonExtended; // VK_KHR_get_physical_device_properties2 @@ -691,7 +913,6 @@ QJsonObject VulkanDeviceInfo::toJson(std::string submitter, std::string comment) jsonExtended["devicefeatures2"] = jsonFeatures2; root["extended"] = jsonExtended; -#endif return root; } diff --git a/vulkanDeviceInfo.h b/vulkanDeviceInfo.h index eb0ad3f..50e7370 100644 --- a/vulkanDeviceInfo.h +++ b/vulkanDeviceInfo.h @@ -4,7 +4,7 @@ * * Device information class * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -75,6 +75,7 @@ class VulkanDeviceInfo: public VulkanDeviceInfoExtensions private: std::vector layers; bool vulkan_1_1(); + bool vulkan_1_2(); bool extensionSupported(const char* extensionName); #if defined(__ANDROID__) std::string getSystemProperty(const char* propname); @@ -90,8 +91,12 @@ class VulkanDeviceInfo: public VulkanDeviceInfoExtensions VkPhysicalDeviceProperties props; VkPhysicalDeviceMemoryProperties memoryProperties; VkPhysicalDeviceFeatures deviceFeatures; + QVariantMap core11Features; + QVariantMap core12Features; bool hasSubgroupProperties = false; QVariantMap subgroupProperties; + QVariantMap core11Properties; + QVariantMap core12Properties; std::vector queueFamilies; std::vector formats; VulkanSurfaceInfo surfaceInfo; diff --git a/vulkancapsviewer.cpp b/vulkancapsviewer.cpp index 9551044..ab764e8 100644 --- a/vulkancapsviewer.cpp +++ b/vulkancapsviewer.cpp @@ -2,7 +2,7 @@ * * Vulkan hardware capability viewer * -* Copyright (C) 2016 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -75,14 +75,9 @@ extern "C"{ using std::to_string; -#define VK_API_VERSION VK_API_VERSION_1_1 +const std::string vulkanCapsViewer::version = "3.0"; +const std::string vulkanCapsViewer::reportVersion = "3.0"; -const std::string vulkanCapsViewer::version = "2.23"; -const std::string vulkanCapsViewer::reportVersion = "2.0"; - -/// -/// Returns operating system name -/// OSInfo getOperatingSystem() { // QSysInfo works for all supported operating systems @@ -93,6 +88,19 @@ OSInfo getOperatingSystem() return osInfo; } +// Convert a list variant into an imploded string +QString arrayToStr(QVariant value) { + QList list = value.toList(); + QString imploded; + for (auto i = 0; i < list.size(); i++) { + imploded += list[i].toString(); + if (i < list.size() - 1) + imploded += ", "; + } + return "[" + imploded + "]"; +} + + #ifdef __ANDROID__ void setTouchProps(QWidget *widget) { QScroller *scroller = QScroller::scroller(widget); @@ -132,13 +140,11 @@ vulkanCapsViewer::vulkanCapsViewer(QWidget *parent) qApp->setStyle(QStyleFactory::create("Fusion")); - vulkanApiVersion = QString::fromStdString(vulkanResources::versionToString(VK_API_VERSION)); - ui.label_header_top->setText(ui.label_header_top->text() + " " + QString::fromStdString(version)); #ifdef ANDROID // Load Vulkan libraries on Android manually if (!loadVulkanLibrary()) { - QMessageBox::warning(this, "Error", "Could not initialize Vulkan!\n\nPlease make sure that this device actually supports the Vulkan API!"); + QMessageBox::warning(this, "Error", "Could not initialize Vulkan!\n\nPlease make sure that this device actually supports the Vulkan API."); exit(EXIT_FAILURE); } // Adjust toolbar to better fit mobile devices @@ -181,21 +187,45 @@ vulkanCapsViewer::vulkanCapsViewer(QWidget *parent) if (!initVulkan()) { - QMessageBox::warning(this, "Error", "Could not initialize Vulkan!\nDevice must support Vulkan API version " + vulkanApiVersion + "!"); + QMessageBox::warning(this, "Error", "Could not initialize Vulkan!\n\nMake sure that at least one installed device supports Vulkan and supports at least Version 1.1."); exit(EXIT_FAILURE); } appSettings.restore(); // Models and filters - // Limits - ui.treeViewDeviceLimits->setModel(&filterProxies.limits); - filterProxies.limits.setSourceModel(&models.limits); - connect(ui.filterLineEditLimits, SIGNAL(textChanged(QString)), this, SLOT(slotFilterLimits(QString))); - // Features - ui.treeViewDeviceFeatures->setModel(&filterProxies.features); - filterProxies.features.setSourceModel(&models.features); + // Core 1.0 properties + ui.treeViewDeviceProperties->setModel(&filterProxies.propertiesCore10); + filterProxies.propertiesCore10.setSourceModel(&models.propertiesCore10); + connect(ui.filterLineEditProperties, SIGNAL(textChanged(QString)), this, SLOT(slotFilterPropertiesCore10(QString))); + // Core 1.1 properties + ui.treeViewDevicePropertiesCore11->setModel(&filterProxies.propertiesCore11); + filterProxies.propertiesCore11.setSourceModel(&models.propertiesCore11); + connect(ui.filterLineEditPropertiesCore11, SIGNAL(textChanged(QString)), this, SLOT(slotFilterPropertiesCore11(QString))); + // Core 1.2 properties + ui.treeViewDevicePropertiesCore12->setModel(&filterProxies.propertiesCore12); + filterProxies.propertiesCore12.setSourceModel(&models.propertiesCore12); + connect(ui.filterLineEditPropertiesCore12, SIGNAL(textChanged(QString)), this, SLOT(slotFilterPropertiesCore12(QString))); + // Extension properties + ui.treeViewDevicePropertiesExtensions->setModel(&filterProxies.propertiesExtensions); + filterProxies.propertiesExtensions.setSourceModel(&models.propertiesExtensions); + connect(ui.filterLineEditPropertiesExtensions, SIGNAL(textChanged(QString)), this, SLOT(slotFilterPropertiesExtensions(QString))); + // Core 1.0 features + ui.treeViewDeviceFeatures->setModel(&filterProxies.featuresCore10); + filterProxies.featuresCore10.setSourceModel(&models.featuresCore10); connect(ui.filterLineEditFeatures, SIGNAL(textChanged(QString)), this, SLOT(slotFilterFeatures(QString))); + // Core 1.1 features + ui.treeViewDeviceFeaturesCore11->setModel(&filterProxies.featuresCore11); + filterProxies.featuresCore11.setSourceModel(&models.featuresCore11); + connect(ui.filterLineEditFeaturesCore11, SIGNAL(textChanged(QString)), this, SLOT(slotFilterFeaturesCore11(QString))); + // Core 1.2 features + ui.treeViewDeviceFeaturesCore12->setModel(&filterProxies.featuresCore12); + filterProxies.featuresCore12.setSourceModel(&models.featuresCore12); + connect(ui.filterLineEditFeaturesCore12, SIGNAL(textChanged(QString)), this, SLOT(slotFilterFeaturesCore12(QString))); + // Extension features + ui.treeViewDeviceFeaturesExtensions->setModel(&filterProxies.featuresExtensions); + filterProxies.featuresExtensions.setSourceModel(&models.featuresExtensions); + connect(ui.filterLineEditFeaturesExtensions, SIGNAL(textChanged(QString)), this, SLOT(slotFilterFeaturesExtensions(QString))); // Extensions ui.treeViewDeviceExtensions->setModel(&filterProxies.extensions); filterProxies.extensions.setSourceModel(&models.extensions); @@ -220,62 +250,43 @@ vulkanCapsViewer::~vulkanCapsViewer() } } -/// -/// Close the application -/// void vulkanCapsViewer::slotClose() { close(); } -/// -/// Display database in default browser -/// void vulkanCapsViewer::slotBrowseDatabase() { QString link = "https://vulkan.gpuinfo.org/"; QDesktopServices::openUrl(QUrl(link)); } -/// -/// Display device report in default browser -/// void vulkanCapsViewer::slotDisplayOnlineReport() { int reportId = databaseConnection.getReportId(vulkanGPUs[selectedDeviceIndex]); - stringstream ss; - ss << databaseConnection.getBaseUrl() << "displayreport.php?id=" << reportId; - QDesktopServices::openUrl(QUrl(QString::fromStdString(ss.str()))); + QUrl url(databaseConnection.databaseUrl + "displayreport.php?id=" + QString::number(reportId)); + QDesktopServices::openUrl(url); } -/// -/// Refresh GPU list -/// -void vulkanCapsViewer::slotRefresh() +std::string apiVersionText(uint32_t apiVersion) { - // getGPUs(); TODO : Clean up before refresh + return to_string(VK_VERSION_MAJOR(apiVersion)) + "." + to_string(VK_VERSION_MINOR(apiVersion)) + "." + to_string(VK_VERSION_PATCH(apiVersion)); } -/// -/// Display an about box -/// void vulkanCapsViewer::slotAbout() { std::stringstream aboutText; aboutText << "

Vulkan Hardware Capability Viewer " << version << "

" "Copyright (c) 2016-2020 by Sascha Willems

" - "Build against Vulkan API " + vulkanApiVersion.toStdString() + - " header version " + to_string(VK_HEADER_VERSION) + "

" - "This tool is FREEWARE

" - "For usage and distribution details refer to the readme


" - "https://www.gpuinfo.org

"; + "This tool is Free Open Source Software

" + "For usage and distribution details refer to the readme

" + "https://www.gpuinfo.org

" + "Vulkan instance API version: " + apiVersionText(instanceApiVersion) + "
" + "Compiled against Vulkan header version: " + to_string(VK_HEADER_VERSION) + "

"; aboutText << "

"; - QMessageBox::about(this, tr("About the Vulkan hardware capability viewer"), QString::fromStdString(aboutText.str())); + QMessageBox::about(this, tr("About the Vulkan Hardware Capability Viewer"), QString::fromStdString(aboutText.str())); } -/// -/// GPU selection changed -/// void vulkanCapsViewer::slotComboBoxGPUIndexChanged(int index) { if (index != selectedDeviceIndex) @@ -284,9 +295,6 @@ void vulkanCapsViewer::slotComboBoxGPUIndexChanged(int index) } } -/// -/// Save report to disk (JSON) -/// void vulkanCapsViewer::slotSaveReport() { VulkanDeviceInfo device = vulkanGPUs[selectedDeviceIndex]; @@ -297,9 +305,6 @@ void vulkanCapsViewer::slotSaveReport() } } -/// -/// Upload report to online database -/// void vulkanCapsViewer::slotUploadReport() { VulkanDeviceInfo device = vulkanGPUs[selectedDeviceIndex]; @@ -311,41 +316,61 @@ void vulkanCapsViewer::slotUploadReport() return; } - int reportId = databaseConnection.getReportId(device); - if (reportId > -1) - { - QMessageBox::StandardButton reply; - reply = QMessageBox::question(this, "Device already present", "A report for the selected device is aleady present in the database.\n\nDo you want to open the report in your browser?", QMessageBox::Yes | QMessageBox::No); - if (reply == QMessageBox::Yes) - { - QString url = QString::fromStdString(databaseConnection.getBaseUrl() + "displayreport.php?id=" + to_string(reportId)); - QDesktopServices::openUrl(QUrl(url)); - } - return; - } + // Upload new report + if (reportState == ReportState::not_present) { + submitDialog dialog(appSettings.submitterName, "Submit new report"); + if (dialog.exec() == QDialog::Accepted) { + exportReportAsJSON("vulkanreport.json", dialog.getSubmitter(), dialog.getComment()); + std::ostringstream sstream(std::ios::out | std::ios::binary); + std::ifstream inFile("vulkanreport.json"); + std::string line; + while (std::getline(inFile, line)) sstream << line << "\r\n"; + string reply = databaseConnection.postReport(sstream.str()); + if (reply == "res_uploaded") + { + QMessageBox::information(this, "Report submitted", "Your report has been uploaded to the database!\n\nThank you for your contribution!"); + checkReportDatabaseState(); + } + else + { + QMessageBox::warning(this, "Error", "The report could not be uploaded : \n" + QString::fromStdString(reply)); + } + } + return; + } - submitDialog dialog(appSettings.submitterName); - bool ok = (dialog.exec() == QDialog::Accepted); + // Update existing report + if (reportState == ReportState::is_updatable) { + submitDialog dialog(appSettings.submitterName, "Update existing report"); + if (dialog.exec() == QDialog::Accepted) { + int reportId = databaseConnection.getReportId(device); + QApplication::setOverrideCursor(Qt::WaitCursor); + QString updateLog; + bool updateResult = databaseConnection.postReportForUpdate(device, reportId, updateLog); + QApplication::restoreOverrideCursor(); + if (updateResult) { + QMessageBox::information(this, "Report updated", "The report has been updated with the following information:\n\n" + updateLog + "\nThank you for your contribution!"); + } + else { + QMessageBox::warning(this, "Error", "The report could not be updated : \n" + QString::fromStdString("xxx")); + } + checkReportDatabaseState(); + } + return; + } - if (ok) - { - exportReportAsJSON("vulkanreport.json", dialog.getSubmitter(), dialog.getComment()); - std::ostringstream sstream(std::ios::out | std::ios::binary); - std::ifstream inFile("vulkanreport.json"); - std::string line; - while (std::getline(inFile, line)) sstream << line << "\r\n"; - - string reply = databaseConnection.postReport(sstream.str()); - if (reply == "res_uploaded") - { - QMessageBox::information(this, "Report submitted", "Your report has been uploaded to the database!\n\nThanks for your contribution!"); - checkReportDatabaseState(); - } - else - { - QMessageBox::warning(this, "Error", "The report could not be uploaded : \n" + QString::fromStdString(reply)); - } - } + // Show link to database for existing reports + if (reportState == ReportState::is_present) { + int reportId = databaseConnection.getReportId(device); + QMessageBox::StandardButton reply; + reply = QMessageBox::question(this, "Device already present", "A report for the selected device is already present in the database.\n\nDo you want to open the report in your browser?", QMessageBox::Yes | QMessageBox::No); + if (reply == QMessageBox::Yes) + { + QUrl url(databaseConnection.databaseUrl + "displayreport.php?id=" + QString::number(reportId)); + QDesktopServices::openUrl(url); + } + return; + } } void vulkanCapsViewer::slotSettings() @@ -356,16 +381,52 @@ void vulkanCapsViewer::slotSettings() appSettings.restore(); } -void vulkanCapsViewer::slotFilterLimits(QString text) +void vulkanCapsViewer::slotFilterPropertiesCore10(QString text) { - QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); - filterProxies.limits.setFilterRegExp(regExp); + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.propertiesCore10.setFilterRegExp(regExp); +} + +void vulkanCapsViewer::slotFilterPropertiesCore11(QString text) +{ + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.propertiesCore11.setFilterRegExp(regExp); +} + +void vulkanCapsViewer::slotFilterPropertiesCore12(QString text) +{ + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.propertiesCore12.setFilterRegExp(regExp); +} + +void vulkanCapsViewer::slotFilterPropertiesExtensions(QString text) +{ + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.propertiesExtensions.setFilterRegExp(regExp); } void vulkanCapsViewer::slotFilterFeatures(QString text) { QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); - filterProxies.features.setFilterRegExp(regExp); + filterProxies.featuresCore10.setFilterRegExp(regExp); +} + +void vulkanCapsViewer::slotFilterFeaturesCore11(QString text) +{ + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.featuresCore11.setFilterRegExp(regExp); +} + +void vulkanCapsViewer::slotFilterFeaturesCore12(QString text) +{ + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.featuresCore12.setFilterRegExp(regExp); +} + +void vulkanCapsViewer::slotFilterFeaturesExtensions(QString text) +{ + QRegExp regExp(text, Qt::CaseInsensitive, QRegExp::RegExp); + filterProxies.featuresExtensions.setFilterRegExp(regExp); } void vulkanCapsViewer::slotFilterExtensions(QString text) @@ -385,34 +446,25 @@ void vulkanCapsViewer::slotComboTabChanged(int index) ui.tabWidgetDevice->setCurrentIndex(index); } -void vulkanCapsViewer::displayGlobalExtensions() -{ - QTreeWidget *tree = ui.treeWidgetGlobalExtenssions; - - for (auto& ext : instanceInfo.extensions) { - QTreeWidgetItem *treeItem = new QTreeWidgetItem(tree); - treeItem->setText(0, QString::fromUtf8(ext.extensionName)); - treeItem->setText(1, QString::fromStdString(vulkanResources::revisionToString(ext.specVersion))); - } - for (int i = 0; i < tree->columnCount(); i++) { - tree->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); - } -} - -/// -/// Initialize vulkan and dome some initial setup -/// bool vulkanCapsViewer::initVulkan() { VkResult vkRes; + // Get the max. supported Vulkan Version if vkEnumerateInstanceVersion is available (loader version 1.1 and up) + PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion = reinterpret_cast(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); + if (vkEnumerateInstanceVersion) { + vkEnumerateInstanceVersion(&instanceApiVersion); + } else { + instanceApiVersion = VK_API_VERSION_1_0; + } + VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "VulkanCapsViewer"; appInfo.applicationVersion = 1; appInfo.pEngineName = "VulkanCapsViewer"; appInfo.engineVersion = 1; - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = instanceApiVersion; // Create Vulkan instance VkInstanceCreateInfo instanceCreateInfo = {}; @@ -513,7 +565,7 @@ bool vulkanCapsViewer::initVulkan() QString error; if (vkRes == VK_ERROR_INCOMPATIBLE_DRIVER) { - error = "No compatible Vulkan driver found!\nThis version requires a Vulkan driver that is compatible with API Level " + QString::fromStdString(vulkanResources::versionToString(VK_API_VERSION)); + error = "No compatible Vulkan driver found!\nThis version requires a Vulkan driver that is compatible with at least Vulkan 1.1"; } else { @@ -640,15 +692,12 @@ bool vulkanCapsViewer::initVulkan() surface = VK_NULL_HANDLE; } - displayGlobalLayers(ui.treeWidgetGlobalLayers); - displayGlobalExtensions(); + displayInstanceLayers(); + displayInstanceExtensions(); return true; } -/// -/// Get details for the specificed vulkan GPU -/// void vulkanCapsViewer::getGPUinfo(VulkanDeviceInfo *GPU, uint32_t id, VkPhysicalDevice device) { VkResult vkRes; @@ -692,11 +741,8 @@ void vulkanCapsViewer::getGPUinfo(VulkanDeviceInfo *GPU, uint32_t id, VkPhysical VkDeviceCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - info.pNext = NULL; info.pQueueCreateInfos = queueCreateInfos.data(); info.queueCreateInfoCount = (uint32_t)queueCreateInfos.size(); - info.pEnabledFeatures = NULL; - info.ppEnabledLayerNames = NULL; info.enabledLayerCount = 0; // info.enabledExtensionCount = enabledExtensions.size(); // info.ppEnabledExtensionNames = enabledExtensions.data(); @@ -716,9 +762,6 @@ void vulkanCapsViewer::getGPUinfo(VulkanDeviceInfo *GPU, uint32_t id, VkPhysical GPU->appVersion = version; } -/// -/// Get list of all available GPUs that support Vulkan -/// void vulkanCapsViewer::getGPUs() { VkResult vkRes; @@ -763,6 +806,11 @@ void vulkanCapsViewer::getGPUs() { QMessageBox::warning(this, tr("Error"), "Could not find a GPU with Vulkan support!"); } + + // Only display device selection of more than once device is present (Android only) +#ifdef __ANDROID__ + ui.widgetDeviceSelection->setVisible(vulkanGPUs.size() > 1); +#endif } QTreeWidgetItem *addTreeItem(QTreeWidgetItem *parent, const std::string& key, const std::string& value) @@ -774,32 +822,6 @@ QTreeWidgetItem *addTreeItem(QTreeWidgetItem *parent, const std::string& key, co return newItem; } -enum ItemFormat {DEFAULT_FORMAT, HEX_FORMAT}; -QTreeWidgetItem *addTreeItem(QTreeWidgetItem *parent, QVariantMap::const_iterator iter, const ItemFormat format = DEFAULT_FORMAT) -{ - // Map some key names to different display names - QMap replaceList; - replaceList["apiVersionText"] = "apiVersion"; - replaceList["deviceTypeText"] = "deviceType"; - replaceList["driverVersionText"] = "driverVersion"; - - QString keyName = iter.key(); - if (replaceList.contains(keyName)) { - keyName = replaceList[keyName]; - } - - QTreeWidgetItem *newItem = new QTreeWidgetItem(parent); - newItem->setText(0, keyName); - if (format == HEX_FORMAT){ - newItem->setText(1, vulkanResources::toHexQString(iter.value().toULongLong())); - } else { - assert(format == DEFAULT_FORMAT); - newItem->setText(1, iter.value().toString()); - } - parent->addChild(newItem); - return newItem; -} - QTreeWidgetItem *addTreeItemVkBool32(QTreeWidgetItem *parent, const std::string& key, const VkBool32 value) { QTreeWidgetItem *newItem = new QTreeWidgetItem(parent); @@ -833,9 +855,150 @@ QTreeWidgetItem *addTreeItemFlags(QTreeWidgetItem *parent, const std::string& fl return flagsItem; } -/// -/// Display information on given device -/// +void addVkBool32Item(QStandardItem* parent, const QVariantMap::const_iterator& iterator) +{ + QList item; + item << new QStandardItem(iterator.key()); + item << new QStandardItem(iterator.value().toBool() ? "true" : "false"); + item[1]->setForeground(iterator.value().toBool() ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); + parent->appendRow(item); +} + +void addVkSampleCountFlagsItem(QStandardItem* parent, const QVariantMap::const_iterator& iterator) +{ + const auto samples = static_cast(iterator.value().toUInt()); + QList item; + item << new QStandardItem(iterator.key()); + item << new QStandardItem(vulkanResources::toQStringList(samples)); + parent->appendRow(item); +} + +void addUUIDItem(QStandardItem* parent, const QString& key, uint8_t* UUID) +{ + std::ostringstream uuidSs; + uuidSs << std::hex << std::noshowbase << std::uppercase; + for (uint32_t i = 0; i < VK_UUID_SIZE; i++) { + uuidSs << std::right << std::setw(2) << std::setfill('0') << static_cast(UUID[i]); + if (i == 3 || i == 5 || i == 7 || i == 9) uuidSs << '-'; + } + QList item; + item << new QStandardItem(key); + item << new QStandardItem(QString::fromStdString(uuidSs.str())); + parent->appendRow(item); +} + +void addUUIDItem(QStandardItem* parent, const QVariantMap::const_iterator& iterator) +{ + const QJsonArray values = iterator.value().toJsonArray(); + std::ostringstream uuidSs; + uuidSs << std::hex << std::noshowbase << std::uppercase; + for (size_t i = 0; i < values.size(); i++) { + uuidSs << std::right << std::setw(2) << std::setfill('0') << static_cast(values[static_cast(i)].toInt()); + if (i == 3 || i == 5 || i == 7 || i == 9) uuidSs << '-'; + } + QList item; + item << new QStandardItem(iterator.key()); + item << new QStandardItem(QString::fromStdString(uuidSs.str())); + parent->appendRow(item); +} + +void addHexItem(QStandardItem* parent, const QVariantMap::const_iterator& iterator) +{ + QList item; + item << new QStandardItem(iterator.key()); + item << new QStandardItem(vulkanResources::toHexQString(iterator.value().toULongLong())); + parent->appendRow(item); +} + +void addVariantListItem(QStandardItem* parent, const QVariantMap::const_iterator& iterator) +{ + QList item; + item << new QStandardItem(iterator.key()); + item << new QStandardItem(arrayToStr(iterator.value())); + parent->appendRow(item); +} + +template +void addBitFlagsItem(QStandardItem* parent, const QString& key, const VkFlags flags, std::string(* const flagToString)(BitsType)) +{ + QList flagsParentItem; + flagsParentItem << new QStandardItem(key); + flagsParentItem << new QStandardItem(QString::fromStdString(vulkanResources::toHexString(flags))); + parent->appendRow(flagsParentItem); + for (typename std::underlying_type::type bit = 0x1; bit != 0; bit <<= 1) { + const QString bitName = QString::fromStdString(flagToString(static_cast(bit))); + if (flags & bit) { + QList flagItem; + flagItem << new QStandardItem(bitName); + flagItem << new QStandardItem(); + flagsParentItem[0]->appendRow(flagItem); + } + } + if (key == "subgroupSupportedStages") { + if ((flags & VK_SHADER_STAGE_ALL_GRAPHICS) == VK_SHADER_STAGE_ALL_GRAPHICS) { + QList flagItem; + flagItem << new QStandardItem(QString::fromStdString(vulkanResources::shaderStagesBitString(VK_SHADER_STAGE_ALL_GRAPHICS))); + flagItem << new QStandardItem(); + flagsParentItem[0]->appendRow(flagItem); + } + if ((flags & VK_SHADER_STAGE_ALL) == VK_SHADER_STAGE_ALL) { + QList flagItem; + flagItem << new QStandardItem(QString::fromStdString(vulkanResources::shaderStagesBitString(VK_SHADER_STAGE_ALL))); + flagItem << new QStandardItem(); + flagsParentItem[0]->appendRow(flagItem); + } + } +} + +void addPropertiesRow(QStandardItem* parent, const QVariantMap::const_iterator& iterator) +{ + QString key = iterator.key(); + + if (vulkanResources::skipValueNames.contains(key)) { + return; + } + + if (vulkanResources::boolValueNames.contains(key)) { + addVkBool32Item(parent, iterator); + return; + }; + if (vulkanResources::sampleFlagsValueNames.contains(key)) { + addVkSampleCountFlagsItem(parent, iterator); + return; + } + if (vulkanResources::uuidValueNames.contains(key)) { + addUUIDItem(parent, iterator); + return; + } + if (vulkanResources::hexValueNames.contains(key)) { + addHexItem(parent, iterator); + return; + } + if (iterator.value().canConvert(QVariant::List)) { + addVariantListItem(parent, iterator); + return; + } + if (key == "subgroupSupportedOperations") { + const VkSubgroupFeatureFlags flags = iterator.value().toUInt(); + addBitFlagsItem(parent, iterator.key(), flags, vulkanResources::subgroupFeatureBitString); + return; + } + if (key == "subgroupSupportedStages") { + const VkShaderStageFlags flags = iterator.value().toUInt(); + addBitFlagsItem(parent, iterator.key(), flags, vulkanResources::shaderStagesBitString); + return; + } + + if (vulkanResources::replaceKeyNames.contains(key)) { + key = vulkanResources::replaceKeyNames[key]; + } + + QList item; + item << new QStandardItem(key); + item << new QStandardItem(iterator.value().toString()); + parent->appendRow(item); +} + void vulkanCapsViewer::displayDevice(int index) { assert(index < vulkanGPUs.size()); @@ -845,9 +1008,7 @@ void vulkanCapsViewer::displayDevice(int index) displayDeviceProperties(&device); displayDeviceMemoryProperites(&device); - displayDeviceLimits(&device); displayDeviceFeatures(&device); - displayDeviceLayers(&device); displayDeviceFormats(&device); displayDeviceExtensions(&device); displayDeviceQueues(&device); @@ -858,94 +1019,108 @@ void vulkanCapsViewer::displayDevice(int index) void vulkanCapsViewer::displayDeviceProperties(VulkanDeviceInfo *device) { - QTreeWidget *treeWidget = ui.treeWidgetDeviceProperties; - treeWidget->clear(); - QTreeWidgetItem *treeItem = treeWidget->invisibleRootItem(); - - - { - // Some keys are doubled for raw and readable data for vkjson compatiblity, filter them out and display readable versions only - const QSet skipList = {"apiVersion", "deviceType", "driverVersion", "headerversion"}; - - // Some values look better as hex int - const QSet hexList = {"vendorID", "deviceID"}; - - // Basic properties - for(QVariantMap::const_iterator iter = device->properties.begin(); iter != device->properties.end(); ++iter) { - const QString& propName = iter.key(); - if (skipList.contains(propName)) continue; - - const ItemFormat itemFormat = hexList.contains(propName) ? HEX_FORMAT : DEFAULT_FORMAT; - addTreeItem(treeItem, iter, itemFormat); + // Core 1.0 + models.propertiesCore10.clear(); + QStandardItem* rootItem = models.propertiesCore10.invisibleRootItem(); + for (QVariantMap::const_iterator iter = device->properties.begin(); iter != device->properties.end(); ++iter) { + addPropertiesRow(rootItem, iter); + } + addUUIDItem(rootItem, "pipelineCacheUUID", device->props.pipelineCacheUUID); + // Core 1.0 limits + QList core10LimitsItem; + core10LimitsItem << new QStandardItem("Limits"); + rootItem->appendRow(core10LimitsItem); + for (QVariantMap::const_iterator iter = device->limits.begin(); iter != device->limits.end(); ++iter) { + addPropertiesRow(core10LimitsItem[0], iter); + } + // Core 1.0 sparse properties + QList core10SparseItem; + core10SparseItem << new QStandardItem("Sparse properties"); + rootItem->appendRow(core10SparseItem); + for (QVariantMap::const_iterator iter = device->sparseProperties.begin(); iter != device->sparseProperties.end(); ++iter) { + addVkBool32Item(core10SparseItem[0], iter); + } +#if !defined(__ANDROID__) + ui.treeViewDeviceProperties->expandAll(); +#endif + ui.treeViewDeviceProperties->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + + // Core 1.1 + models.propertiesCore11.clear(); + if (!(device->core11Properties.empty())) { + ui.tabWidgetProperties->setTabEnabled(1, true); + QStandardItem* rootItem = models.propertiesCore11.invisibleRootItem(); + for (QVariantMap::const_iterator iter = device->core11Properties.begin(); iter != device->core11Properties.end(); ++iter) { + addPropertiesRow(rootItem, iter); } + ui.treeViewDevicePropertiesCore11->expandAll(); + ui.treeViewDevicePropertiesCore11->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + } + else { + ui.tabWidgetProperties->setTabEnabled(1, false); } - // Sparse properties - QTreeWidgetItem *parentItem = new QTreeWidgetItem(treeItem); - parentItem->setText(0, "sparse properties"); - treeItem->addChild(parentItem); - for(QVariantMap::const_iterator iter = device->sparseProperties.begin(); iter != device->sparseProperties.end(); ++iter) { - addTreeItemVkBool32(parentItem, iter.key().toStdString(), iter.value().toBool()); + // Core 1.2 + models.propertiesCore12.clear(); + if (!(device->core12Properties.empty())) { + ui.tabWidgetProperties->setTabEnabled(2, true); + QStandardItem* rootItem = models.propertiesCore12.invisibleRootItem(); + for (QVariantMap::const_iterator iter = device->core12Properties.begin(); iter != device->core12Properties.end(); ++iter) { + addPropertiesRow(rootItem, iter); + } + ui.treeViewDevicePropertiesCore12->expandAll(); + ui.treeViewDevicePropertiesCore12->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + } + else { + ui.tabWidgetProperties->setTabEnabled(2, false); } - // Subgroup operations properties - if (device->hasSubgroupProperties) { - QTreeWidgetItem *parentItem = new QTreeWidgetItem(treeItem); - parentItem->setText(0, "subgroup properties"); - for(QVariantMap::const_iterator iter = device->subgroupProperties.begin(); iter != device->subgroupProperties.end(); ++iter) { - QString keyName = iter.key(); - if (keyName == "quadOperationsInAllStages") { - addTreeItemVkBool32(parentItem, iter.key().toStdString(), iter.value().toBool()); - } - if (keyName == "subgroupSize") { - addTreeItem(parentItem, iter); - } - if (keyName == "supportedOperations") { - const VkSubgroupFeatureFlags flags = iter.value().toUInt(); - addTreeItemFlags(parentItem, iter.key().toStdString(), flags, vulkanResources::subgroupFeatureBitString); + // Extensions + models.propertiesExtensions.clear(); + if (!(device->properties2.empty())) { + ui.tabWidgetProperties->setTabEnabled(3, true); + QStandardItem* rootItem = models.propertiesExtensions.invisibleRootItem(); + for (auto& extension : device->extensions) { + bool hasProperties = false; + QList extItem; + for (auto& property : device->properties2) { + if (strcmp(property.extension, extension.extensionName) == 0) { + if (!hasProperties) { + hasProperties = true; + extItem << new QStandardItem(QString::fromStdString(extension.extensionName)); + extItem << new QStandardItem(); + } + QList propertyItem; + propertyItem << new QStandardItem(QString::fromStdString(property.name)); + + if (property.value.canConvert(QVariant::List)) { + propertyItem << new QStandardItem(arrayToStr(property.value)); + } + else { + switch (property.value.type()) { + case QVariant::Bool: { + bool boolVal = property.value.toBool(); + propertyItem << new QStandardItem(boolVal ? "true" : "false"); + propertyItem[1]->setForeground(boolVal ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); + break; + } + default: + propertyItem << new QStandardItem(property.value.toString()); + } + } + extItem.first()->appendRow(propertyItem); + } } - if (keyName == "supportedStages") { - VkShaderStageFlags flags = iter.value().toUInt(); - QTreeWidgetItem *stagesItem = addTreeItemFlags(parentItem, iter.key().toStdString(), flags, vulkanResources::shaderStagesBitString); - addTreeItemFlag(stagesItem, - QString::fromStdString(vulkanResources::shaderStagesBitString(VK_SHADER_STAGE_ALL_GRAPHICS)), - (flags & VK_SHADER_STAGE_ALL_GRAPHICS) == VK_SHADER_STAGE_ALL_GRAPHICS); - addTreeItemFlag(stagesItem, - QString::fromStdString(vulkanResources::shaderStagesBitString(VK_SHADER_STAGE_ALL)), - (flags & VK_SHADER_STAGE_ALL) == VK_SHADER_STAGE_ALL); + if (hasProperties) { + rootItem->appendRow(extItem); } } + ui.treeViewDevicePropertiesExtensions->expandAll(); + ui.treeViewDevicePropertiesExtensions->header()->setSectionResizeMode(QHeaderView::ResizeToContents); } - - // Pipeline cache UUID - std::ostringstream uuidSs; - uuidSs << std::hex << std::noshowbase << std::nouppercase; - assert(VK_UUID_SIZE == 16); - for (uint32_t i = 0; i < VK_UUID_SIZE; ++i){ - uuidSs << std::right << std::setw(2) << std::setfill('0') << static_cast(device->props.pipelineCacheUUID[i]); - if (i == 3 || i == 5 || i == 7 || i == 9) uuidSs << '-'; - } - addTreeItem(treeItem, "pipelineCacheUUID", uuidSs.str()); - - // Operating system - stringstream ss; - ss << device->os.name << " " << device->os.version << " (" << device->os.architecture << ")"; - addTreeItem(treeItem, "operatingsystem", ss.str()); - - // Platform specific info - if (device->platformdetails.size() > 0) { - QTreeWidgetItem *platformItem = new QTreeWidgetItem(treeItem); - platformItem->setText(0, "Platform details"); - treeItem->addChild(platformItem); - for (auto& detail : device->platformdetails) { - addTreeItem(platformItem, detail.first, detail.second); - } + else { + ui.tabWidgetProperties->setTabEnabled(3, false); } - - ui.treeWidgetDeviceProperties->expandAll(); - - for (int i = 0; i < treeWidget->columnCount(); i++) - treeWidget->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); } void vulkanCapsViewer::displayDeviceMemoryProperites(VulkanDeviceInfo *device) @@ -983,106 +1158,111 @@ void vulkanCapsViewer::displayDeviceMemoryProperites(VulkanDeviceInfo *device) treeWidget->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); } -void vulkanCapsViewer::displayDeviceLimits(VulkanDeviceInfo *device) +void vulkanCapsViewer::displayDeviceFeatures(VulkanDeviceInfo *device) { - const QSet sampleFlagsLims = { - "framebufferColorSampleCounts", "framebufferDepthSampleCounts", "framebufferStencilSampleCounts", "framebufferNoAttachmentsSampleCounts", - "sampledImageColorSampleCounts", "sampledImageIntegerSampleCounts", "sampledImageDepthSampleCounts", "sampledImageStencilSampleCounts", - "storageImageSampleCounts" - }; + // Core 1.0 + models.featuresCore10.clear(); + QStandardItem *rootItem = models.featuresCore10.invisibleRootItem(); + for(QVariantMap::const_iterator iter = device->features.begin(); iter != device->features.end(); ++iter) { + addVkBool32Item(rootItem, iter); + } + ui.treeViewDeviceFeatures->expandAll(); + ui.treeViewDeviceFeatures->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - const QSet boolLims = {"timestampComputeAndGraphics", "strictLines", "standardSampleLocations"}; - - models.limits.clear(); - QStandardItem *rootItem = models.limits.invisibleRootItem(); - for(QVariantMap::const_iterator iter = device->limits.begin(); iter != device->limits.end(); ++iter) { - QList rowItems; - rowItems << new QStandardItem(iter.key()); - if (iter.value().canConvert(QVariant::List)) { - QList list = iter.value().toList(); - QString listStr = "["; - for (int i = 0; i < list.size(); i++) { - listStr += list[i].toString(); - if (i < list.size() - 1) - listStr += ", "; - } - listStr += "]"; - rowItems << new QStandardItem(listStr); - } else if (sampleFlagsLims.contains(iter.key())){ - const auto samples = static_cast(iter.value().toUInt()); - rowItems << new QStandardItem(vulkanResources::toQStringList(samples)); - } else if (boolLims.contains(iter.key())){ - rowItems << new QStandardItem(iter.value().toBool() ? "true" : "false"); - rowItems[1]->setForeground(iter.value().toBool() ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); - } else { - rowItems << new QStandardItem(iter.value().toString()); + // Core 1.1 + models.featuresCore11.clear(); + if (!(device->core11Features.empty())) { + ui.tabWidgetFeatures->setTabEnabled(1, true); + QStandardItem *rootItem = models.featuresCore11.invisibleRootItem(); + for(QVariantMap::const_iterator iter = device->core11Features.begin(); iter != device->core11Features.end(); ++iter) { + addVkBool32Item(rootItem, iter); } - rootItem->appendRow(rowItems); + ui.treeViewDeviceFeaturesCore11->expandAll(); + ui.treeViewDeviceFeaturesCore11->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + } + else { + ui.tabWidgetFeatures->setTabEnabled(1, false); } - ui.treeViewDeviceLimits->header()->setSectionResizeMode(QHeaderView::ResizeToContents); -} -void vulkanCapsViewer::displayDeviceFeatures(VulkanDeviceInfo *device) -{ - models.features.clear(); - QStandardItem *rootItem = models.features.invisibleRootItem(); + // Core 1.2 + models.featuresCore12.clear(); + if (!(device->core12Features.empty())) { + ui.tabWidgetFeatures->setTabEnabled(2, true); + QStandardItem *rootItem = models.featuresCore12.invisibleRootItem(); + for(QVariantMap::const_iterator iter = device->core12Features.begin(); iter != device->core12Features.end(); ++iter) { + addVkBool32Item(rootItem, iter); + } + ui.treeViewDeviceFeaturesCore12->expandAll(); + ui.treeViewDeviceFeaturesCore12->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + } + else { + ui.tabWidgetFeatures->setTabEnabled(2, false); + } - // Basic features - for(QVariantMap::const_iterator iter = device->features.begin(); iter != device->features.end(); ++iter) { - QList rowItems; - rowItems << new QStandardItem(iter.key()); - rowItems << new QStandardItem(iter.value().toBool() ? "true" : "false"); - rowItems[1]->setForeground(iter.value().toBool() ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); - rootItem->appendRow(rowItems); - } + // Extensions + models.featuresExtensions.clear(); + if (!(device->features2.empty())) { + ui.tabWidgetFeatures->setTabEnabled(3, true); + QStandardItem* rootItem = models.featuresExtensions.invisibleRootItem(); + for (auto& extension : device->extensions) { + bool hasFeatures = false; + QList extItem; + for (auto& feature : device->features2) { + if (strcmp(feature.extension, extension.extensionName) == 0) { + if (!hasFeatures) { + hasFeatures = true; + extItem << new QStandardItem(QString::fromStdString(extension.extensionName)); + extItem << new QStandardItem(); + } + QList featureItem; + featureItem << new QStandardItem(QString::fromStdString(feature.name)); + featureItem << new QStandardItem((feature.supported) ? "true" : "false"); + featureItem[1]->setForeground((feature.supported) ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); + extItem.first()->appendRow(featureItem); + } + } + if (hasFeatures) { + rootItem->appendRow(extItem); + } + } + ui.treeViewDeviceFeaturesExtensions->expandAll(); + ui.treeViewDeviceFeaturesExtensions->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + } + else { + ui.tabWidgetFeatures->setTabEnabled(3, false); + } - ui.treeViewDeviceFeatures->expandAll(); - ui.treeViewDeviceFeatures->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - ui.treeViewDeviceFeatures->header()->setStretchLastSection(false); } -void vulkanCapsViewer::displayGlobalLayers(QTreeWidget *tree) +void vulkanCapsViewer::displayInstanceLayers() { - using namespace vulkanResources; - - tree->clear(); + ui.treeWidgetGlobalLayers->clear(); for (auto& layer : instanceInfo.layers) { - QTreeWidgetItem *treeItem = new QTreeWidgetItem(tree); + QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui.treeWidgetGlobalLayers); treeItem->setText(0, QString::fromUtf8(layer.properties.layerName)); - treeItem->setText(1, QString::fromStdString(versionToString(layer.properties.specVersion))); - treeItem->setText(2, QString::fromStdString(revisionToString(layer.properties.implementationVersion))); + treeItem->setText(1, QString::fromStdString(vulkanResources::versionToString(layer.properties.specVersion))); + treeItem->setText(2, QString::fromStdString(vulkanResources::revisionToString(layer.properties.implementationVersion))); treeItem->setText(3, QString::fromStdString(to_string(layer.extensions.size()))); treeItem->setText(4, layer.properties.description); for (auto& layerExt : layer.extensions) { - addTreeItem(treeItem, layerExt.extensionName, revisionToString(layerExt.specVersion)); + addTreeItem(treeItem, layerExt.extensionName, vulkanResources::revisionToString(layerExt.specVersion)); } } - for (int i = 0; i < tree->columnCount(); i++) - tree->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); + for (int i = 0; i < ui.treeWidgetGlobalLayers->columnCount(); i++) + ui.treeWidgetGlobalLayers->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); } -void vulkanCapsViewer::displayDeviceLayers(VulkanDeviceInfo *device) +void vulkanCapsViewer::displayInstanceExtensions() { - using namespace vulkanResources; - - QTreeWidget *treeWidget = ui.treeWidgetDeviceLayers; - treeWidget->clear(); - ui.tabWidgetDevice->setTabText(5, "Layers (" + QString::number(device->getLayers().size()) + ")"); - for (auto& layer : device->getLayers()) - { - QTreeWidgetItem *treeItem = new QTreeWidgetItem(treeWidget); - treeItem->setText(0, QString::fromUtf8(layer.properties.layerName)); - treeItem->setText(1, QString::fromStdString(versionToString(layer.properties.specVersion))); - treeItem->setText(2, QString::fromStdString(revisionToString(layer.properties.implementationVersion))); - treeItem->setText(3, QString::fromStdString(to_string(layer.extensions.size()))); - treeItem->setText(4, layer.properties.description); - for (auto& layerExt : layer.extensions) - { - addTreeItem(treeItem, layerExt.extensionName, revisionToString(layerExt.specVersion)); - } - } - for (int i = 0; i < treeWidget->columnCount(); i++) - treeWidget->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); + ui.treeWidgetGlobalExtenssions->clear(); + for (auto& ext : instanceInfo.extensions) { + QTreeWidgetItem* treeItem = new QTreeWidgetItem(ui.treeWidgetGlobalExtenssions); + treeItem->setText(0, QString::fromUtf8(ext.extensionName)); + treeItem->setText(1, QString::fromStdString(vulkanResources::revisionToString(ext.specVersion))); + } + for (int i = 0; i < ui.treeWidgetGlobalExtenssions->columnCount(); i++) { + ui.treeWidgetGlobalExtenssions->header()->setSectionResizeMode(i, QHeaderView::ResizeToContents); + } } void addFlagModelItem(QStandardItem *parent, QString flagName, bool flag) @@ -1204,25 +1384,8 @@ void vulkanCapsViewer::displayDeviceFormats(VulkanDeviceInfo *device) ui.treeViewFormats->sortByColumn(0, Qt::SortOrder::AscendingOrder); } -QString arrayToStr(QVariant value) { - QList list = value.toList(); - QString listStr = "["; - for (int i = 0; i < list.size(); i++) { - listStr += list[i].toString(); - if (i < list.size() - 1) - listStr += ", "; - } - listStr += "]"; - return listStr; -} - -/* - Fill extension tree model incudling extension features and properties -*/ void vulkanCapsViewer::displayDeviceExtensions(VulkanDeviceInfo *device) { - ui.tabWidgetDevice->setTabText(3, "Extensions (" + QString::number(device->extensions.size()) + ")"); - models.extensions.clear(); QStandardItem *rootItem = models.extensions.invisibleRootItem(); @@ -1230,58 +1393,6 @@ void vulkanCapsViewer::displayDeviceExtensions(VulkanDeviceInfo *device) QList extItem; extItem << new QStandardItem(QString::fromStdString(extension.extensionName)); extItem << new QStandardItem(QString::fromStdString(vulkanResources::revisionToString(extension.specVersion))); - - // Features - bool hasFeatures = false; - QList featureRootItem; - for (auto& feature : device->features2) { - featureRootItem << new QStandardItem("Features"); - featureRootItem << new QStandardItem(" "); - if (strcmp(feature.extension, extension.extensionName) == 0) { - hasFeatures = true; - QList featureItem; - featureItem << new QStandardItem(QString::fromStdString(feature.name)); - featureItem << new QStandardItem((feature.supported) ? "true" : "false"); - featureItem[1]->setForeground((feature.supported) ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); - featureRootItem.first()->appendRow(featureItem); - } - } - if (hasFeatures) { - extItem.first()->appendRow(featureRootItem); - } - - // Properties - bool hasProperties = false; - QList propertiesRootItem; - for (auto& property : device->properties2) { - propertiesRootItem << new QStandardItem("Properties"); - propertiesRootItem << new QStandardItem(" "); - if (strcmp(property.extension, extension.extensionName) == 0) { - hasProperties = true; - QList propertyItem; - propertyItem << new QStandardItem(QString::fromStdString(property.name)); - - if (property.value.canConvert(QVariant::List)) { - propertyItem << new QStandardItem(arrayToStr(property.value)); - } else { - switch (property.value.type()) { - case QVariant::Bool: { - bool boolVal = property.value.toBool(); - propertyItem << new QStandardItem(boolVal ? "true" : "false"); - propertyItem[1]->setForeground(boolVal ? QColor::fromRgb(0, 128, 0) : QColor::fromRgb(255, 0, 0)); - break; - } - default: - propertyItem << new QStandardItem(property.value.toString()); - } - } - propertiesRootItem.first()->appendRow(propertyItem); - } - } - if (hasProperties) { - extItem.first()->appendRow(propertiesRootItem); - } - rootItem->appendRow(extItem); } @@ -1291,7 +1402,6 @@ void vulkanCapsViewer::displayDeviceExtensions(VulkanDeviceInfo *device) void vulkanCapsViewer::displayDeviceQueues(VulkanDeviceInfo *device) { - ui.tabWidgetDevice->setTabText(6, "Queues Families (" + QString::number(device->queueFamilies.size()) + ")"); QTreeWidget* treeWidget = ui.treeWidgetQueues; treeWidget->clear(); for (auto& queueFamily : device->queueFamilies) @@ -1446,42 +1556,34 @@ void vulkanCapsViewer::exportReportAsJSON(std::string fileName, std::string subm jsonFile.write(doc.toJson(QJsonDocument::Indented)); } -/// -/// Display database state for the currently selected device -/// void vulkanCapsViewer::checkReportDatabaseState() { ui.labelDevicePresent->setText("Connecting to database..."); - ui.labelDevicePresent->setVisible(true); ui.toolButtonOnlineDevice->setEnabled(false); QApplication::setOverrideCursor(Qt::WaitCursor); if (!databaseConnection.checkServerConnection()) { ui.labelDevicePresent->setText("Could not connect to the database!\n\nPlease check your internet connection and proxy settings!"); - ui.labelDevicePresent->setVisible(true); QApplication::restoreOverrideCursor(); return; } - if (databaseConnection.checkReportPresent(vulkanGPUs[selectedDeviceIndex])) + int reportId; + if (databaseConnection.checkReportPresent(vulkanGPUs[selectedDeviceIndex], reportId)) { - ui.toolButtonOnlineDevice->setEnabled(true); - ui.labelDevicePresent->setText("Device report already present in database"); - // Report present, check if it can be updated - // TODO : Update mechanics! - /* - int reportId = glhttp.getReportId(core.description); - if (canUpdateReport(reportId)) { - ui.labelDevicePresent->setText("Device already present in database, but can be updated with missing values!"); - } - */ + // Check if report can be updated with new information not yet stored in the database + if (databaseConnection.checkCanUpdateReport(vulkanGPUs[selectedDeviceIndex], reportId)) { + setReportState(ReportState::is_updatable); + } + else { + setReportState(ReportState::is_present); + } } else { - ui.labelDevicePresent->setText("Device report not present in database yet"); + setReportState(ReportState::not_present); } - ui.labelDevicePresent->setVisible(true); QApplication::restoreOverrideCursor(); } @@ -1522,3 +1624,31 @@ int vulkanCapsViewer::uploadReportNonVisual(int deviceIndex, QString submitter, return -3; } } + +void vulkanCapsViewer::setReportState(ReportState state) +{ + reportState = state; + switch (reportState) { + case ReportState::is_present: + ui.toolButtonOnlineDevice->setEnabled(false); + ui.toolButtonOnlineDevice->setEnabled(true); + ui.toolButtonUpload->setText("Upload"); + ui.labelDevicePresent->setText("Device is already present in the database"); + break; + case ReportState::not_present: + ui.toolButtonOnlineDevice->setEnabled(false); + ui.toolButtonUpload->setText("Upload"); + ui.labelDevicePresent->setText("Device can be uploaded to the database"); + break; + case ReportState::is_updatable: + ui.toolButtonOnlineDevice->setEnabled(true); + ui.toolButtonUpload->setText("Update"); + ui.labelDevicePresent->setText("Device is already present in the database, but can be updated"); + break; + default: + ui.toolButtonOnlineDevice->setEnabled(false); + ui.toolButtonUpload->setText("n.a."); + ui.labelDevicePresent->setText("Could not get report state from database"); + } +} + diff --git a/vulkancapsviewer.h b/vulkancapsviewer.h index b4e3d3b..5a1c420 100644 --- a/vulkancapsviewer.h +++ b/vulkancapsviewer.h @@ -1,3 +1,23 @@ +/* +* +* Vulkan hardware capability viewer +* +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) +* +* This code is free software, you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License version 3 as published by the Free Software Foundation. +* +* Please review the following information to ensure the GNU Lesser +* General Public License version 3 requirements will be met: +* http://opensource.org/licenses/lgpl-3.0.html +* +* The code is distributed WITHOUT ANY WARRANTY; without even the +* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +* PURPOSE. See the GNU LGPL 3.0 for more details. +* +*/ + #ifndef VULKANCAPSVIEWER_H #define VULKANCAPSVIEWER_H @@ -31,6 +51,8 @@ struct vulkanGlobalInfo } features; }; +enum ReportState { unknown, not_present, is_present, is_updatable }; + class vulkanCapsViewer : public QMainWindow { Q_OBJECT @@ -38,6 +60,7 @@ class vulkanCapsViewer : public QMainWindow public: static const std::string version; static const std::string reportVersion; + ReportState reportState = ReportState::unknown; std::vector vulkanGPUs; vulkanInstanceInfo instanceInfo; vulkanGlobalInfo globalInfo; @@ -48,7 +71,7 @@ class vulkanCapsViewer : public QMainWindow void exportReportAsJSON(std::string fileName, std::string submitter, std::string comment); int uploadReportNonVisual(int deviceIndex, QString submitter, QString comment); private: - QString vulkanApiVersion; + uint32_t instanceApiVersion; int selectedDeviceIndex = 0; VkInstance vkInstance = VK_NULL_HANDLE; VkSurfaceKHR surface; @@ -56,14 +79,26 @@ class vulkanCapsViewer : public QMainWindow Ui::vulkanCapsViewerClass ui; settings appSettings; struct { - TreeProxyFilter limits; - TreeProxyFilter features; + TreeProxyFilter propertiesCore10; + TreeProxyFilter propertiesCore11; + TreeProxyFilter propertiesCore12; + TreeProxyFilter propertiesExtensions; + TreeProxyFilter featuresCore10; + TreeProxyFilter featuresCore11; + TreeProxyFilter featuresCore12; + TreeProxyFilter featuresExtensions; TreeProxyFilter formats; TreeProxyFilter extensions; } filterProxies; struct { - QStandardItemModel limits; - QStandardItemModel features; + QStandardItemModel propertiesCore10; + QStandardItemModel propertiesCore11; + QStandardItemModel propertiesCore12; + QStandardItemModel propertiesExtensions; + QStandardItemModel featuresCore10; + QStandardItemModel featuresCore11; + QStandardItemModel featuresCore12; + QStandardItemModel featuresExtensions; QStandardItemModel formats; QStandardItemModel extensions; } models; @@ -76,27 +111,31 @@ class vulkanCapsViewer : public QMainWindow void displayDevice(int index); void displayDeviceProperties(VulkanDeviceInfo *device); void displayDeviceMemoryProperites(VulkanDeviceInfo *device); - void displayDeviceLimits(VulkanDeviceInfo *device); void displayDeviceFeatures(VulkanDeviceInfo *device); - void displayDeviceLayers(VulkanDeviceInfo *device); void displayDeviceFormats(VulkanDeviceInfo *device); void displayDeviceExtensions(VulkanDeviceInfo *device); void displayDeviceQueues(VulkanDeviceInfo *device); void displayDeviceSurfaceInfo(VulkanDeviceInfo &device); - void displayGlobalLayers(QTreeWidget *tree); - void displayGlobalExtensions(); + void displayInstanceLayers(); + void displayInstanceExtensions(); + void setReportState(ReportState state); private Q_SLOTS: void slotClose(); void slotBrowseDatabase(); void slotDisplayOnlineReport(); - void slotRefresh(); void slotAbout(); void slotComboBoxGPUIndexChanged(int index); void slotSaveReport(); void slotUploadReport(); void slotSettings(); - void slotFilterLimits(QString text); - void slotFilterFeatures(QString text); + void slotFilterPropertiesCore10(QString text); + void slotFilterPropertiesCore11(QString text); + void slotFilterPropertiesCore12(QString text); + void slotFilterPropertiesExtensions(QString text); + void slotFilterFeatures(QString text); + void slotFilterFeaturesCore11(QString text); + void slotFilterFeaturesCore12(QString text); + void slotFilterFeaturesExtensions(QString text); void slotFilterExtensions(QString text); void slotFilterFormats(QString text); void slotComboTabChanged(int index); diff --git a/vulkancapsviewer.qrc b/vulkancapsviewer.qrc index 1233a77..14fabae 100644 --- a/vulkancapsviewer.qrc +++ b/vulkancapsviewer.qrc @@ -1,18 +1,18 @@ - - Resources/vulkan48.png - Resources/device48.png - Resources/refresh16.png - Resources/compare24.png - Resources/db24.png - Resources/gpu32.png - Resources/save48.png - Resources/close48.png - Resources/about48.png - Resources/browse48.png - Resources/settings48.png - Resources/upload48.png - Resources/refresh48.png - Resources/vulkan32.png - + + Resources/vulkan32.png + Resources/vulkan48.png + Resources/device48.png + Resources/refresh16.png + Resources/compare24.png + Resources/db24.png + Resources/gpu32.png + Resources/save48.png + Resources/close48.png + Resources/about48.png + Resources/browse48.png + Resources/settings48.png + Resources/upload48.png + Resources/refresh48.png + diff --git a/vulkancapsviewer.ui b/vulkancapsviewer.ui index 4da6481..69285ef 100644 --- a/vulkancapsviewer.ui +++ b/vulkancapsviewer.ui @@ -19,7 +19,7 @@ - Vulkan Hardware Capability Viewer 1.0 (beta) + Vulkan Hardware Capability Viewer false @@ -41,6 +41,15 @@ QTabWidget::tab-bar { alignment: center; } +QTabBar::tab:disabled { + min-width: 0 !important; + width: 0 !important; + height: 0 !important; + margin: 0 !important; + padding: 0 !important; + border: none !important; +} + QTabBar::tab { min-width: 8ex; padding: 8px 16px; @@ -82,6 +91,10 @@ QTreeView::item { QTreeView { font-size: 12px; +} + +QTreeView { + alternate-background-color: #F6F6F6; } @@ -370,7 +383,7 @@ QTreeView { - + background-color: rgb(68, 68, 68); @@ -498,7 +511,7 @@ height: 24px; - Device Info + Properties 16 @@ -508,7 +521,7 @@ height: 24px; - Device Info + Properties @@ -516,11 +529,6 @@ height: 24px; Features - - - Limits - - Extensions @@ -531,11 +539,6 @@ height: 24px; Formats - - - Layers - - Queue Families @@ -553,7 +556,7 @@ height: 24px; - Vulkan Instance + Instance @@ -584,160 +587,548 @@ height: 24px; false - + - Device + Properties - + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - - QTreeView::item { height: 1.25em; } - - - QAbstractItemView::NoEditTriggers - - - true - - - true + + + 0 - - 200 - - - true - - - - key - - - - - value - - + + + Core 1.0 + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + + + + Core 1.1 + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + + + + Core 1.2 + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + + + + Extensions + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + - + Features - - - - - - 0 - - - 2 - - - 0 - - - 2 - - - - - - 0 - 0 - - - - - - - - Filter : - - - - - - - - - - QTreeView::item { height: 1.25em; } - - - QAbstractItemView::NoEditTriggers - - - true - - - false - - - 200 - - - - - - - - Limits - - - - - - - 0 - - - 2 - - - 0 - - - 2 - - - - - Filter : - - - - - - - - 0 - 0 - - - - - - - + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - - - QTreeView::item { height: 1.25em; } - - - QAbstractItemView::NoEditTriggers - - - true - - - true + + + 0 + + + Core 1.0 + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + + + + Core 1.1 + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + + + + Core 1.2 + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + + + + Extensions + + + + + + + 0 + + + 2 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + + + + Filter : + + + + + + + + + + QTreeView::item { height: 1.25em; } + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + 200 + + + + + @@ -866,57 +1257,6 @@ height: 24px; - - - Layers - - - - - - QTreeView::item { height: 1.25em; } - - - QAbstractItemView::NoEditTriggers - - - true - - - 200 - - - true - - - - Name - - - - - Specification - - - - - Impementation - - - - - Extension count - - - - - Description - - - - - - Queue families @@ -1036,7 +1376,7 @@ height: 24px; - Vulkan + Instance @@ -1046,7 +1386,7 @@ height: 24px; 0 - 5 + 0 0 @@ -1163,7 +1503,7 @@ height: 24px; 0 0 927 - 20 + 21 diff --git a/vulkandatabase.cpp b/vulkandatabase.cpp index 50d6101..db0ead7 100644 --- a/vulkandatabase.cpp +++ b/vulkandatabase.cpp @@ -1,10 +1,10 @@ /* * -* OpenGL hardware capability viewer and database +* Vulkan hardware capability viewer and database * -* Server http communication class implementation +* Database communication class implementation * -* Copyright (C) 2011-2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,14 +33,6 @@ QString VulkanDatabase::username = ""; QString VulkanDatabase::password = ""; QString VulkanDatabase::databaseUrl = "http://vulkan.gpuinfo.org/"; -VulkanDatabase::VulkanDatabase() -{ -} - -VulkanDatabase::~VulkanDatabase() -{ -} - /// /// Checks if the online database can be reached /// @@ -48,7 +40,7 @@ bool VulkanDatabase::checkServerConnection() { manager = new QNetworkAccessManager(nullptr); - QUrl qurl(QString::fromStdString(getBaseUrl() + "/services/serverstate.php")); + QUrl qurl(databaseUrl + "api/v3/serverstate.php"); if (username != "" && password != "") { @@ -86,7 +78,7 @@ string VulkanDatabase::httpGet(string url) QEventLoop loop; connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - loop.exec(); + loop.exec(QEventLoop::ExcludeUserInputEvents); if (reply->error() == QNetworkReply::NoError) { @@ -135,7 +127,7 @@ string VulkanDatabase::httpPost(string url, string data) QEventLoop loop; connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - loop.exec(); + loop.exec(QEventLoop::ExcludeUserInputEvents); if (reply->error() == QNetworkReply::NoError) { @@ -171,70 +163,107 @@ int VulkanDatabase::getReportId(VulkanDeviceInfo device) { string reply; stringstream urlss; - urlss << getBaseUrl() << "/services/getreportid.php?" + urlss << databaseUrl.toStdString() << "api/v3/getreportid.php?" << "devicename=" << device.props.deviceName << "&driverversion=" << device.getDriverVersion() << "&osname=" << device.os.name << "&osversion=" << device.os.version << "&osarchitecture=" << device.os.architecture << "&apiversion=" << vulkanResources::versionToString(device.props.apiVersion); +#ifdef __ANDROID__ + // Compare against platform info on Android, as driver version and device name (which is just the GPU name on android) are not sufficient to identify a single report + urlss << "&androidproductmodel=" << device.platformdetails["android.ProductModel"]; + urlss << "&androidproductmanufacturer=" << device.platformdetails["android.ProductManufacturer"]; +#endif; string url = encodeUrl(urlss.str()); reply = httpGet(url); return (!reply.empty()) ? atoi(reply.c_str()) : -1; } -/// /// Checks if the report is present in the online database -/// -bool VulkanDatabase::checkReportPresent(VulkanDeviceInfo device) -{ - int reportID = getReportId(device); - return (reportID > -1) ? true : false; -} - -/// -/// Fechtes an xml with all report data from the online database -/// -/// id of the report to get the report xml for -/// xml string -string VulkanDatabase::fetchReport(int reportId) +bool VulkanDatabase::checkReportPresent(VulkanDeviceInfo device, int& reportId) { - string reportXml; - stringstream urlss; - urlss << getBaseUrl() << "services/getreport.php?id=" << reportId; - reportXml = httpGet(urlss.str()); - return reportXml; + reportId = getReportId(device); + return (reportId > -1) ? true : false; } -/// /// Posts the given xml for a report to the database -/// -/// todo string VulkanDatabase::postReport(string xml) { string httpReply; stringstream urlss; - urlss << getBaseUrl() << "api/v2/uploadreport.php"; + urlss << databaseUrl.toStdString() << "api/v3/uploadreport.php"; httpReply = httpPost(urlss.str(), xml); return httpReply; } -/// -/// Posts the given url to the db report update script -/// -/// Coma separated list of updated caps -string VulkanDatabase::postReportForUpdate(string xml) +// Checks if the report stored in the database can be updated with missing data from the local report +bool VulkanDatabase::checkCanUpdateReport(VulkanDeviceInfo& device, int reportId) { - string httpReply; - stringstream urlss; - urlss << getBaseUrl() << "services/updatereport.php"; - httpReply = httpPost(urlss.str(), xml); - return httpReply; + manager = new QNetworkAccessManager(nullptr); + QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpPart jsonPart; + jsonPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"data\"; filename=\"update_check_report.json\"")); + QJsonDocument doc(device.toJson("", "")); + jsonPart.setBody(doc.toJson()); + multiPart->append(jsonPart); + QUrl qurl(databaseUrl + "api/v3/checkcanupdatereport.php?reportid=" + QString::number(reportId)); + QNetworkRequest request(qurl); + QNetworkReply* reply = manager->post(request, multiPart); + multiPart->setParent(reply); + QEventLoop loop; + connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(QEventLoop::ExcludeUserInputEvents); + bool result = false; + if (reply->error() == QNetworkReply::NoError) + { + QJsonDocument response = QJsonDocument::fromJson(reply->readAll()); + bool canUpdate = response.isObject() ? response.object()["canupdate"].toBool() : false; + result = canUpdate; + } + else + { + QString err(reply->errorString()); + result = false; + } + delete(manager); + return result; } - -string VulkanDatabase::getBaseUrl() +// Upload the current report for updating an existing report +bool VulkanDatabase::postReportForUpdate(VulkanDeviceInfo &device, int reportId, QString &updateLog) { - return databaseUrl.toStdString(); + manager = new QNetworkAccessManager(nullptr); + QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpPart jsonPart; + jsonPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"data\"; filename=\"update_report.json\"")); + QJsonDocument doc(device.toJson("", "")); + jsonPart.setBody(doc.toJson()); + multiPart->append(jsonPart); + QUrl qurl(databaseUrl + "api/v3/updatereport.php?reportid=" + QString::number(reportId)); + QNetworkRequest request(qurl); + QNetworkReply* reply = manager->post(request, multiPart); + multiPart->setParent(reply); + QEventLoop loop; + connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(QEventLoop::ExcludeUserInputEvents); + bool result = false; + if (reply->error() == QNetworkReply::NoError) + { + QJsonDocument response = QJsonDocument::fromJson(reply->readAll()); + if (response.isObject() && response.object()["log"].isArray()) { + QJsonArray logArray = response.object()["log"].toArray(); + foreach(const QJsonValue logEntry, logArray) { + updateLog += logEntry.toString() + "\n"; + } + } + result = true; + } + else + { + QString err(reply->errorString()); + result = false; + } + delete(manager); + return result; } - diff --git a/vulkandatabase.h b/vulkandatabase.h index acb1fa0..e1d6243 100644 --- a/vulkandatabase.h +++ b/vulkandatabase.h @@ -4,7 +4,7 @@ * * Database communication class implementation * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -49,13 +49,10 @@ class VulkanDatabase : static QString password; static QString databaseUrl; int getReportId(VulkanDeviceInfo device); - bool checkReportPresent(VulkanDeviceInfo device); + bool checkReportPresent(VulkanDeviceInfo device, int &reportId); + bool checkCanUpdateReport(VulkanDeviceInfo &device, int reportId); bool checkServerConnection(); - string getBaseUrl(); - string fetchReport(int reportId); string postReport(string xml); - string postReportForUpdate(string xml); - VulkanDatabase(); - ~VulkanDatabase(); + bool postReportForUpdate(VulkanDeviceInfo &device, int reportId, QString &updateLog); }; diff --git a/vulkanresources.h b/vulkanresources.h index 7c0e89b..6aa982c 100644 --- a/vulkanresources.h +++ b/vulkanresources.h @@ -4,7 +4,7 @@ * * Helpers converting Vulkan entities to strings * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2015-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,9 +31,9 @@ #include #include +#include #include "vulkan/vulkan.h" - namespace vulkanResources { template inline std::string toHexString(const Number number) @@ -118,7 +118,7 @@ namespace vulkanResources { STR(VIRTUAL_GPU); STR(CPU); #undef STR - default: return "UNKNOWN_DEVICE_TYPE (" + toHexString(type) + ")"; + default: return "UNKNOWN_DEVICE_TYPE (" + toHexString(type) + ")"; } } @@ -160,7 +160,7 @@ namespace vulkanResources { STR(ERROR_INVALID_DEVICE_ADDRESS_EXT); STR(ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT); #undef STR - default: return "UNKNOWN_RESULT (" + toHexString(result) + ")"; + default: return "UNKNOWN_RESULT (" + toHexString(result) + ")"; } } @@ -389,7 +389,7 @@ namespace vulkanResources { STR(G16_B16R16_2PLANE_422_UNORM); STR(G16_B16_R16_3PLANE_444_UNORM); #undef STR - default: return "UNKNOWN_ENUM (" + toHexString(format) + ")"; + default: return "UNKNOWN_ENUM (" + toHexString(format) + ")"; } } @@ -405,7 +405,7 @@ namespace vulkanResources { STR(SHARED_DEMAND_REFRESH); STR(SHARED_CONTINUOUS_REFRESH); #undef STR - default: return "UNKNOWN_ENUM (" + toHexString(presentMode) + ")"; + default: return "UNKNOWN_ENUM (" + toHexString(presentMode) + ")"; } } @@ -431,13 +431,13 @@ namespace vulkanResources { STR(EXTENDED_SRGB_NONLINEAR_EXT); STR(DISPLAY_NATIVE_AMD); #undef STR - default: return "UNKNOWN_ENUM (" + toHexString(colorSpace) + ")"; + default: return "UNKNOWN_ENUM (" + toHexString(colorSpace) + ")"; } } inline std::string driverIdKHRString(const VkDriverIdKHR driverId) { - switch(driverId){ + switch (driverId) { #define STR(r) case VK_DRIVER_ID_##r##_KHR: return #r STR(AMD_PROPRIETARY); STR(AMD_OPEN_SOURCE); @@ -452,13 +452,13 @@ namespace vulkanResources { STR(GGP_PROPRIETARY); STR(BROADCOM_PROPRIETARY); #undef STR - default: return "UNKNOWN_ENUM (" + toHexString(driverId) + ")"; + default: return "UNKNOWN_ENUM (" + toHexString(driverId) + ")"; }; } inline std::string imageUsageBitString(const VkImageUsageFlagBits usageBit) { - switch(usageBit){ + switch (usageBit) { #define STR(r) case VK_IMAGE_USAGE_##r: return #r STR(TRANSFER_SRC_BIT); STR(TRANSFER_DST_BIT); @@ -471,13 +471,13 @@ namespace vulkanResources { STR(SHADING_RATE_IMAGE_BIT_NV); STR(FRAGMENT_DENSITY_MAP_BIT_EXT); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(usageBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(usageBit) + ")"; }; } inline std::string surfaceTransformBitString(const VkSurfaceTransformFlagBitsKHR transformBit) { - switch(transformBit){ + switch (transformBit) { #define STR(r) case VK_SURFACE_TRANSFORM_##r##_KHR: return #r STR(IDENTITY_BIT); STR(ROTATE_90_BIT); @@ -489,26 +489,26 @@ namespace vulkanResources { STR(HORIZONTAL_MIRROR_ROTATE_270_BIT); STR(INHERIT_BIT); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(transformBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(transformBit) + ")"; }; } inline std::string compositeAlphaBitString(const VkCompositeAlphaFlagBitsKHR alphaBit) { - switch(alphaBit){ + switch (alphaBit) { #define STR(r) case VK_COMPOSITE_ALPHA_##r##_KHR: return #r STR(OPAQUE_BIT); STR(PRE_MULTIPLIED_BIT); STR(POST_MULTIPLIED_BIT); STR(INHERIT_BIT); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(alphaBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(alphaBit) + ")"; }; } inline std::string memoryPropBitString(const VkMemoryPropertyFlagBits memoryPropBit) { - switch(memoryPropBit){ + switch (memoryPropBit) { #define STR(r) case VK_MEMORY_PROPERTY_##r: return #r STR(DEVICE_LOCAL_BIT); STR(HOST_VISIBLE_BIT); @@ -519,24 +519,24 @@ namespace vulkanResources { STR(DEVICE_COHERENT_BIT_AMD); STR(DEVICE_UNCACHED_BIT_AMD); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(memoryPropBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(memoryPropBit) + ")"; }; } inline std::string memoryHeapBitString(const VkMemoryPropertyFlagBits heapBit) { - switch(heapBit){ + switch (heapBit) { #define STR(r) case VK_MEMORY_HEAP_##r: return #r STR(DEVICE_LOCAL_BIT); STR(MULTI_INSTANCE_BIT); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(heapBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(heapBit) + ")"; }; } inline std::string queueBitString(const VkQueueFlagBits queueBit) { - switch(queueBit){ + switch (queueBit) { #define STR(r) case VK_QUEUE_##r: return #r STR(GRAPHICS_BIT); STR(COMPUTE_BIT); @@ -544,13 +544,13 @@ namespace vulkanResources { STR(SPARSE_BINDING_BIT); STR(PROTECTED_BIT); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(queueBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(queueBit) + ")"; }; } inline std::string subgroupFeatureBitString(const VkSubgroupFeatureFlagBits subgroupBit) { - switch(subgroupBit){ + switch (subgroupBit) { #define STR(r) case VK_SUBGROUP_FEATURE_##r: return #r STR(BASIC_BIT); STR(VOTE_BIT); @@ -562,13 +562,13 @@ namespace vulkanResources { STR(QUAD_BIT); STR(PARTITIONED_BIT_NV); #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(subgroupBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(subgroupBit) + ")"; }; } inline std::string shaderStagesBitString(const VkShaderStageFlagBits stageBit) { - switch(stageBit){ + switch (stageBit) { #define STR(r) case VK_SHADER_STAGE_##r: return #r STR(VERTEX_BIT); STR(TESSELLATION_CONTROL_BIT); @@ -587,7 +587,7 @@ namespace vulkanResources { STR(MESH_BIT_NV); STR(ALL); // technically not a single bit, but it should work here #undef STR - default: return "UNKNOWN_FLAG (" + toHexString(stageBit) + ")"; + default: return "UNKNOWN_FLAG (" + toHexString(stageBit) + ")"; }; } @@ -606,7 +606,7 @@ namespace vulkanResources { inline std::string conformanceVersionKHRString(const VkConformanceVersionKHR& conformanceVersion) { - const std::vector versionAsList = {conformanceVersion.major, conformanceVersion.minor, conformanceVersion.subminor, conformanceVersion.patch}; + const std::vector versionAsList = { conformanceVersion.major, conformanceVersion.minor, conformanceVersion.subminor, conformanceVersion.patch }; std::vector versionAsStringList; const auto u8ToString = [](const uint8_t num) { return std::to_string(static_cast(num)); @@ -615,4 +615,87 @@ namespace vulkanResources { return joinString('.', versionAsStringList); } + + // Values to be displayed as sample counts + const QSet sampleFlagsValueNames = { + "framebufferColorSampleCounts", + "framebufferDepthSampleCounts", + "framebufferStencilSampleCounts", + "framebufferNoAttachmentsSampleCounts", + "sampledImageColorSampleCounts", + "sampledImageIntegerSampleCounts", + "sampledImageDepthSampleCounts", + "sampledImageStencilSampleCounts", + "storageImageSampleCounts", + // Core 1.2 + "framebufferIntegerColorSampleCounts" + }; + + // Values to be displayed as booleans + const QSet boolValueNames = { + "timestampComputeAndGraphics", + "strictLines", + "standardSampleLocations", + // Core 1.1 + "deviceLUIDValid", + "subgroupQuadOperationsInAllStages", + "protectedNoFault", + // Core 1.2 + "shaderSignedZeroInfNanPreserveFloat16", + "shaderSignedZeroInfNanPreserveFloat32", + "shaderSignedZeroInfNanPreserveFloat64", + "shaderDenormPreserveFloat16", + "shaderDenormPreserveFloat32", + "shaderDenormPreserveFloat64", + "shaderDenormFlushToZeroFloat16", + "shaderDenormFlushToZeroFloat32", + "shaderDenormFlushToZeroFloat64", + "shaderRoundingModeRTEFloat16", + "shaderRoundingModeRTEFloat32", + "shaderRoundingModeRTEFloat64", + "shaderRoundingModeRTZFloat16", + "shaderRoundingModeRTZFloat32", + "shaderRoundingModeRTZFloat64", + "shaderUniformBufferArrayNonUniformIndexingNative", + "shaderSampledImageArrayNonUniformIndexingNative", + "shaderStorageBufferArrayNonUniformIndexingNative", + "shaderStorageImageArrayNonUniformIndexingNative", + "shaderInputAttachmentArrayNonUniformIndexingNative", + "robustBufferAccessUpdateAfterBind", + "quadDivergentImplicitLod", + "independentResolveNone", + "independentResolve", + "filterMinmaxSingleComponentFormats", + "filterMinmaxImageComponentMapping" + }; + + // Values to be displayed as UUIds + const QSet uuidValueNames = { + "deviceUUID", + // Core 1.1 + "driverUUID", + "deviceLUID" + }; + + // Values to be displayed as hex + const QSet hexValueNames = { + "vendorID", + "deviceID" + }; + + // Values not to be displayd + const QSet skipValueNames = { + "apiVersion", + "deviceType", + "driverVersion", + "headerversion" + }; + + // Key replacement for display + const QMap replaceKeyNames = { + { "apiVersionText", "apiVersion" }, + { "deviceTypeText", "driverVersion" }, + { "driverVersionText", "driverVersion" }, + }; + }; diff --git a/vulkansurfaceinfo.hpp b/vulkansurfaceinfo.hpp index 36624d3..082ed7c 100644 --- a/vulkansurfaceinfo.hpp +++ b/vulkansurfaceinfo.hpp @@ -4,7 +4,7 @@ * * Surface information class * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2020 by Sascha Willems (www.saschawillems.de) * * This code is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -43,9 +43,7 @@ struct VulkanSurfaceInfo return; } - //todo: error checking - VkResult vkRes; - vkRes = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &capabilities); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &capabilities); // Present modes uint32_t presentModeCount; @@ -54,7 +52,7 @@ struct VulkanSurfaceInfo presentModes.resize(presentModeCount); if (presentModeCount > 0) { - vkRes = vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, presentModes.data()); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, presentModes.data()); } } @@ -65,7 +63,7 @@ struct VulkanSurfaceInfo formats.resize(surfaceFormatCount); if (surfaceFormatCount > 0) { - vkRes = vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &surfaceFormatCount, formats.data()); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &surfaceFormatCount, formats.data()); } } }