Vulkan: correctly expose Vulkan entry points

This change fixes the advertisement of core Vulkan entry points as below:
1. GIPA returns a valid checked_proc for 1.1 core device APIs.
2. GDPA returns NULL for 1.1 core device APIs on a 1.0 physical device.

Bug: 134185757
Bug: 142266108
Test: dEQP-VK.memory.binding on 1.1 loader and 1.0 device ICD
Test: dEQP-VK.api.info.instance on 1.1 loader and 1.0 instance ICD
Change-Id: I0a3e06dc04bade4f36a7e68ee2f53979c656ee4e
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 48f26e7..1578d9f 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -519,7 +519,11 @@
       get_device_proc_addr_(nullptr),
       driver_extensions_(nullptr),
       driver_extension_count_(0) {
-    enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
+    // advertise the loader supported core Vulkan API version at vulkan::api
+    for (uint32_t i = driver::ProcHook::EXTENSION_CORE_1_0;
+         i != driver::ProcHook::EXTENSION_COUNT; ++i) {
+        enabled_extensions_.set(i);
+    }
 }
 
 LayerChain::~LayerChain() {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index b413ac9..c3c19ec 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -99,6 +99,7 @@
 
     VkResult Validate();
     void DowngradeApiVersion();
+    void UpgradeDeviceCoreApiVersion(uint32_t api_version);
 
     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -328,8 +329,12 @@
       physical_dev_(VK_NULL_HANDLE),
       instance_info_(create_info),
       extension_filter_() {
-    hook_extensions_.set(ProcHook::EXTENSION_CORE);
-    hal_extensions_.set(ProcHook::EXTENSION_CORE);
+    // instance core versions need to match the loader api version
+    for (uint32_t i = ProcHook::EXTENSION_CORE_1_0;
+         i != ProcHook::EXTENSION_COUNT; ++i) {
+        hook_extensions_.set(i);
+        hal_extensions_.set(i);
+    }
 }
 
 CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -340,8 +345,9 @@
       physical_dev_(physical_dev),
       dev_info_(create_info),
       extension_filter_() {
-    hook_extensions_.set(ProcHook::EXTENSION_CORE);
-    hal_extensions_.set(ProcHook::EXTENSION_CORE);
+    // initialize with baseline core API version
+    hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+    hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
 }
 
 CreateInfoWrapper::~CreateInfoWrapper() {
@@ -540,7 +546,8 @@
             case ProcHook::ANDROID_external_memory_android_hardware_buffer:
             case ProcHook::ANDROID_native_buffer:
             case ProcHook::GOOGLE_display_timing:
-            case ProcHook::EXTENSION_CORE:
+            case ProcHook::EXTENSION_CORE_1_0:
+            case ProcHook::EXTENSION_CORE_1_1:
             case ProcHook::EXTENSION_COUNT:
                 // Device and meta extensions. If we ever get here it's a bug in
                 // our code. But enumerating them lets us avoid having a default
@@ -588,7 +595,8 @@
             case ProcHook::EXT_debug_report:
             case ProcHook::EXT_swapchain_colorspace:
             case ProcHook::ANDROID_native_buffer:
-            case ProcHook::EXTENSION_CORE:
+            case ProcHook::EXTENSION_CORE_1_0:
+            case ProcHook::EXTENSION_CORE_1_1:
             case ProcHook::EXTENSION_COUNT:
                 // Instance and meta extensions. If we ever get here it's a bug
                 // in our code. But enumerating them lets us avoid having a
@@ -636,6 +644,31 @@
     }
 }
 
+void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) {
+    ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper.");
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+    api_version ^= VK_VERSION_PATCH(api_version);
+#pragma clang diagnostic pop
+
+    // cap the API version to the loader supported highest version
+    if (api_version > VK_API_VERSION_1_1)
+        api_version = VK_API_VERSION_1_1;
+
+    switch (api_version) {
+        case VK_API_VERSION_1_1:
+            hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+            hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+            [[clang::fallthrough]];
+        case VK_API_VERSION_1_0:
+            break;
+        default:
+            ALOGD("Unknown upgrade API version[%u]", api_version);
+            break;
+    }
+}
+
 VKAPI_ATTR void* DefaultAllocate(void*,
                                  size_t size,
                                  size_t alignment,
@@ -771,7 +804,7 @@
                        : nullptr;
             break;
         case ProcHook::DEVICE:
-            proc = (hook->extension == ProcHook::EXTENSION_CORE)
+            proc = (hook->extension == ProcHook::EXTENSION_CORE_1_0)
                        ? hook->proc
                        : hook->checked_proc;
             break;
@@ -1117,6 +1150,13 @@
     if (!data)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
 
+    VkPhysicalDeviceProperties properties;
+    ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
+    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+                                                     &properties);
+    ATRACE_END();
+
+    wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion);
     data->hook_extensions |= wrapper.GetHookExtensions();
 
     // call into the driver
