vknulldrv: implement VkDeviceMemory objects

Change-Id: If9c22b3800058877c7854d59622b7205b79cf731
(cherry picked from commit 4ff851997ef2972b3b846656d93a06e44858259e)
diff --git a/vulkan/nulldrv/Android.mk b/vulkan/nulldrv/Android.mk
index 0ab33fb..a81bcd6 100644
--- a/vulkan/nulldrv/Android.mk
+++ b/vulkan/nulldrv/Android.mk
@@ -4,7 +4,10 @@
 LOCAL_CLANG := true
 LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
 LOCAL_CFLAGS += -DLOG_TAG=\"vknulldrv\"
-LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef
+LOCAL_CFLAGS += -Weverything -Werror \
+	-Wno-padded \
+	-Wno-undef \
+	-Wno-zero-length-array
 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 ec9cae6..69e2c0f 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -237,6 +237,55 @@
 }
 
 // -----------------------------------------------------------------------------
+// DeviceMemory
+
+struct DeviceMemory {
+    typedef VkDeviceMemory HandleType;
+    VkDeviceSize size;
+    alignas(16) uint8_t data[0];
+};
+template <>
+struct HandleTraits<VkDeviceMemory> {
+    typedef DeviceMemory* PointerType;
+};
+
+VkResult AllocMemory(VkDevice device,
+                     const VkMemoryAllocInfo* alloc_info,
+                     VkDeviceMemory* mem_handle) {
+    if (SIZE_MAX - sizeof(DeviceMemory) <= alloc_info->allocationSize)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    const VkAllocCallbacks* alloc = device->instance->alloc;
+    size_t size = sizeof(DeviceMemory) + size_t(alloc_info->allocationSize);
+    DeviceMemory* mem = static_cast<DeviceMemory*>(
+        alloc->pfnAlloc(alloc->pUserData, size, alignof(DeviceMemory),
+                        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
+    if (!mem)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    mem->size = size;
+    *mem_handle = GetHandleToObject(mem);
+    return VK_SUCCESS;
+}
+
+VkResult FreeMemory(VkDevice device, VkDeviceMemory mem_handle) {
+    const VkAllocCallbacks* alloc = device->instance->alloc;
+    DeviceMemory* mem = GetObjectFromHandle(mem_handle);
+    alloc->pfnFree(alloc->pUserData, mem);
+    return VK_SUCCESS;
+}
+
+VkResult MapMemory(VkDevice,
+                   VkDeviceMemory mem_handle,
+                   VkDeviceSize offset,
+                   VkDeviceSize,
+                   VkMemoryMapFlags,
+                   void** out_ptr) {
+    DeviceMemory* mem = GetObjectFromHandle(mem_handle);
+    *out_ptr = &mem->data[0] + offset;
+    return VK_SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
 // Buffer
 
 struct Buffer {
@@ -346,23 +395,7 @@
     return VK_SUCCESS;
 }
 
-VkResult AllocMemory(VkDevice device, const VkMemoryAllocInfo* pAllocInfo, VkDeviceMemory* pMem) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
-    return VK_SUCCESS;
-}
-
-VkResult FreeMemory(VkDevice device, VkDeviceMemory mem) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
-    return VK_SUCCESS;
-}
-
-VkResult MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
-    return VK_SUCCESS;
-}
-
 VkResult UnmapMemory(VkDevice device, VkDeviceMemory mem) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }
 
@@ -382,7 +415,6 @@
 }
 
 VkResult BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }