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());
}
}
}