@@ -1161,12 +1201,6 @@
         return VK_ERROR_INCOMPATIBLE_DRIVER;
     }
 
-    VkPhysicalDeviceProperties properties;
-    ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
-    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
-                                                     &properties);
-    ATRACE_END();
-
     if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
         // Log that the app is hitting software Vulkan implementation
         android::GraphicsEnv::getInstance().setTargetStats(
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index f058c47..61e1818 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -67,9 +67,7 @@
         : opaque_api_data(),
           allocator(alloc),
           driver(),
-          get_device_proc_addr(nullptr) {
-        hook_extensions.set(ProcHook::EXTENSION_CORE);
-    }
+          get_device_proc_addr(nullptr) {}
 
     api::InstanceData opaque_api_data;
 
@@ -89,9 +87,7 @@
         : opaque_api_data(),
           allocator(alloc),
           debug_report_callbacks(debug_report_callbacks_),
-          driver() {
-        hook_extensions.set(ProcHook::EXTENSION_CORE);
-    }
+          driver() {}
 
     api::DeviceData opaque_api_data;
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index f676573..52205e9 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -74,6 +74,15 @@
     }
 }
 
+VKAPI_ATTR VkResult checkedBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
+        return BindImageMemory2(device, bindInfoCount, pBindInfos);
+    } else {
+        Logger(device).Err(device, "VK_VERSION_1_1 not enabled. vkBindImageMemory2 not executed.");
+        return VK_SUCCESS;
+    }
+}
+
 VKAPI_ATTR VkResult checkedBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
     if (GetData(device).hook_extensions[ProcHook::KHR_bind_memory2]) {
         return BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
@@ -145,6 +154,14 @@
     }
 }
 
+VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
+        GetDeviceQueue2(device, pQueueInfo, pQueue);
+    } else {
+        Logger(device).Err(device, "VK_VERSION_1_1 not enabled. vkGetDeviceQueue2 not executed.");
+    }
+}
+
 // clang-format on
 
 const ProcHook g_proc_hooks[] = {
@@ -173,16 +190,16 @@
     {
         "vkAllocateCommandBuffers",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
         nullptr,
     },
     {
         "vkBindImageMemory2",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_1,
         reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2),
-        nullptr,
+        reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2),
     },
     {
         "vkBindImageMemory2KHR",
@@ -208,14 +225,14 @@
     {
         "vkCreateDevice",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
         nullptr,
     },
     {
         "vkCreateInstance",
         ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
         nullptr,
     },
@@ -243,14 +260,14 @@
     {
         "vkDestroyDevice",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
         nullptr,
     },
     {
         "vkDestroyInstance",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
         nullptr,
     },
@@ -271,28 +288,28 @@
     {
         "vkEnumerateDeviceExtensionProperties",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
         nullptr,
     },
     {
         "vkEnumerateInstanceExtensionProperties",
         ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
         nullptr,
     },
     {
         "vkEnumeratePhysicalDeviceGroups",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_1,
         reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
         nullptr,
     },
     {
         "vkEnumeratePhysicalDevices",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
         nullptr,
     },
@@ -313,28 +330,28 @@
     {
         "vkGetDeviceProcAddr",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
         nullptr,
     },
     {
         "vkGetDeviceQueue",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
         nullptr,
     },
     {
         "vkGetDeviceQueue2",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_1,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
-        nullptr,
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceQueue2),
     },
     {
         "vkGetInstanceProcAddr",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
         nullptr,
     },
@@ -446,7 +463,7 @@
     {
         "vkQueueSubmit",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit),
         nullptr,
     },
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index cd7d8f8..43c4d14 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -49,7 +49,8 @@
         KHR_bind_memory2,
         KHR_get_physical_device_properties2,
 
-        EXTENSION_CORE,  // valid bit
+        EXTENSION_CORE_1_0,
+        EXTENSION_CORE_1_1,
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
     };
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index 0f3d760..a64a702 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -177,8 +177,12 @@
     for ext in _KNOWN_EXTENSIONS:
       f.write(gencom.indent(2) + gencom.base_ext_name(ext) + ',\n')
 
-    f.write("""
-        EXTENSION_CORE,  // valid bit
+    f.write('\n')
+    for version in gencom.version_code_list:
+      f.write(gencom.indent(2) + 'EXTENSION_CORE_' + version + ',\n')
+
+    # EXTENSION_COUNT must be the next enum after the highest API version.
+    f.write("""\
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
     };
