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/api/vulkan.api b/vulkan/api/vulkan.api
index 5d35ddf..d735844 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -75,6 +75,9 @@
 @extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION     5
 @extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME             "VK_KHR_win32_surface"
 
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       2
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
+
 
 /////////////
 //  Types  //
@@ -121,6 +124,8 @@
 @extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayKHR
 @extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayModeKHR
 
+@extension("VK_EXT_debug_report") @nonDispatchHandle type u64 VkDebugReportCallbackEXT
+
 
 /////////////
 //  Enums  //
@@ -722,6 +727,46 @@
     VK_COLORSPACE_SRGB_NONLINEAR_KHR                        = 0x00000000,
 }
 
+@extension("VK_EXT_debug_report")
+enum VkDebugReportObjectTypeEXT {
+    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT                 = 0,
+    VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT                = 1,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT         = 2,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT                  = 3,
+    VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT                   = 4,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT               = 5,
+    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT          = 6,
+    VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT                   = 7,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT           = 8,
+    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT                  = 9,
+    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT                   = 10,
+    VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT                   = 11,
+    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT              = 12,
+    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT             = 13,
+    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT              = 14,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT           = 15,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT          = 16,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT         = 17,
+    VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT             = 18,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT                = 19,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT   = 20,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT                 = 21,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT         = 22,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT          = 23,
+    VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT             = 24,
+    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT            = 25,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT             = 26,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT           = 27,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT            = 28,
+}
+
+@extension("VK_EXT_debug_report")
+enum VkDebugReportErrorEXT {
+    VK_DEBUG_REPORT_ERROR_NONE_EXT                          = 0,
+    VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT                  = 1,
+}
+
+
 /////////////////
 //  Bitfields  //
 /////////////////
@@ -1249,6 +1294,17 @@
 //bitfield VkWin32SurfaceCreateFlagBitsKHR {
 //}
 
+@extension("VK_EXT_debug_report")
+type VkFlags VkDebugReportFlagsEXT
+@extension("VK_EXT_debug_report")
+bitfield VkDebugReportFlagBitsEXT {
+    VK_DEBUG_REPORT_INFO_BIT_EXT                            = 0x00000001,
+    VK_DEBUG_REPORT_WARN_BIT_EXT                            = 0x00000002,
+    VK_DEBUG_REPORT_PERF_WARN_BIT_EXT                       = 0x00000004,
+    VK_DEBUG_REPORT_ERROR_BIT_EXT                           = 0x00000008,
+    VK_DEBUG_REPORT_DEBUG_BIT_EXT                           = 0x00000010,
+}
+
 
 //////////////////
 //  Structures  //
@@ -2534,6 +2590,15 @@
     platform.HWND                               hwnd
 }
 
+@extension("VK_EXT_debug_report")
+class VkDebugReportCallbackCreateInfoEXT {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkDebugReportFlagsEXT                       flags
+    PFN_vkDebugReportCallbackEXT                pfnCallback
+    void*                                       pUserData
+}
+
 
 ////////////////
 //  Commands  //
@@ -5068,6 +5133,49 @@
     return ?
 }
 
+@extension("VK_EXT_debug_report")
+@external type void* PFN_vkDebugReportCallbackEXT
+@extension("VK_EXT_debug_report")
+@pfn cmd VkBool32 vkDebugReportCallbackEXT(
+        VkDebugReportFlagsEXT                   flags,
+        VkDebugReportObjectTypeEXT              objectType,
+        u64                                     object,
+        platform.size_t                         location,
+        s32                                     messageCode,
+        const char*                             pLayerPrefix,
+        const char*                             pMessage,
+        void*                                   pUserData) {
+    return ?
+}
+
+@extension("VK_EXT_debug_report")
+cmd VkResult vkCreateDebugReportCallbackEXT(
+        VkInstance                                  instance,
+        const VkDebugReportCallbackCreateInfoEXT*   pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDebugReportCallbackEXT*                   pCallback) {
+    return ?
+}
+
+@extension("VK_EXT_debug_report")
+cmd void vkDestroyDebugReportCallbackEXT(
+        VkInstance                                  instance,
+        VkDebugReportCallbackEXT                    callback,
+        const VkAllocationCallbacks*                pAllocator) {
+}
+
+@extension("VK_EXT_debug_report")
+cmd void vkDebugReportMessageEXT(
+        VkInstance                                  instance,
+        VkDebugReportFlagsEXT                       flags,
+        VkDebugReportObjectTypeEXT                  objectType,
+        u64                                         object,
+        platform.size_t                             location,
+        s32                                         messageCode,
+        const char*                                 pLayerPrefix,
+        const char*                                 pMessage) {
+}
+
 
 ////////////////
 // Validation //
