vulkan: Support VK_EXT_debug_report in loader and nulldrv

* Add extension to vulkan.api.
* Fix a few errors in upstream vk_ext_debug_report.h; bugs filed.
* Loader enumerates extension iff the driver supports it.
  - TODO: Also enumerate if any layers that support it are implicitly
    enabled.
  - Note extension may still be enabled if any layer supports it.
* Add loader bottom procs for the extension functions. These will call
  through to the driver version if the driver supports the extension.
* Add no-op support to nulldrv, mostly for testing the loader.

Change-Id: I092d2da56ee4c64498f8edae75e0d995478bb6f2
(cherry picked from commit a5ef7c27bc85e3628814532a32ffb9a5c33c4b73)
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index 4241757..e643918 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -16,9 +16,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_CLANG := true
-LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
-LOCAL_CFLAGS += -DLOG_TAG=\"vulkan\"
-LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef
+LOCAL_CFLAGS := -DLOG_TAG=\"vulkan\" \
+	-std=c99 -fvisibility=hidden -fstrict-aliasing \
+	-Weverything -Werror \
+	-Wno-padded \
+	-Wno-undef
+#LOCAL_CFLAGS += -DLOG_NDEBUG=0
 LOCAL_CPPFLAGS := -std=c++14 \
 	-Wno-c++98-compat-pedantic \
 	-Wno-exit-time-destructors \
@@ -31,6 +34,7 @@
 	system/core/libsync/include
 
 LOCAL_SRC_FILES := \
+	debug_report.cpp \
 	dispatch_gen.cpp \
 	layers_extensions.cpp \
 	loader.cpp \