@@ -249,6 +253,18 @@
   return False
 
 
+def _get_proc_hook_enum(cmd):
+  """Returns the ProcHook enumeration for the corresponding core function.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  assert cmd in gencom.version_dict
+  for version in gencom.version_code_list:
+    if gencom.version_dict[cmd] == 'VK_VERSION_' + version:
+      return 'ProcHook::EXTENSION_CORE_' + version
+
+
 def _need_proc_hook_stub(cmd):
   """Returns true if a function needs a ProcHook stub.
 
@@ -259,6 +275,8 @@
     if cmd in gencom.extension_dict:
       if not gencom.is_extension_internal(gencom.extension_dict[cmd]):
         return True
+    elif gencom.version_dict[cmd] != 'VK_VERSION_1_0':
+      return True
   return False
 
 
@@ -271,8 +289,16 @@
   """
   if _need_proc_hook_stub(cmd):
     return_type = gencom.return_type_dict[cmd]
-    ext_name = gencom.extension_dict[cmd]
-    ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
+
+    ext_name = ''
+    ext_hook = ''
+    if cmd in gencom.extension_dict:
+      ext_name = gencom.extension_dict[cmd]
+      ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
+    else:
+      ext_name = gencom.version_dict[cmd]
+      ext_hook = _get_proc_hook_enum(cmd)
+
     handle = gencom.param_dict[cmd][0][1]
     param_types = ', '.join([''.join(i) for i in gencom.param_dict[cmd]])
     param_names = ', '.join([''.join(i[1]) for i in gencom.param_dict[cmd]])
@@ -306,12 +332,12 @@
 
   f.write(gencom.indent(1) + '{\n')
   f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
-  f.write("""\
-        ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE,
-        reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
-        nullptr,
-    },\n""")
+  f.write(gencom.indent(2) + 'ProcHook::GLOBAL,\n')
+  f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+  f.write(gencom.indent(2) + 'reinterpret_cast<PFN_vkVoidFunction>(' +
+          gencom.base_name(cmd) + '),\n')
+  f.write(gencom.indent(2) + 'nullptr,\n')
+  f.write(gencom.indent(1) + '},\n')
 
 
 def _define_instance_proc_hook(cmd, f):
@@ -339,8 +365,8 @@
         reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
         nullptr,\n""")
   else:
+    f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
     f.write("""\
-        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
         nullptr,\n""")
 
@@ -358,10 +384,17 @@
   f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
   f.write(gencom.indent(2) + 'ProcHook::DEVICE,\n')
 
-  if cmd in gencom.extension_dict:
-    ext_name = gencom.extension_dict[cmd]
-    f.write(gencom.indent(2) + 'ProcHook::' +
-            gencom.base_ext_name(ext_name) + ',\n')
+  if (cmd in gencom.extension_dict or
+      gencom.version_dict[cmd] != 'VK_VERSION_1_0'):
+    ext_name = ''
+    ext_hook = ''
+    if cmd in gencom.extension_dict:
+      ext_name = gencom.extension_dict[cmd]
+      ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
+    else:
+      ext_name = gencom.version_dict[cmd]
+      ext_hook = _get_proc_hook_enum(cmd)
+    f.write(gencom.indent(2) + ext_hook + ',\n')
 
     if gencom.is_extension_internal(ext_name):
       f.write("""\
@@ -374,8 +407,8 @@
               gencom.base_name(cmd) + '),\n')
 
   else:
+    f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
     f.write("""\
-        ProcHook::EXTENSION_CORE,
         reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
         nullptr,\n""")
 
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index 670ba66..cf370fa 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -91,6 +91,9 @@
 # Dict for mapping a function to its return type.
 return_type_dict = {}
 
+# List of the sorted Vulkan version codes. e.g. '1_0', '1_1'.
+version_code_list = []
+
 # Dict for mapping a function to the core Vulkan API version.
 version_dict = {}
 
@@ -171,6 +174,15 @@
   return ext[3:]
 
 
+def version_code(version):
+  """Returns the version code from a version string.
+
+  Args:
+    version: Vulkan version string.
+  """
+  return version[11:]
+
+
 def is_function_supported(cmd):
   """Returns true if a function is core or from a supportable extension.
 
@@ -313,6 +325,7 @@
   extension_dict
   param_dict
   return_type_dict
+  version_code_list
   version_dict
   """
   registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
@@ -385,3 +398,9 @@
           cmd_name = command.get('name')
           if cmd_name in command_list:
             version_dict[cmd_name] = apiversion
+
+  version_code_set = set()
+  for version in version_dict.values():
+    version_code_set.add(version_code(version))
+  for code in sorted(version_code_set):
+    version_code_list.append(code)