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/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);