diff --git a/vulkan/include/vulkan/vk_debug_report_lunarg.h b/vulkan/include/vulkan/vk_debug_report_lunarg.h
deleted file mode 100644
index 58939c9..0000000
--- a/vulkan/include/vulkan/vk_debug_report_lunarg.h
+++ /dev/null
@@ -1,182 +0,0 @@
-//
-// File: vk_debug_report_lunarg.h
-//
-/*
- * Vulkan
- *
- * Copyright (C) 2015 LunarG, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *   Jon Ashburn <jon@lunarg.com>
- *   Courtney Goeltzenleuchter <courtney@lunarg.com>
- */
-
-#ifndef __VK_DEBUG_REPORT_LUNARG_H__
-#define __VK_DEBUG_REPORT_LUNARG_H__
-
-#include "vulkan.h"
-
-#define VK_DEBUG_REPORT_EXTENSION_NUMBER 5
-#define VK_DEBUG_REPORT_EXTENSION_REVISION 1
-#ifdef __cplusplus
-extern "C"
-{
-#endif // __cplusplus
-
-/*
-***************************************************************************************************
-*   DebugReport Vulkan Extension API
-***************************************************************************************************
-*/
-typedef enum {
-    VK_OBJECT_TYPE_INSTANCE = 0,
-    VK_OBJECT_TYPE_PHYSICAL_DEVICE = 1,
-    VK_OBJECT_TYPE_DEVICE = 2,
-    VK_OBJECT_TYPE_QUEUE = 3,
-    VK_OBJECT_TYPE_COMMAND_BUFFER = 4,
-    VK_OBJECT_TYPE_DEVICE_MEMORY = 5,
-    VK_OBJECT_TYPE_BUFFER = 6,
-    VK_OBJECT_TYPE_BUFFER_VIEW = 7,
-    VK_OBJECT_TYPE_IMAGE = 8,
-    VK_OBJECT_TYPE_IMAGE_VIEW = 9,
-    VK_OBJECT_TYPE_ATTACHMENT_VIEW = 10,
-    VK_OBJECT_TYPE_SHADER_MODULE = 12,
-    VK_OBJECT_TYPE_SHADER = 13,
-    VK_OBJECT_TYPE_PIPELINE = 14,
-    VK_OBJECT_TYPE_PIPELINE_LAYOUT = 15,
-    VK_OBJECT_TYPE_SAMPLER = 16,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET = 17,
-    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 18,
-    VK_OBJECT_TYPE_DESCRIPTOR_POOL = 19,
-    VK_OBJECT_TYPE_FENCE = 20,
-    VK_OBJECT_TYPE_SEMAPHORE = 21,
-    VK_OBJECT_TYPE_EVENT = 22,
-    VK_OBJECT_TYPE_QUERY_POOL = 23,
-    VK_OBJECT_TYPE_FRAMEBUFFER = 24,
-    VK_OBJECT_TYPE_RENDER_PASS = 25,
-    VK_OBJECT_TYPE_PIPELINE_CACHE = 26,
-    VK_OBJECT_TYPE_SWAPCHAIN_KHR = 27,
-    VK_OBJECT_TYPE_CMD_POOL = 28,
-    VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_INSTANCE,
-    VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_CMD_POOL,
-    VK_OBJECT_TYPE_NUM = (VK_OBJECT_TYPE_CMD_POOL - VK_OBJECT_TYPE_INSTANCE + 1),
-    VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
-} VkDbgObjectType;
-
-#define VK_DEBUG_REPORT_EXTENSION_NAME "DEBUG_REPORT"
-
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDbgMsgCallback)
-
-// ------------------------------------------------------------------------------------------------
-// Enumerations
-
-typedef enum VkDbgReportFlags_
-{
-    VK_DBG_REPORT_INFO_BIT       = 0x0001,
-    VK_DBG_REPORT_WARN_BIT       = 0x0002,
-    VK_DBG_REPORT_PERF_WARN_BIT  = 0x0004,
-    VK_DBG_REPORT_ERROR_BIT      = 0x0008,
-    VK_DBG_REPORT_DEBUG_BIT      = 0x0010,
-} VkDbgReportFlags;
-
-// Debug Report ERROR codes
-typedef enum _DEBUG_REPORT_ERROR
-{
-    DEBUG_REPORT_NONE,                  // Used for INFO & other non-error messages
-    DEBUG_REPORT_CALLBACK_REF,          // Callbacks were not destroyed prior to calling DestroyInstance
-} DEBUG_REPORT_ERROR;
-
-#define VK_DEBUG_REPORT_ENUM_EXTEND(type, id)    ((type)(VK_DEBUG_REPORT_EXTENSION_NUMBER * -1000 + (id)))
-
-#define VK_OBJECT_TYPE_MSG_CALLBACK VK_DEBUG_REPORT_ENUM_EXTEND(VkDbgObjectType, 0)
-#define VK_ERROR_VALIDATION_FAILED VK_DEBUG_REPORT_ENUM_EXTEND(VkResult, 0)
-
-// ------------------------------------------------------------------------------------------------
-// Vulkan function pointers
-
-typedef VkBool32 (VKAPI_PTR *PFN_vkDbgMsgCallback)(
-    VkFlags                             msgFlags,
-    VkDbgObjectType                     objType,
-    uint64_t                            srcObject,
-    size_t                              location,
-    int32_t                             msgCode,
-    const char*                         pLayerPrefix,
-    const char*                         pMsg,
-    void*                               pUserData);
-
-// ------------------------------------------------------------------------------------------------
-// API functions
-
-typedef VkResult (VKAPI_PTR *PFN_vkDbgCreateMsgCallback)(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback);
-typedef VkResult (VKAPI_PTR *PFN_vkDbgDestroyMsgCallback)(VkInstance instance, VkDbgMsgCallback msgCallback);
-
-#ifdef VK_PROTOTYPES
-
-// DebugReport extension entrypoints
-VKAPI_ATTR VkResult VKAPI_CALL vkDbgCreateMsgCallback(
-    VkInstance                          instance,
-    VkFlags                             msgFlags,
-    const PFN_vkDbgMsgCallback          pfnMsgCallback,
-    void*                               pUserData,
-    VkDbgMsgCallback*                   pMsgCallback);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkDbgDestroyMsgCallback(
-    VkInstance                          instance,
-    VkDbgMsgCallback                    msgCallback);
-
-// DebugReport utility callback functions
-VKAPI_ATTR void VKAPI_CALL vkDbgStringCallback(
-    VkFlags                             msgFlags,
-    VkDbgObjectType                     objType,
-    uint64_t                            srcObject,
-    size_t                              location,
-    int32_t                             msgCode,
-    const char*                         pLayerPrefix,
-    const char*                         pMsg,
-    void*                               pUserData);
-
-VKAPI_ATTR void VKAPI_CALL vkDbgStdioCallback(
-    VkFlags                             msgFlags,
-    VkDbgObjectType                     objType,
-    uint64_t                            srcObject,
-    size_t                              location,
-    int32_t                             msgCode,
-    const char*                         pLayerPrefix,
-    const char*                         pMsg,
-    void*                               pUserData);
-
-VKAPI_ATTR void VKAPI_CALL vkDbgBreakCallback(
-    VkFlags                             msgFlags,
-    VkDbgObjectType                     objType,
-    uint64_t                            srcObject,
-    size_t                              location,
-    int32_t                             msgCode,
-    const char*                         pLayerPrefix,
-    const char*                         pMsg,
-    void*                               pUserData);
-
-#endif // VK_PROTOTYPES
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // __VK_DEBUG_REPORT_LUNARG_H__
diff --git a/vulkan/include/vulkan/vk_ext_debug_report.h b/vulkan/include/vulkan/vk_ext_debug_report.h
index 40d0df3..c391033 100644
--- a/vulkan/include/vulkan/vk_ext_debug_report.h
+++ b/vulkan/include/vulkan/vk_ext_debug_report.h
@@ -47,8 +47,7 @@
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
-#define VK_EXT_DEBUG_REPORT_REVISION      2
-#define VK_EXT_DEBUG_REPORT_EXTENSION_NUMBER 11
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION    2
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
 
 
@@ -85,8 +84,8 @@
 } VkDebugReportObjectTypeEXT;
 
 typedef enum VkDebugReportErrorEXT {
-    VK_DEBUG_REPORT_ERROR_NONE = 0,
-    VK_DEBUG_REPORT_ERROR_CALLBACK_REF = 1,
+    VK_DEBUG_REPORT_ERROR_NONE_EXT = 0,
+    VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1,
 } VkDebugReportErrorEXT;
 
 typedef enum VkDebugReportFlagBitsEXT {
@@ -106,7 +105,7 @@
     int32_t                                     messageCode,
     const char*                                 pLayerPrefix,
     const char*                                 pMessage,
-    const void*                                 pUserData);
+    void*                                       pUserData);
 
 
 typedef struct VkDebugReportCallbackCreateInfoEXT {
@@ -114,7 +113,7 @@
     const void*                                 pNext;
     VkDebugReportFlagsEXT                       flags;
     PFN_vkDebugReportCallbackEXT                pfnCallback;
-    const void*                                 pUserData;
+    void*                                       pUserData;
 } VkDebugReportCallbackCreateInfoEXT;
 
 typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
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");
diff --git a/vulkan/nulldrv/Android.mk b/vulkan/nulldrv/Android.mk
index 2db6138..77d4746 100644
--- a/vulkan/nulldrv/Android.mk
+++ b/vulkan/nulldrv/Android.mk
@@ -16,12 +16,13 @@
 include $(CLEAR_VARS)
 
 LOCAL_CLANG := true
-LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
-LOCAL_CFLAGS += -DLOG_TAG=\"vknulldrv\"
-LOCAL_CFLAGS += -Weverything -Werror \
+LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing \
+	-DLOG_TAG=\"vknulldrv\" \
+	-Weverything -Werror \
 	-Wno-padded \
 	-Wno-undef \
 	-Wno-zero-length-array
+#LOCAL_CFLAGS += -DLOG_NDEBUG=0
 LOCAL_CPPFLAGS := -std=c++1y \
 	-Wno-c++98-compat-pedantic \
 	-Wno-c99-extensions
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 93168ba..1b19d9a 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -15,13 +15,13 @@
  */
 
 #include <hardware/hwvulkan.h>
+#include <vulkan/vk_ext_debug_report.h>
 
-#include <inttypes.h>
-#include <string.h>
 #include <algorithm>
 #include <array>
+#include <inttypes.h>
+#include <string.h>
 
-// #define LOG_NDEBUG 0
 #include <log/log.h>
 #include <utils/Errors.h>
 
@@ -37,6 +37,8 @@
     hwvulkan_dispatch_t dispatch;
     VkAllocationCallbacks allocator;
     VkPhysicalDevice_T physical_device;
+    uint64_t next_callback_handle;
+    bool debug_report_enabled;
 };
 
 struct VkQueue_T {
@@ -67,6 +69,7 @@
 namespace HandleType {
 enum Enum {
     kBufferView,
+    kDebugReportCallbackEXT,
     kDescriptorPool,
     kDescriptorSet,
     kDescriptorSetLayout,
@@ -86,7 +89,6 @@
     kNumTypes
 };
 }  // namespace HandleType
-uint64_t AllocHandle(VkDevice device, HandleType::Enum type);
 
 const VkDeviceSize kMaxDeviceMemory = VkDeviceSize(INTPTR_MAX) + 1;
 
@@ -164,14 +166,26 @@
         offsetof(VkInstance_T, physical_device));
 }
 