diff --git a/vulkan/libvulkan/debug_report.cpp b/vulkan/libvulkan/debug_report.cpp
new file mode 100644
index 0000000..fea9f18
--- /dev/null
+++ b/vulkan/libvulkan/debug_report.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "loader.h"
+
+namespace vulkan {
+
+VkResult DebugReportCallbackList::CreateCallback(
+    VkInstance instance,
+    const VkDebugReportCallbackCreateInfoEXT* create_info,
+    const VkAllocationCallbacks* allocator,
+    VkDebugReportCallbackEXT* callback) {
+    VkDebugReportCallbackEXT driver_callback;
+    VkResult result = GetDriverDispatch(instance).CreateDebugReportCallbackEXT(
+        GetDriverInstance(instance), create_info, allocator, &driver_callback);
+    if (result != VK_SUCCESS)
+        return result;
+
+    const VkAllocationCallbacks* alloc =
+        allocator ? allocator : GetAllocator(instance);
+    void* mem =
+        alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node),
+                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (!mem) {
+        GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
+            GetDriverInstance(instance), driver_callback, allocator);
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+
+    std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
+    head_.next =
+        new (mem) Node{head_.next, create_info->flags, create_info->pfnCallback,
+                       create_info->pUserData, driver_callback};
+    *callback =
+        VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(head_.next));
+    return VK_SUCCESS;
+}
+
+void DebugReportCallbackList::DestroyCallback(
+    VkInstance instance,
+    VkDebugReportCallbackEXT callback,
+    const VkAllocationCallbacks* allocator) {
+    Node* node = reinterpret_cast<Node*>(uintptr_t(callback));
+    std::unique_lock<decltype(rwmutex_)> lock(rwmutex_);
+    Node* prev = &head_;
+    while (prev && prev->next != node)
+        prev = prev->next;
+    prev->next = node->next;
+    lock.unlock();
+
+    GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
+        GetDriverInstance(instance), node->driver_callback, allocator);
+
+    const VkAllocationCallbacks* alloc =
+        allocator ? allocator : GetAllocator(instance);
+    alloc->pfnFree(alloc->pUserData, node);
+}
+
+void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
+                                      VkDebugReportObjectTypeEXT object_type,
+                                      uint64_t object,
+                                      size_t location,
+                                      int32_t message_code,
+                                      const char* layer_prefix,
+                                      const char* message) {
+    std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
+    Node* node = &head_;
+    while ((node = node->next)) {
+        if ((node->flags & flags) != 0) {
+            node->callback(flags, object_type, object, location, message_code,
+                           layer_prefix, message, node->data);
+        }
+    }
+}
+
+VkResult CreateDebugReportCallbackEXT_Bottom(
+    VkInstance instance,
+    const VkDebugReportCallbackCreateInfoEXT* create_info,
+    const VkAllocationCallbacks* allocator,
+    VkDebugReportCallbackEXT* callback) {
+    return GetDebugReportCallbacks(instance).CreateCallback(
+        instance, create_info, allocator, callback);
+}
+
+void DestroyDebugReportCallbackEXT_Bottom(
+    VkInstance instance,
+    VkDebugReportCallbackEXT callback,
+    const VkAllocationCallbacks* allocator) {
+    if (callback)
+        GetDebugReportCallbacks(instance).DestroyCallback(instance, callback,
+                                                          allocator);
+}
+
+void DebugReportMessageEXT_Bottom(VkInstance instance,
+                                  VkDebugReportFlagsEXT flags,
+                                  VkDebugReportObjectTypeEXT object_type,
+                                  uint64_t object,
+                                  size_t location,
+                                  int32_t message_code,
+                                  const char* layer_prefix,
+                                  const char* message) {
+    GetDriverDispatch(instance).DebugReportMessageEXT(
+        GetDriverInstance(instance), flags, object_type, object, location,
+        message_code, layer_prefix, message);
+    GetDebugReportCallbacks(instance).Message(flags, object_type, object,
+                                              location, message_code,
+                                              layer_prefix, message);
+}
+
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/debug_report.h b/vulkan/libvulkan/debug_report.h
new file mode 100644
index 0000000..5bce240
--- /dev/null
+++ b/vulkan/libvulkan/debug_report.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBVULKAN_DEBUG_REPORT_H
+#define LIBVULKAN_DEBUG_REPORT_H 1
+
+#include <shared_mutex>
+#include <vulkan/vk_ext_debug_report.h>
+
+namespace vulkan {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateDebugReportCallbackEXT_Bottom(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+VKAPI_ATTR void DestroyDebugReportCallbackEXT_Bottom(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void DebugReportMessageEXT_Bottom(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+// clang-format on
+
+class DebugReportCallbackList {
+   public:
+    DebugReportCallbackList()
+        : head_{nullptr, 0, nullptr, nullptr, VK_NULL_HANDLE} {}
+    DebugReportCallbackList(const DebugReportCallbackList&) = delete;
+    DebugReportCallbackList& operator=(const DebugReportCallbackList&) = delete;
+    ~DebugReportCallbackList() = default;
+
+    VkResult CreateCallback(
+        VkInstance instance,
+        const VkDebugReportCallbackCreateInfoEXT* create_info,
+        const VkAllocationCallbacks* allocator,
+        VkDebugReportCallbackEXT* callback);
+    void DestroyCallback(VkInstance instance,
+                         VkDebugReportCallbackEXT callback,
+                         const VkAllocationCallbacks* allocator);
+    void Message(VkDebugReportFlagsEXT flags,
+                 VkDebugReportObjectTypeEXT object_type,
+                 uint64_t object,
+                 size_t location,
+                 int32_t message_code,
+                 const char* layer_prefix,
+                 const char* message);
+
+   private:
+    struct Node {
+        Node* next;
+        VkDebugReportFlagsEXT flags;
+        PFN_vkDebugReportCallbackEXT callback;
+        void* data;
+        VkDebugReportCallbackEXT driver_callback;
+    };
+
+    // TODO(jessehall): replace with std::shared_mutex when available in libc++
+    std::shared_timed_mutex rwmutex_;
+    Node head_;
+};
+
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_DEBUG_REPORT_H
diff --git a/vulkan/libvulkan/dispatch.tmpl b/vulkan/libvulkan/dispatch.tmpl
index 11ec697..0f1194c 100644
--- a/vulkan/libvulkan/dispatch.tmpl
+++ b/vulkan/libvulkan/dispatch.tmpl
@@ -44,6 +44,7 @@

 #define VK_USE_PLATFORM_ANDROID_KHR
 #include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vk_ext_debug_report.h>
 #include <vulkan/vulkan.h>

 namespace vulkan {
@@ -155,7 +156,7 @@
 const NameProc kLoaderExportProcs[] = {«
     // clang-format off
   {{range $f := SortBy (AllCommands $) "FunctionName"}}
-    {{if (Macro "IsFunctionSupported" $f)}}
+    {{if (Macro "IsExported" $f)}}
       {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}})},
     {{end}}
   {{end}}
@@ -507,11 +508,13 @@
 {{define "IsExported"}}
   {{AssertType $ "Function"}}
 
-  {{$ext := GetAnnotation $ "extension"}}
-  {{if $ext}}
-    {{Macro "IsLoaderExtension" $ext}}
-  {{else}}
-    true
+  {{if (Macro "IsFunctionSupported" $)}}
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      {{Macro "IsLoaderExtension" $ext}}
+    {{else}}
+      true
+    {{end}}
   {{end}}
 {{end}}
 
diff --git a/vulkan/libvulkan/dispatch_gen.cpp b/vulkan/libvulkan/dispatch_gen.cpp
index ebdf0da..60da749 100644
--- a/vulkan/libvulkan/dispatch_gen.cpp
+++ b/vulkan/libvulkan/dispatch_gen.cpp
@@ -224,9 +224,12 @@
     // clang-format off
     {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR_Bottom))},
     {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateAndroidSurfaceKHR>(CreateAndroidSurfaceKHR_Bottom))},
