diff --git a/.gitignore b/.gitignore index 5477809..6e1852f 100644 --- a/.gitignore +++ b/.gitignore @@ -230,3 +230,11 @@ redist/*.zip devdatabase.ini /db.ini + +android-build/** +tools/*.zip +tools/*.dmg +tools/*.apk +tools/*.AppImage + +log.txt \ No newline at end of file diff --git a/VulkanContext.h b/VulkanContext.h index ac64bfb..468034d 100644 --- a/VulkanContext.h +++ b/VulkanContext.h @@ -2,7 +2,7 @@ * * Vulkan hardware capability viewer * -* Copyright (C) 2016-2022 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2023 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,6 +31,7 @@ struct VulkanContext PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = nullptr; PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = nullptr; PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR = nullptr; + PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2 = nullptr; }; extern VulkanContext vulkanContext; diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 849fd43..65fdd48 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/vulkanDeviceInfo.cpp b/vulkanDeviceInfo.cpp index ba1ae0a..22ae4c7 100644 --- a/vulkanDeviceInfo.cpp +++ b/vulkanDeviceInfo.cpp @@ -101,37 +101,76 @@ void VulkanDeviceInfo::readLayers() void VulkanDeviceInfo::readSupportedFormats() { + // A note before adding new formats in here: In order for them to be properly displayed, formats also need to be added to the database + assert(device != NULL); - qInfo() << "Reading formats"; - // Base formats - int32_t firstFormat = VK_FORMAT_R4G4_UNORM_PACK8; - int32_t lastFormat = VK_FORMAT_ASTC_12x12_SRGB_BLOCK; + if (hasFormatFeatureFlags2) { + qInfo() << "Reading formats using VK_KHR_format_feature_flags2"; + } else { + qInfo() << "Reading formats"; + } + + // Generate format listing from core and supported extensions + std::vector formatList{}; + + // Core formats + uint64_t firstFormat = VK_FORMAT_R4G4_UNORM_PACK8; + uint64_t lastFormat = VK_FORMAT_ASTC_12x12_SRGB_BLOCK; for (int32_t format = firstFormat; format <= lastFormat; format++) { - VulkanFormatInfo formatInfo = {}; - formatInfo.format = (VkFormat)format; - vkGetPhysicalDeviceFormatProperties(device, formatInfo.format, &formatInfo.properties); - formatInfo.supported = (formatInfo.properties.linearTilingFeatures != 0) || (formatInfo.properties.optimalTilingFeatures != 0) || (formatInfo.properties.bufferFeatures != 0); - formats.push_back(formatInfo); + formatList.push_back(format); } + // VK_KHR_sampler_ycbcr_conversion if (extensionSupported(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME)) { for (int32_t format = VK_FORMAT_G8B8G8R8_422_UNORM; format < VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM; format++) { - VulkanFormatInfo formatInfo = {}; - formatInfo.format = (VkFormat)format; - vkGetPhysicalDeviceFormatProperties(device, formatInfo.format, &formatInfo.properties); - formatInfo.supported = (formatInfo.properties.linearTilingFeatures != 0) || (formatInfo.properties.optimalTilingFeatures != 0) || (formatInfo.properties.bufferFeatures != 0); - formats.push_back(formatInfo); + formatList.push_back((VkFormat)format); } } + // VK_IMG_FORMAT_PVRTC_EXTENSION_NAME if (extensionSupported(VK_IMG_FORMAT_PVRTC_EXTENSION_NAME)) { for (int32_t format = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; format < VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG; format++) { - VulkanFormatInfo formatInfo = {}; - formatInfo.format = (VkFormat)format; - vkGetPhysicalDeviceFormatProperties(device, formatInfo.format, &formatInfo.properties); - formatInfo.supported = (formatInfo.properties.linearTilingFeatures != 0) || (formatInfo.properties.optimalTilingFeatures != 0) || (formatInfo.properties.bufferFeatures != 0); - formats.push_back(formatInfo); + formatList.push_back((VkFormat)format); + } + } + + for (auto i = 0; i < formatList.size(); i++) { + VkFormat format = (VkFormat)formatList[i]; + + VulkanFormatInfo formatInfo = {}; + formatInfo.format = (VkFormat)format; + + // Use the same data structure for both base and newer feature flag bits + // As the _flags2 also contain the base flags this will work both in the app and the database + + if (hasFormatFeatureFlags2) { + // Using VK_KHR_format_feature_flags2 + VkFormatProperties3 formatProperties3{}; + formatProperties3.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR; + + VkFormatProperties2 formatProperties2{}; + formatProperties2.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + formatProperties2.pNext = &formatProperties3; + + vulkanContext.vkGetPhysicalDeviceFormatProperties2(device, formatInfo.format, &formatProperties2); + + formatInfo.bufferFeatures = formatProperties3.bufferFeatures; + formatInfo.linearTilingFeatures = formatProperties3.linearTilingFeatures; + formatInfo.optimalTilingFeatures = formatProperties3.optimalTilingFeatures; + + formatInfo.isFeatureFlags2 = true; } + else { + VkFormatProperties formatProperties{}; + vkGetPhysicalDeviceFormatProperties(device, formatInfo.format, &formatProperties); + + formatInfo.bufferFeatures = formatProperties.bufferFeatures; + formatInfo.linearTilingFeatures = formatProperties.linearTilingFeatures; + formatInfo.optimalTilingFeatures = formatProperties.optimalTilingFeatures; + } + + formatInfo.supported = (formatInfo.linearTilingFeatures != 0) || (formatInfo.optimalTilingFeatures != 0) || (formatInfo.bufferFeatures != 0); + formats.push_back(formatInfo); } } @@ -418,12 +457,19 @@ void VulkanDeviceInfo::readPhysicalProperties() core13Properties["maxBufferSize"] = QVariant::fromValue(coreProps13.maxBufferSize).toString(); } } + + if (extensionSupported(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)) { + qInfo() << "Device supports VK_KHR_format_feature_flags2"; + hasFormatFeatureFlags2 = true; + } + + properties["hasFormatFeatureFlags2"] = hasFormatFeatureFlags2; } void VulkanDeviceInfo::readPhysicalFeatures() { assert(device != NULL); - qInfo() << "Reading physical feattures"; + qInfo() << "Reading physical features"; vkGetPhysicalDeviceFeatures(device, &deviceFeatures); features.clear(); @@ -887,9 +933,9 @@ QJsonObject VulkanDeviceInfo::toJson(QString submitter, QString comment) QJsonArray jsonFormat; jsonFormat.append((QJsonValue(format.format))); QJsonObject jsonFormatFeatures; - jsonFormatFeatures["linearTilingFeatures"] = QVariant::fromValue(format.properties.linearTilingFeatures).toString(); - jsonFormatFeatures["optimalTilingFeatures"] = QVariant::fromValue(format.properties.optimalTilingFeatures).toString(); - jsonFormatFeatures["bufferFeatures"] = QVariant::fromValue(format.properties.bufferFeatures).toString(); + jsonFormatFeatures["linearTilingFeatures"] = QVariant::fromValue(format.linearTilingFeatures).toString(); + jsonFormatFeatures["optimalTilingFeatures"] = QVariant::fromValue(format.optimalTilingFeatures).toString(); + jsonFormatFeatures["bufferFeatures"] = QVariant::fromValue(format.bufferFeatures).toString(); jsonFormatFeatures["supported"] = format.supported; jsonFormat.append(jsonFormatFeatures); jsonFormats.append(jsonFormat); diff --git a/vulkanDeviceInfo.h b/vulkanDeviceInfo.h index 2b63a7f..3f1c8c6 100644 --- a/vulkanDeviceInfo.h +++ b/vulkanDeviceInfo.h @@ -106,6 +106,7 @@ class VulkanDeviceInfo: public VulkanDeviceInfoExtensions QVariantMap core13Features; bool hasSubgroupProperties = false; bool hasFeaturModifyingTool = false; + bool hasFormatFeatureFlags2 = false; QVariantMap subgroupProperties; QVariantMap core11Properties; QVariantMap core12Properties; diff --git a/vulkanFormatInfo.hpp b/vulkanFormatInfo.hpp index 4d2060e..6feb22a 100644 --- a/vulkanFormatInfo.hpp +++ b/vulkanFormatInfo.hpp @@ -4,7 +4,7 @@ * * Layer information struct * -* Copyright (C) 2015 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2015-2024 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 @@ -27,6 +27,13 @@ struct VulkanFormatInfo { VkFormat format; - VkFormatProperties properties; + + uint64_t linearTilingFeatures; + uint64_t optimalTilingFeatures; + uint64_t bufferFeatures; + + bool isFeatureFlags2{ false }; + + // @todo: deprecate bool supported; }; \ No newline at end of file diff --git a/vulkancapsviewer.cpp b/vulkancapsviewer.cpp index b331156..e0971de 100644 --- a/vulkancapsviewer.cpp +++ b/vulkancapsviewer.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "submitDialog.h" @@ -81,7 +82,7 @@ extern "C" const char *getWorkingFolderForiOS(void); using std::to_string; -const QString VulkanCapsViewer::version = "3.42"; +const QString VulkanCapsViewer::version = "3.50"; const QString VulkanCapsViewer::reportVersion = "3.3"; OSInfo getOperatingSystem() @@ -727,6 +728,12 @@ bool VulkanCapsViewer::initVulkan() deviceProperties2Available = false; QMessageBox::warning(this, tr("Error"), "Could not get function pointer for vkGetPhysicalDeviceProperties2KHR (even though extension is enabled!)\nNew features and properties won't be displayed!"); } + // Function pointers for new format properties + vulkanContext.vkGetPhysicalDeviceFormatProperties2 = reinterpret_cast(vkGetInstanceProcAddr(vulkanContext.instance, "vkGetPhysicalDeviceFormatProperties2")); + if (!vulkanContext.vkGetPhysicalDeviceFormatProperties2) { + deviceFormatProperties2Available = false; + QMessageBox::warning(this, tr("Error"), "Could not get function pointer for vkGetPhysicalDeviceFormatProperties2 (even though extension is enabled!)\nNew format properties won't be displayed!"); + } } vulkanContext.vkGetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast(vkGetInstanceProcAddr(vulkanContext.instance, "vkGetPhysicalDeviceSurfaceSupportKHR")); @@ -1538,16 +1545,6 @@ void VulkanCapsViewer::displayOSInfo(VulkanDeviceInfo& device) } } -void addFlagModelItem(QStandardItem *parent, QString flagName, bool flag) -{ - if (flag) - { - QList flagItems; - flagItems << new QStandardItem(flagName); - parent->appendRow(flagItems); - } -} - void VulkanCapsViewer::displayDeviceFormats(VulkanDeviceInfo *device) { models.formats.clear(); @@ -1557,11 +1554,11 @@ void VulkanCapsViewer::displayDeviceFormats(VulkanDeviceInfo *device) QList rowItems; rowItems << new QStandardItem(QString::fromStdString(vulkanResources::formatString(format.format))); - std::vector featureFlags = + std::vector featureFlags = { - format.properties.linearTilingFeatures, - format.properties.optimalTilingFeatures, - format.properties.bufferFeatures + format.linearTilingFeatures, + format.optimalTilingFeatures, + format.bufferFeatures }; uint32_t i = 1; @@ -1573,75 +1570,38 @@ void VulkanCapsViewer::displayDeviceFormats(VulkanDeviceInfo *device) } rootItem->appendRow(rowItems); - - struct featureSet { - std::string name; - VkFlags flags; - }; - std::vector featureSets = - { - { "Linear tiling flags", format.properties.linearTilingFeatures }, - { "Optimal tiling flags", format.properties.optimalTilingFeatures }, - { "Buffer features flags", format.properties.bufferFeatures } + std::unordered_map featureSets = { + { "Linear tiling flags", format.linearTilingFeatures }, + { "Optimal tiling flags", format.optimalTilingFeatures }, + { "Buffer features flags", format.bufferFeatures } }; - if (format.supported) + // Always use feature2 enums, as they contain all initial enums + for (auto& featureSet : featureSets) { - for (auto& featureSet : featureSets) - { - QList flagItems; - flagItems << new QStandardItem(QString::fromStdString(featureSet.name)); + QList flagItems; + flagItems << new QStandardItem(QString::fromStdString(featureSet.first)); - if (featureSet.flags == 0) - { - QList flagItem; - flagItem << new QStandardItem("none"); - flagItems[0]->appendRow(flagItem); - } - else - { - #define ADD_FLAG(flag) \ - if (featureSet.flags & flag) \ - { \ - QList flagItem; \ - QString flagname(#flag); \ - flagname = flagname.replace("VK_FORMAT_FEATURE_", ""); \ - flagItem << new QStandardItem(flagname); \ - flagItems[0]->appendRow(flagItem); \ + if (featureSet.second == 0) + { + QList flagItem; + flagItem << new QStandardItem("none"); + flagItems[0]->appendRow(flagItem); + } + else + { + for (auto& formatFlag : vulkanResources::formatFeatureFlags2) { + if (featureSet.second & formatFlag) { + QList flagItem; + QString flagname = vulkanResources::formatFeature2String(formatFlag); + flagname = flagname.replace("VK_FORMAT_FEATURE_2_", ""); + flagItem << new QStandardItem(flagname); + flagItems[0]->appendRow(flagItem); } - - // Core - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_BLIT_SRC_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_BLIT_DST_BIT) - // 1.1 - ADD_FLAG(VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_TRANSFER_DST_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_DISJOINT_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) - - // EXT - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) - ADD_FLAG(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) } - - rowItems[0]->appendRow(flagItems); - } + + rowItems[0]->appendRow(flagItems); } } diff --git a/vulkancapsviewer.h b/vulkancapsviewer.h index 3666051..4026e3b 100644 --- a/vulkancapsviewer.h +++ b/vulkancapsviewer.h @@ -75,6 +75,7 @@ class VulkanCapsViewer : public QMainWindow std::vector instanceLayers; std::vector instanceExtensions; bool deviceProperties2Available = false; + bool deviceFormatProperties2Available = false; VulkanDatabase database; void checkReportDatabaseState(); VulkanCapsViewer(QWidget *parent = 0); diff --git a/vulkandatabase.cpp b/vulkandatabase.cpp index 93349f7..44079a3 100644 --- a/vulkandatabase.cpp +++ b/vulkandatabase.cpp @@ -4,7 +4,7 @@ * * Database communication class implementation * -* Copyright (C) 2016-2023 by Sascha Willems (www.saschawillems.de) +* Copyright (C) 2016-2024 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 @@ -140,7 +140,7 @@ bool VulkanDatabase::uploadReport(QJsonObject json, QString& message) QJsonDocument doc(json); httpPart.setBody(doc.toJson()); multiPart->append(httpPart); - QUrl qurl(databaseUrl + "api/v3/uploadreport.php"); + QUrl qurl(databaseUrl + "api/v4/uploadreport.php"); QNetworkRequest request(qurl); QNetworkReply* reply = manager->post(request, multiPart); multiPart->setParent(reply); diff --git a/vulkanresources.h b/vulkanresources.h index cd820a9..2e64918 100644 --- a/vulkanresources.h +++ b/vulkanresources.h @@ -406,6 +406,60 @@ namespace vulkanResources { return QString::fromStdString(formatString(format)); } + inline QString formatFeature2String(const VkFormatFeatureFlagBits2 feature) + { + switch (feature) + { +#define STR(r) case VK_FORMAT_FEATURE_2_##r: return #r + STR(SAMPLED_IMAGE_BIT); + STR(STORAGE_IMAGE_BIT); + STR(STORAGE_IMAGE_ATOMIC_BIT); + STR(UNIFORM_TEXEL_BUFFER_BIT); + STR(STORAGE_TEXEL_BUFFER_BIT); + STR(STORAGE_TEXEL_BUFFER_ATOMIC_BIT); + STR(VERTEX_BUFFER_BIT); + STR(COLOR_ATTACHMENT_BIT); + STR(COLOR_ATTACHMENT_BLEND_BIT); + STR(DEPTH_STENCIL_ATTACHMENT_BIT); + STR(BLIT_SRC_BIT); + STR(BLIT_DST_BIT); + STR(SAMPLED_IMAGE_FILTER_LINEAR_BIT); + STR(SAMPLED_IMAGE_FILTER_CUBIC_BIT); + STR(TRANSFER_SRC_BIT); + STR(TRANSFER_DST_BIT); + STR(SAMPLED_IMAGE_FILTER_MINMAX_BIT); + STR(MIDPOINT_CHROMA_SAMPLES_BIT); + STR(SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT); + STR(SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT); + STR(SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT); + STR(SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT); + STR(DISJOINT_BIT); + STR(COSITED_CHROMA_SAMPLES_BIT); + STR(STORAGE_READ_WITHOUT_FORMAT_BIT); + STR(STORAGE_WRITE_WITHOUT_FORMAT_BIT); + STR(SAMPLED_IMAGE_DEPTH_COMPARISON_BIT); + STR(VIDEO_DECODE_OUTPUT_BIT_KHR); + STR(VIDEO_DECODE_DPB_BIT_KHR); + STR(ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR); + STR(FRAGMENT_DENSITY_MAP_BIT_EXT); + STR(FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR); + STR(HOST_IMAGE_TRANSFER_BIT_EXT); + STR(LINEAR_COLOR_ATTACHMENT_BIT_NV); + STR(WEIGHT_IMAGE_BIT_QCOM); + STR(WEIGHT_SAMPLED_IMAGE_BIT_QCOM); + STR(BLOCK_MATCHING_BIT_QCOM); + STR(BOX_FILTER_SAMPLED_BIT_QCOM); + STR(OPTICAL_FLOW_IMAGE_BIT_NV); + STR(OPTICAL_FLOW_VECTOR_BIT_NV); + STR(OPTICAL_FLOW_COST_BIT_NV); + STR(VIDEO_ENCODE_INPUT_BIT_KHR); + STR(VIDEO_ENCODE_DPB_BIT_KHR); + +#undef STR + default: return QString::fromStdString("UNKNOWN_ENUM (" + toHexString(feature) + ")"); + } + } + inline QString imageLayoutString(const VkImageLayout imageLayout) { switch (imageLayout) @@ -798,4 +852,53 @@ namespace vulkanResources { { "driverVersionText", "driverVersion" }, }; + // Values in the 32-bit range map 1:1 to their non _2_ VK_FORMAT_FEATURE equivalents, so we can reuse this + const std::vector formatFeatureFlags2 = { + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT, + VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT, + VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT, + VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT, + VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT, + VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT, + VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT, + VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT, + VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT, + VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_FORMAT_FEATURE_2_BLIT_SRC_BIT, + VK_FORMAT_FEATURE_2_BLIT_DST_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT, + VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT, + VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT, + VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT, + VK_FORMAT_FEATURE_2_DISJOINT_BIT, + VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT, + VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT, + VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT, + VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT, + VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR, + VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR, + VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR, + VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT, + VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT, + VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV, + VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM, + VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM, + VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM, + VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM, + VK_FORMAT_FEATURE_2_OPTICAL_FLOW_IMAGE_BIT_NV, + VK_FORMAT_FEATURE_2_OPTICAL_FLOW_VECTOR_BIT_NV, + VK_FORMAT_FEATURE_2_OPTICAL_FLOW_COST_BIT_NV, +#ifdef VK_ENABLE_BETA_EXTENSIONS + VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR, + VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR, +#endif + }; + };