+uint64_t AllocHandle(uint64_t type, uint64_t* next_handle) {
+    const uint64_t kHandleMask = (UINT64_C(1) << 56) - 1;
+    ALOGE_IF(*next_handle == kHandleMask,
+             "non-dispatchable handles of type=%" PRIu64
+             " are about to overflow",
+             type);
+    return (UINT64_C(1) << 63) | ((type & 0x7) << 56) |
+           ((*next_handle)++ & kHandleMask);
+}
+
+template <class Handle>
+Handle AllocHandle(VkInstance instance, HandleType::Enum type) {
+    return reinterpret_cast<Handle>(
+        AllocHandle(type, &instance->next_callback_handle));
+}
+
 template <class Handle>
 Handle AllocHandle(VkDevice device, HandleType::Enum type) {
-    const uint64_t kHandleMask = (UINT64_C(1) << 56) - 1;
-    ALOGE_IF(device->next_handle[type] == kHandleMask,
-             "non-dispatchable handles of type=%u are about to overflow", type);
     return reinterpret_cast<Handle>(
-        (UINT64_C(1) << 63) | ((uint64_t(type) & 0x7) << 56) |
-        (device->next_handle[type]++ & kHandleMask));
+        AllocHandle(type, &device->next_handle[type]));
 }
 
 }  // namespace
@@ -192,15 +206,33 @@
 // Global
 
 VKAPI_ATTR