+    {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT_Bottom))},
     {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice_Bottom))},
     {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Bottom))},
     {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR_Bottom))},
+    {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT_Bottom))},
+    {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT_Bottom))},
     {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance_Bottom))},
     {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySurfaceKHR>(DestroySurfaceKHR_Bottom))},
     {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR_Bottom))},
@@ -283,7 +286,10 @@
 const NameOffset kInstanceDispatchOffsets[] = {
     // clang-format off
     {"vkCreateAndroidSurfaceKHR", offsetof(InstanceDispatchTable, CreateAndroidSurfaceKHR)},
+    {"vkCreateDebugReportCallbackEXT", offsetof(InstanceDispatchTable, CreateDebugReportCallbackEXT)},
     {"vkCreateDevice", offsetof(InstanceDispatchTable, CreateDevice)},
+    {"vkDebugReportMessageEXT", offsetof(InstanceDispatchTable, DebugReportMessageEXT)},
+    {"vkDestroyDebugReportCallbackEXT", offsetof(InstanceDispatchTable, DestroyDebugReportCallbackEXT)},
     {"vkDestroyInstance", offsetof(InstanceDispatchTable, DestroyInstance)},
     {"vkDestroySurfaceKHR", offsetof(InstanceDispatchTable, DestroySurfaceKHR)},
     {"vkEnumerateDeviceExtensionProperties", offsetof(InstanceDispatchTable, EnumerateDeviceExtensionProperties)},
@@ -558,6 +564,21 @@
         ALOGE("missing instance proc: %s", "vkCreateAndroidSurfaceKHR");
         success = false;
     }
+    dispatch.CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(get_proc_addr(instance, "vkCreateDebugReportCallbackEXT"));
+    if (UNLIKELY(!dispatch.CreateDebugReportCallbackEXT)) {
+        ALOGE("missing instance proc: %s", "vkCreateDebugReportCallbackEXT");
+        success = false;
+    }
+    dispatch.DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(get_proc_addr(instance, "vkDestroyDebugReportCallbackEXT"));
+    if (UNLIKELY(!dispatch.DestroyDebugReportCallbackEXT)) {
+        ALOGE("missing instance proc: %s", "vkDestroyDebugReportCallbackEXT");
+        success = false;
+    }
+    dispatch.DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(get_proc_addr(instance, "vkDebugReportMessageEXT"));
+    if (UNLIKELY(!dispatch.DebugReportMessageEXT)) {
+        ALOGE("missing instance proc: %s", "vkDebugReportMessageEXT");
+        success = false;
+    }
     // clang-format on
     return success;
 }
@@ -1262,6 +1283,27 @@
         ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceSparseImageFormatProperties");
         success = false;
     }
+    if (extensions[kEXT_debug_report]) {
+        dispatch.CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(get_proc_addr(instance, "vkCreateDebugReportCallbackEXT"));
+        if (UNLIKELY(!dispatch.CreateDebugReportCallbackEXT)) {
+            ALOGE("missing driver proc: %s", "vkCreateDebugReportCallbackEXT");
+            success = false;
+        }
+    }
+    if (extensions[kEXT_debug_report]) {
+        dispatch.DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(get_proc_addr(instance, "vkDestroyDebugReportCallbackEXT"));
+        if (UNLIKELY(!dispatch.DestroyDebugReportCallbackEXT)) {
+            ALOGE("missing driver proc: %s", "vkDestroyDebugReportCallbackEXT");
+            success = false;
+        }
+    }
+    if (extensions[kEXT_debug_report]) {
+        dispatch.DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(get_proc_addr(instance, "vkDebugReportMessageEXT"));
+        if (UNLIKELY(!dispatch.DebugReportMessageEXT)) {
+            ALOGE("missing driver proc: %s", "vkDebugReportMessageEXT");
+            success = false;
+        }
+    }
     dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
     if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
         ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
