libvulkan: Only load driver functions for enabled extensions

Change-Id: I4105291bd42583a10420681b729f03ecd7a91724
(cherry picked from commit 1c77ae2acda376b791932beffcb931c378e8ee36)
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index 48fc923..079352b 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -178,6 +178,8 @@
 // Global Data and Initialization
 
 hwvulkan_device_t* g_hwdevice = nullptr;
+InstanceExtensionSet g_driver_instance_extensions;
+
 void LoadVulkanHAL() {
     static const hwvulkan_module_t* module;
     int result =
@@ -195,6 +197,41 @@
         module = nullptr;
         return;
     }
+
+    VkResult vkresult;
+    uint32_t count;
+    if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
+             nullptr, &count, nullptr)) != VK_SUCCESS) {
+        ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
+              vkresult);
+        g_hwdevice->common.close(&g_hwdevice->common);
+        g_hwdevice = nullptr;
+        module = nullptr;
+        return;
+    }
+    VkExtensionProperties* extensions = static_cast<VkExtensionProperties*>(
+        alloca(count * sizeof(VkExtensionProperties)));
+    if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
+             nullptr, &count, extensions)) != VK_SUCCESS) {
+        ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
+              vkresult);
+        g_hwdevice->common.close(&g_hwdevice->common);
+        g_hwdevice = nullptr;
+        module = nullptr;
+        return;
+    }
+    ALOGV_IF(count > 0, "Driver-supported instance extensions:");
+    for (uint32_t i = 0; i < count; i++) {
+        ALOGV("  %s (v%u)", extensions[i].extensionName,
+              extensions[i].specVersion);
+        InstanceExtension id =
+            InstanceExtensionFromName(extensions[i].extensionName);
+        if (id != kInstanceExtensionCount)
+            g_driver_instance_extensions.set(id);
+    }
+    // Ignore driver attempts to support loader extensions
+    g_driver_instance_extensions.reset(kKHR_surface);
+    g_driver_instance_extensions.reset(kKHR_android_surface);
 }
 
 bool EnsureInitialized() {
@@ -244,6 +281,7 @@
 
     struct {
         VkInstance instance;
+        InstanceExtensionSet supported_extensions;
         DriverDispatchTable dispatch;
         uint32_t num_physical_devices;
     } drv;  // may eventually be an array
@@ -475,13 +513,27 @@
     VkInstanceCreateInfo driver_create_info = *create_info;
     driver_create_info.enabledLayerCount = 0;
     driver_create_info.ppEnabledLayerNames = nullptr;
-    // TODO(jessehall): We currently only enumerate the VK_KHR_surface and
-    // VK_KHR_android_surface extensions, which we don't allow drivers to
-    // support. As soon as we enumerate instance extensions supported by the
-    // driver, we should instead filter the requested extension list here to
-    // only the extensions supported by the driver.
+
+    InstanceExtensionSet enabled_extensions;
     driver_create_info.enabledExtensionCount = 0;
     driver_create_info.ppEnabledExtensionNames = nullptr;
+    size_t max_names = std::min(create_info->enabledExtensionCount,
+                                g_driver_instance_extensions.count());
+    if (max_names > 0) {
+        const char** names =
+            static_cast<const char**>(alloca(max_names * sizeof(char*)));
+        for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
+            InstanceExtension id = InstanceExtensionFromName(
+                create_info->ppEnabledExtensionNames[i]);
+            if (id != kInstanceExtensionCount &&
+                g_driver_instance_extensions[id]) {
+                names[driver_create_info.enabledExtensionCount++] =
+                    create_info->ppEnabledExtensionNames[i];
+                enabled_extensions.set(id);
+            }
+        }
+        driver_create_info.ppEnabledExtensionNames = names;
+    }
 
     result = g_hwdevice->CreateInstance(&driver_create_info, instance.alloc,
                                         &instance.drv.instance);
@@ -492,7 +544,7 @@
 
     if (!LoadDriverDispatchTable(instance.drv.instance,
                                  g_hwdevice->GetInstanceProcAddr,
-                                 instance.drv.dispatch)) {
+                                 enabled_extensions, instance.drv.dispatch)) {
         DestroyInstance_Bottom(instance.handle, allocator);
         return VK_ERROR_INITIALIZATION_FAILED;
     }
@@ -834,19 +886,22 @@
     if (layer_name) {
         GetLayerExtensions(layer_name, &extensions, &num_extensions);
     } else {
-        static const VkExtensionProperties kInstanceExtensions[] = {
-            {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
-            {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
-             VK_KHR_ANDROID_SURFACE_SPEC_VERSION}};
-        extensions = kInstanceExtensions;
-        num_extensions = sizeof(kInstanceExtensions) / sizeof(kInstanceExtensions[0]);
-
+        VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
+            alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
+        available[num_extensions++] = VkExtensionProperties{
+            VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION};
+        available[num_extensions++] =
+            VkExtensionProperties{VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+                                  VK_KHR_ANDROID_SURFACE_SPEC_VERSION};
+        if (g_driver_instance_extensions[kEXT_debug_report]) {
+            available[num_extensions++] =
+                VkExtensionProperties{VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+                                      VK_EXT_DEBUG_REPORT_SPEC_VERSION};
+        }
         // TODO(jessehall): We need to also enumerate extensions supported by
         // implicitly-enabled layers. Currently we don't have that list of
         // layers until instance creation.
-
-        // TODO(jessehall): We need to also enumerate extensions supported by
-        // any driver.
+        extensions = available;
     }
 
     if (!properties || *properties_count > num_extensions)