-VkResult EnumerateInstanceExtensionProperties(const char*,
-                                              uint32_t* count,
-                                              VkExtensionProperties*) {
-    *count = 0;
-    return VK_SUCCESS;
+VkResult EnumerateInstanceExtensionProperties(
+    const char* layer_name,
+    uint32_t* count,
+    VkExtensionProperties* properties) {
+    if (layer_name) {
+        ALOGW(
+            "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
+            "with a layer name ('%s')",
+            layer_name);
+        *count = 0;
+        return VK_SUCCESS;
+    }
+
+    const VkExtensionProperties kExtensions[] = {
+        {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
+    const uint32_t kExtensionsCount =
+        sizeof(kExtensions) / sizeof(kExtensions[0]);
+
+    if (!properties || *count > kExtensionsCount)
+        *count = kExtensionsCount;
+    if (properties)
+        std::copy(kExtensions, kExtensions + *count, properties);
+    return *count < kExtensionsCount ? VK_INCOMPLETE : VK_SUCCESS;
 }
 
 VKAPI_ATTR
-VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
+VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
                         const VkAllocationCallbacks* allocator,
                         VkInstance* out_instance) {
     // Assume the loader provided alloc callbacks even if the app didn't.
@@ -218,6 +250,16 @@
     instance->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
     instance->allocator = *allocator;
     instance->physical_device.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    instance->next_callback_handle = 0;
+    instance->debug_report_enabled = false;
+
+    for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
+        if (strcmp(create_info->ppEnabledExtensionNames[i],
+                   VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
+            ALOGV("Enabling " VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+            instance->debug_report_enabled = true;
+        }
+    }
 
     *out_instance = instance;
     return VK_SUCCESS;
@@ -269,13 +311,15 @@
     VkPhysicalDevice,
     uint32_t* count,
     VkQueueFamilyProperties* properties) {
-    if (properties) {
+    if (!properties || *count > 1)
+        *count = 1;
+    if (properties && *count == 1) {
         properties->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT |
                                  VK_QUEUE_TRANSFER_BIT;
         properties->queueCount = 1;
         properties->timestampValidBits = 64;
+        properties->minImageTransferGranularity = VkExtent3D{1, 1, 1};
     }
-    *count = 1;
 }
 
 void GetPhysicalDeviceMemoryProperties(
@@ -707,6 +751,15 @@
     return VK_SUCCESS;
 }
 
+VkResult CreateDebugReportCallbackEXT(VkInstance instance,
+                                      const VkDebugReportCallbackCreateInfoEXT*,
+                                      const VkAllocationCallbacks*,
+                                      VkDebugReportCallbackEXT* callback) {
+    *callback = AllocHandle<VkDebugReportCallbackEXT>(
+        instance, HandleType::kDebugReportCallbackEXT);
+    return VK_SUCCESS;
+}
+
 VkResult GetSwapchainGrallocUsageANDROID(VkDevice,
                                          VkFormat,
                                          VkImageUsageFlags,
@@ -1081,6 +1134,12 @@
 void CmdExecuteCommands(VkCommandBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCommandBuffer* pCmdBuffers) {
 }
 
+void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator) {
+}
+
+void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage) {
+}
+
 #pragma clang diagnostic pop
 // clang-format on
 
diff --git a/vulkan/nulldrv/null_driver.tmpl b/vulkan/nulldrv/null_driver.tmpl
index 66dceb2..57e72d3 100644
--- a/vulkan/nulldrv/null_driver.tmpl
+++ b/vulkan/nulldrv/null_driver.tmpl
@@ -51,6 +51,7 @@
 #define NULLDRV_NULL_DRIVER_H 1

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

 namespace null_driver {«
@@ -216,6 +217,7 @@
 */}}
 {{define "IsDriverExtension"}}
   {{$ext := index $.Arguments 0}}
-  {{if eq $ext "VK_ANDROID_native_buffer"}}true
+  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
+  {{else if eq $ext "VK_EXT_debug_report"}}true
   {{end}}
 {{end}}
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index a96c2c4..c5f42b0 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -110,6 +110,7 @@
     {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateBufferView>(CreateBufferView))},
     {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateCommandPool>(CreateCommandPool))},
     {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateComputePipelines>(CreateComputePipelines))},
+    {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT))},
     {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorPool>(CreateDescriptorPool))},
     {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorSetLayout>(CreateDescriptorSetLayout))},
     {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice))},
@@ -127,9 +128,11 @@
     {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSampler>(CreateSampler))},
     {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSemaphore>(CreateSemaphore))},
     {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateShaderModule>(CreateShaderModule))},
+    {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT))},
     {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyBuffer>(DestroyBuffer))},
     {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyBufferView>(DestroyBufferView))},
     {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyCommandPool>(DestroyCommandPool))},
+    {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT))},
     {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorPool>(DestroyDescriptorPool))},
     {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorSetLayout>(DestroyDescriptorSetLayout))},
     {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice))},
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 62185a5..ddf4afb 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -22,6 +22,7 @@
 #define NULLDRV_NULL_DRIVER_H 1
 
 #include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vk_ext_debug_report.h>
 #include <vulkan/vulkan.h>
 
 namespace null_driver {
@@ -167,6 +168,9 @@
 VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
 VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
 VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);