diff --git a/vulkan/libvulkan/dispatch_gen.h b/vulkan/libvulkan/dispatch_gen.h
index 877d8aa..14c5da8 100644
--- a/vulkan/libvulkan/dispatch_gen.h
+++ b/vulkan/libvulkan/dispatch_gen.h
@@ -16,6 +16,7 @@
 
 #define VK_USE_PLATFORM_ANDROID_KHR
 #include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vk_ext_debug_report.h>
 #include <vulkan/vulkan.h>
 
 namespace vulkan {
@@ -40,6 +41,9 @@
     PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
     PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
     PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+    PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+    PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+    PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
     // clang-format on
 };
 
@@ -187,6 +191,9 @@
     PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
     PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
     PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+    PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+    PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+    PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
     PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
     PFN_vkCreateImage CreateImage;
     PFN_vkDestroyImage DestroyImage;
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index f302307..90a3827 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-// #define LOG_NDEBUG 0
-
 #include "loader.h"
 #include <alloca.h>
 #include <dirent.h>
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index 079352b..618bd93 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -37,7 +37,6 @@
 #include <cutils/properties.h>
 #include <hardware/hwvulkan.h>
 #include <log/log.h>
-#include <vulkan/vk_debug_report_lunarg.h>
 #include <vulkan/vulkan_loader_data.h>
 
 using namespace vulkan;
@@ -249,7 +248,6 @@
     Instance(const VkAllocationCallbacks* alloc_callbacks)
         : dispatch_ptr(&dispatch),
           handle(reinterpret_cast<VkInstance>(&dispatch_ptr)),
-          get_instance_proc_addr(nullptr),
           alloc(alloc_callbacks),
           num_physical_devices(0),
           active_layers(CallbackAllocator<LayerRef>(alloc)),
@@ -267,17 +265,13 @@
     const VkInstance handle;
     InstanceDispatchTable dispatch;
 
-    // TODO(jessehall): Only needed by GetInstanceProcAddr_Top for
-    // vkDbg*MessageCallback. Points to the outermost layer's function. Remove
-    // once the DEBUG_CALLBACK is integrated into the API file.
-    PFN_vkGetInstanceProcAddr get_instance_proc_addr;
-
     const VkAllocationCallbacks* alloc;
     uint32_t num_physical_devices;
     VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
 
     Vector<LayerRef> active_layers;
-    VkDbgMsgCallback message;
+    VkDebugReportCallbackEXT message;
+    DebugReportCallbackList debug_report_callbacks;
 
     struct {
         VkInstance instance;
@@ -476,17 +470,17 @@
 }
 
 VKAPI_ATTR
-VkBool32 LogDebugMessageCallback(VkFlags message_flags,
-                                 VkDbgObjectType /*obj_type*/,
-                                 uint64_t /*src_object*/,
+VkBool32 LogDebugMessageCallback(VkDebugReportFlagsEXT flags,
+                                 VkDebugReportObjectTypeEXT /*objectType*/,
+                                 uint64_t /*object*/,
                                  size_t /*location*/,
                                  int32_t message_code,
                                  const char* layer_prefix,
                                  const char* message,
                                  void* /*user_data*/) {
-    if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
+    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
         ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
-    } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
+    } else if (flags & VK_DEBUG_REPORT_WARN_BIT_EXT) {
         ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
     }
     return false;
@@ -517,8 +511,9 @@
     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());
+    size_t max_names =
+        std::min(static_cast<size_t>(create_info->enabledExtensionCount),
+                 g_driver_instance_extensions.count());
     if (max_names > 0) {
         const char** names =
             static_cast<const char**>(alloca(max_names * sizeof(char*)));
@@ -598,12 +593,6 @@
     PFN_vkVoidFunction pfn;
     if ((pfn = GetLoaderBottomProcAddr(name)))
         return pfn;
-    // TODO: Possibly move this into the instance table
-    // TODO: Possibly register the callbacks in the loader
-    if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
-        strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
-        return reinterpret_cast<PFN_vkVoidFunction>(Noop);
-    }
     return nullptr;
 }
 
@@ -829,11 +818,12 @@
         instance.drv.dispatch.DestroyInstance(instance.drv.instance, allocator);
     }
     if (instance.message) {
-        PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
-        DebugDestroyMessageCallback =
-            reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
-                vkGetInstanceProcAddr(vkinstance, "vkDbgDestroyMsgCallback"));
-        DebugDestroyMessageCallback(vkinstance, instance.message);
+        PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report_callback;
+        destroy_debug_report_callback =
+            reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+                vkGetInstanceProcAddr(vkinstance,
+                                      "vkDestroyDebugReportCallbackEXT"));
+        destroy_debug_report_callback(vkinstance, instance.message, allocator);
     }
     instance.active_layers.clear();
     const VkAllocationCallbacks* alloc = instance.alloc;
@@ -975,7 +965,6 @@
                 next_element->get_proc_addr);
         }
     }
