Let Skia automatically enable extensions and features

Using the new VulkanPreferredFeatures API.

Bug: b/422204178
Flag: com.android.graphics.surfaceflinger.flags.graphite_renderengine
Change-Id: I60a44360bf093ff43d3265ff11f98345c2a4c190
diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp
index ddf1735..c6c2160 100644
--- a/libs/renderengine/skia/VulkanInterface.cpp
+++ b/libs/renderengine/skia/VulkanInterface.cpp
@@ -26,6 +26,7 @@
 #include <utils/Timers.h>
 
 #include <cinttypes>
+#include <cstring>
 #include <sstream>
 
 namespace android {
@@ -41,7 +42,7 @@
     backendContext.fGraphicsQueueIndex = mQueueIndex;
     backendContext.fMaxAPIVersion = mApiVersion;
     backendContext.fVkExtensions = &mVulkanExtensions;
-    backendContext.fDeviceFeatures2 = mPhysicalDeviceFeatures2;
+    backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
     backendContext.fGetProc = mGrGetProc;
     backendContext.fProtectedContext = mIsProtected ? Protected::kYes : Protected::kNo;
     backendContext.fDeviceLostContext = this; // VulkanInterface is long-lived
@@ -228,7 +229,7 @@
     uint32_t instanceVersion;
     VK_CHECK(vkEnumerateInstanceVersion(&instanceVersion));
 
-    if (instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
+    if (instanceVersion < VK_API_VERSION_1_1) {
         BAIL("Vulkan instance API version %" PRIu32 ".%" PRIu32 ".%" PRIu32 " < 1.1.0",
              VK_VERSION_MAJOR(instanceVersion), VK_VERSION_MINOR(instanceVersion),
              VK_VERSION_PATCH(instanceVersion));
@@ -236,7 +237,7 @@
 
     const VkApplicationInfo appInfo = {
             VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "surfaceflinger", 0, "android platform", 0,
-            VK_MAKE_VERSION(1, 1, 0),
+            VK_API_VERSION_1_1,
     };
 
     VK_GET_PROC(EnumerateInstanceExtensionProperties);
@@ -248,10 +249,18 @@
                                                     instanceExtensions.data()));
     std::vector<const char*> enabledInstanceExtensionNames;
     enabledInstanceExtensionNames.reserve(instanceExtensions.size());
-    mInstanceExtensionNames.reserve(instanceExtensions.size());
     for (const auto& instExt : instanceExtensions) {
         enabledInstanceExtensionNames.push_back(instExt.extensionName);
-        mInstanceExtensionNames.push_back(instExt.extensionName);
+    }
+
+    // Let Skia enable instance extensions.
+    mVulkanFeatures.init(appInfo.apiVersion);
+    mVulkanFeatures.addToInstanceExtensions(instanceExtensions.data(), instanceExtensions.size(),
+                                            enabledInstanceExtensionNames);
+
+    mInstanceExtensionNames.reserve(enabledInstanceExtensionNames.size());
+    for (const char* instExt : enabledInstanceExtensionNames) {
+        mInstanceExtensionNames.push_back(instExt);
     }
 
     const VkInstanceCreateInfo instanceCreateInfo = {
@@ -407,10 +416,48 @@
 
     std::vector<const char*> enabledDeviceExtensionNames;
     enabledDeviceExtensionNames.reserve(deviceExtensions.size());
-    mDeviceExtensionNames.reserve(deviceExtensions.size());
     for (const auto& devExt : deviceExtensions) {
         enabledDeviceExtensionNames.push_back(devExt.extensionName);
-        mDeviceExtensionNames.push_back(devExt.extensionName);
+    }
+
+    mPhysicalDeviceFeatures2 = {};
+    mPhysicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+    void** tailPnext = &mPhysicalDeviceFeatures2.pNext;
+
+    if (protectedContent) {
+        mProtectedMemoryFeatures = {};
+        mProtectedMemoryFeatures.sType =
+                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
+        *tailPnext = &mProtectedMemoryFeatures;
+        tailPnext = &mProtectedMemoryFeatures.pNext;
+    }
+
+    for (const VkExtensionProperties& ext : deviceExtensions) {
+        if (strcmp(ext.extensionName, VK_EXT_DEVICE_FAULT_EXTENSION_NAME) == 0) {
+            mDeviceFaultFeatures = {};
+            mDeviceFaultFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
+            *tailPnext = &mDeviceFaultFeatures;
+            tailPnext = &mDeviceFaultFeatures.pNext;
+
+            break;
+        }
+    }
+
+    // Let Skia add features to be queried.
+    mVulkanFeatures.addFeaturesToQuery(deviceExtensions.data(), deviceExtensions.size(),
+                                       mPhysicalDeviceFeatures2);
+
+    vkGetPhysicalDeviceFeatures2(physicalDevice, &mPhysicalDeviceFeatures2);
+    // Robust buffer access can reduce performance on some platforms. It is not needed by
+    // RenderEngine.
+    mPhysicalDeviceFeatures2.features.robustBufferAccess = VK_FALSE;
+
+    // Let Skia enable extensions and features.
+    mVulkanFeatures.addFeaturesToEnable(enabledDeviceExtensionNames, mPhysicalDeviceFeatures2);
+
+    mDeviceExtensionNames.reserve(enabledDeviceExtensionNames.size());
+    for (const char* devExt : enabledDeviceExtensionNames) {
+        mDeviceExtensionNames.push_back(devExt);
     }
 
     mVulkanExtensions.init(sGetProc, instance, physicalDevice, enabledInstanceExtensionNames.size(),
@@ -421,40 +468,7 @@
         BAIL("Vulkan driver doesn't support external semaphore fd");
     }
 
-    mPhysicalDeviceFeatures2 = new VkPhysicalDeviceFeatures2;
-    mPhysicalDeviceFeatures2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
-    mPhysicalDeviceFeatures2->pNext = nullptr;
-
-    mSamplerYcbcrConversionFeatures = new VkPhysicalDeviceSamplerYcbcrConversionFeatures;
-    mSamplerYcbcrConversionFeatures->sType =
-            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
-    mSamplerYcbcrConversionFeatures->pNext = nullptr;
-
-    mPhysicalDeviceFeatures2->pNext = mSamplerYcbcrConversionFeatures;
-    void** tailPnext = &mSamplerYcbcrConversionFeatures->pNext;
-
-    if (protectedContent) {
-        mProtectedMemoryFeatures = new VkPhysicalDeviceProtectedMemoryFeatures;
-        mProtectedMemoryFeatures->sType =
-                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
-        mProtectedMemoryFeatures->pNext = nullptr;
-        *tailPnext = mProtectedMemoryFeatures;
-        tailPnext = &mProtectedMemoryFeatures->pNext;
-    }
-
-    if (mVulkanExtensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) {
-        mDeviceFaultFeatures = new VkPhysicalDeviceFaultFeaturesEXT;
-        mDeviceFaultFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
-        mDeviceFaultFeatures->pNext = nullptr;
-        *tailPnext = mDeviceFaultFeatures;
-        tailPnext = &mDeviceFaultFeatures->pNext;
-    }
-
-    vkGetPhysicalDeviceFeatures2(physicalDevice, mPhysicalDeviceFeatures2);
-    // Looks like this would slow things down and we can't depend on it on all platforms
-    mPhysicalDeviceFeatures2->features.robustBufferAccess = VK_FALSE;
-
-    if (protectedContent && !mProtectedMemoryFeatures->protectedMemory) {
+    if (protectedContent && !mProtectedMemoryFeatures.protectedMemory) {
         BAIL("Protected memory not supported");
     }
 
@@ -486,7 +500,7 @@
 
     const VkDeviceCreateInfo deviceInfo = {
             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-            mPhysicalDeviceFeatures2,
+            &mPhysicalDeviceFeatures2,
             0,
             1,
             &queueInfo,
@@ -563,26 +577,6 @@
         mInstance = VK_NULL_HANDLE;
     }
 
-    // Optional features that can be deleted directly.
-    // TODO: b/293371537 - This section should likely be improved to walk the pNext chain of
-    // mPhysicalDeviceFeatures2 and free everything like HWUI's VulkanManager.
-    if (mProtectedMemoryFeatures) {
-        delete mProtectedMemoryFeatures;
-        mProtectedMemoryFeatures = nullptr;
-    }
-    if (mSamplerYcbcrConversionFeatures) {
-        delete mSamplerYcbcrConversionFeatures;
-        mSamplerYcbcrConversionFeatures = nullptr;
-    }
-    if (mPhysicalDeviceFeatures2) {
-        delete mPhysicalDeviceFeatures2;
-        mPhysicalDeviceFeatures2 = nullptr;
-    }
-    if (mDeviceFaultFeatures) {
-        delete mDeviceFaultFeatures;
-        mDeviceFaultFeatures = nullptr;
-    }
-
     // Misc. fields that can be trivially reset without special deletion:
     mInitialized = false;
     mIsOwned = false;
@@ -595,6 +589,10 @@
     mIsProtected = false;
     mIsRealtimePriority = false;
 
+    mPhysicalDeviceFeatures2 = {};
+    mProtectedMemoryFeatures = {};
+    mDeviceFaultFeatures = {};
+
     mFuncs = VulkanFuncs();
 
     mInstanceExtensionNames.clear();
diff --git a/libs/renderengine/skia/VulkanInterface.h b/libs/renderengine/skia/VulkanInterface.h
index 1de8b6f..1211519 100644
--- a/libs/renderengine/skia/VulkanInterface.h
+++ b/libs/renderengine/skia/VulkanInterface.h
@@ -18,6 +18,7 @@
 
 #include <include/gpu/vk/VulkanBackendContext.h>
 #include <include/gpu/vk/VulkanExtensions.h>
+#include <include/gpu/vk/VulkanPreferredFeatures.h>
 #include <include/gpu/vk/VulkanTypes.h>
 
 #include <vulkan/vulkan.h>
@@ -82,10 +83,10 @@
     int mQueueIndex = 0;
     uint32_t mApiVersion = 0;
     skgpu::VulkanExtensions mVulkanExtensions;
-    VkPhysicalDeviceFeatures2* mPhysicalDeviceFeatures2 = nullptr;
-    VkPhysicalDeviceSamplerYcbcrConversionFeatures* mSamplerYcbcrConversionFeatures = nullptr;
-    VkPhysicalDeviceProtectedMemoryFeatures* mProtectedMemoryFeatures = nullptr;
-    VkPhysicalDeviceFaultFeaturesEXT* mDeviceFaultFeatures = nullptr;
+    skgpu::VulkanPreferredFeatures mVulkanFeatures;
+    VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2 = {};
+    VkPhysicalDeviceProtectedMemoryFeatures mProtectedMemoryFeatures = {};
+    VkPhysicalDeviceFaultFeaturesEXT mDeviceFaultFeatures = {};
     skgpu::VulkanGetProc mGrGetProc = nullptr;
     bool mIsProtected = false;
     bool mIsRealtimePriority = false;