-    instance->get_instance_proc_addr = next_get_proc_addr;
 
     // This is the magic call that initializes all the layer instances and
     // allows them to create their instance_handle -> instance_data mapping.
@@ -997,7 +986,7 @@
         enable_logging = enable_callback;
         if (enable_callback) {
             enable_callback = AddExtensionToCreateInfo(
-                local_create_info, "DEBUG_REPORT", instance->alloc);
+                local_create_info, "VK_EXT_debug_report", instance->alloc);
         }
     }
 
@@ -1024,13 +1013,18 @@
     }
 
     if (enable_logging) {
-        PFN_vkDbgCreateMsgCallback dbg_create_msg_callback;
-        dbg_create_msg_callback = reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
-            GetInstanceProcAddr_Top(instance->handle,
-                                    "vkDbgCreateMsgCallback"));
-        dbg_create_msg_callback(
-            instance->handle, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
-            LogDebugMessageCallback, nullptr, &instance->message);
+        const VkDebugReportCallbackCreateInfoEXT callback_create_info = {
+            .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
+            .flags =
+                VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARN_BIT_EXT,
+            .pfnCallback = LogDebugMessageCallback,
+        };
+        PFN_vkCreateDebugReportCallbackEXT create_debug_report_callback =
+            reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+                GetInstanceProcAddr_Top(instance->handle,
+                                        "vkCreateDebugReportCallbackEXT"));
+        create_debug_report_callback(instance->handle, &callback_create_info,
+                                     allocator, &instance->message);
     }
 
     return result;
@@ -1050,13 +1044,6 @@
     // Otherwise, look up the handler in the instance dispatch table
     if ((pfn = GetDispatchProcAddr(dispatch, name)))
         return pfn;
-    // TODO(jessehall): Generate these into the instance dispatch table, and
-    // add loader-bottom procs for them.
-    if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
-        strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
-        return GetDispatchParent(vkinstance)
-            .get_instance_proc_addr(vkinstance, name);
-    }
     // Anything not handled already must be a device-dispatched function
     // without a loader-top. We must return a function that will dispatch based
     // on the dispatchable object parameter -- which is exactly what the
@@ -1134,6 +1121,14 @@
     return GetDispatchParent(vkdevice).instance->alloc;
 }
 
+VkInstance GetDriverInstance(VkInstance instance) {
+    return GetDispatchParent(instance).drv.instance;
+}
+
+const DriverDispatchTable& GetDriverDispatch(VkInstance instance) {
+    return GetDispatchParent(instance).drv.dispatch;
+}
+
 const DriverDispatchTable& GetDriverDispatch(VkDevice device) {
     return GetDispatchParent(device).instance->drv.dispatch;
 }
@@ -1142,4 +1137,8 @@
     return GetDispatchParent(queue).instance->drv.dispatch;
 }
 
+DebugReportCallbackList& GetDebugReportCallbacks(VkInstance instance) {
+    return GetDispatchParent(instance).debug_report_callbacks;
+}
+
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index b7edb73..df43f74 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -19,6 +19,7 @@
 
 #include <bitset>
 #include "dispatch_gen.h"
+#include "debug_report.h"
 
 namespace vulkan {
 
@@ -107,8 +108,11 @@
 
 const VkAllocationCallbacks* GetAllocator(VkInstance instance);
 const VkAllocationCallbacks* GetAllocator(VkDevice device);
+VkInstance GetDriverInstance(VkInstance instance);
+const DriverDispatchTable& GetDriverDispatch(VkInstance instance);
 const DriverDispatchTable& GetDriverDispatch(VkDevice device);
 const DriverDispatchTable& GetDriverDispatch(VkQueue queue);
+DebugReportCallbackList& GetDebugReportCallbacks(VkInstance instance);
 
 // -----------------------------------------------------------------------------
 // swapchain.cpp
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 5ee2abf..da843f1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-// #define LOG_NDEBUG 0
-
 #include <algorithm>
 #include <memory>
 
@@ -322,9 +320,9 @@
     if (!allocator)
         allocator = GetAllocator(device);
 
-    ALOGV_IF(create_info->imageArraySize != 1,
-             "Swapchain imageArraySize (%u) != 1 not supported",
-             create_info->imageArraySize);
+    ALOGV_IF(create_info->imageArrayLayers != 1,
+             "Swapchain imageArrayLayers (%u) != 1 not supported",
+             create_info->imageArrayLayers);
 
     ALOGE_IF(create_info->imageFormat != VK_FORMAT_R8G8B8A8_UNORM,
              "swapchain formats other than R8G8B8A8_UNORM not yet implemented");