vulkan: Set up VkCmdBuffer dispatching

Change-Id: Ifb3cea05dab8828c2c00b8ed60c5ad991cdcbea7
(cherry picked from commit 10bf73e13b6904afa606fdcdc05bcc510c605180)
diff --git a/vulkan/libvulkan/entry.cpp b/vulkan/libvulkan/entry.cpp
index 7bfaaf2..f2b4482 100644
--- a/vulkan/libvulkan/entry.cpp
+++ b/vulkan/libvulkan/entry.cpp
@@ -578,7 +578,7 @@
 
 __attribute__((visibility("default")))
 VkResult vkCreateCommandBuffer(VkDevice device, const VkCmdBufferCreateInfo* pCreateInfo, VkCmdBuffer* pCmdBuffer) {
-    return GetVtbl(device).CreateCommandBuffer(device, pCreateInfo, pCmdBuffer);
+    return vulkan::CreateCommandBuffer(device, pCreateInfo, pCmdBuffer);
 }
 
 __attribute__((visibility("default")))
diff --git a/vulkan/libvulkan/entry.cpp.tmpl b/vulkan/libvulkan/entry.cpp.tmpl
index 249f8fd..3eabe2e 100644
--- a/vulkan/libvulkan/entry.cpp.tmpl
+++ b/vulkan/libvulkan/entry.cpp.tmpl
@@ -73,7 +73,7 @@
 */}}
 {{define "IsSpecialEntry"}}
   {{/* TODO: figure out how to do this in a cleaner or at least multi-line way */}}
-  {{if or (eq $ "vkGetInstanceProcAddr") (or (eq $ "vkGetDeviceProcAddr") (or (eq $ "vkGetDeviceQueue") (eq $ "vkDestroyDevice")))}}
+  {{if or (eq $ "vkGetInstanceProcAddr") (or (eq $ "vkGetDeviceProcAddr") (or (eq $ "vkGetDeviceQueue") (or (eq $ "vkCreateCommandBuffer") (eq $ "vkDestroyDevice"))))}}
     true
   {{end}}
 {{end}}
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index a99e90a..19ca9f2 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -494,6 +494,7 @@
         return GetGlobalDeviceProcAddr(name);
     // For special-case functions we always return the loader entry
     if (strcmp(name, "vkGetDeviceQueue") == 0 ||
+        strcmp(name, "vkCreateCommandBuffer") == 0 ||
         strcmp(name, "vkDestroyDevice") == 0) {
         return GetGlobalDeviceProcAddr(name);
     }
@@ -521,6 +522,27 @@
     return VK_SUCCESS;
 }
 
+VkResult CreateCommandBuffer(VkDevice drv_device,
+                             const VkCmdBufferCreateInfo* create_info,
+                             VkCmdBuffer* out_cmdbuf) {
+    const DeviceVtbl* vtbl = GetVtbl(drv_device);
+    VkCmdBuffer cmdbuf;
+    VkResult result =
+        vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
+    if (result != VK_SUCCESS)
+        return result;
+    hwvulkan_dispatch_t* dispatch =
+        reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
+    if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
+        ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
+              dispatch->magic);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    dispatch->vtbl = vtbl;
+    *out_cmdbuf = cmdbuf;
+    return VK_SUCCESS;
+}
+
 VkResult DestroyDevice(VkDevice drv_device) {
     const DeviceVtbl* vtbl = GetVtbl(drv_device);
     Device* device = static_cast<Device*>(vtbl->device);
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index 1f6a1d4..fad92a7 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -187,6 +187,9 @@
                         uint32_t family,
                         uint32_t index,
                         VkQueue* out_queue);
+VkResult CreateCommandBuffer(VkDevice device,
+                             const VkCmdBufferCreateInfo* create_info,
+                             VkCmdBuffer* out_cmdbuf);
 VkResult DestroyDevice(VkDevice drv_device);
 
 // -----------------------------------------------------------------------------
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 281873d..ad7011f 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -48,36 +48,36 @@
 // Using a namespace here instead of 'enum class' since we want scoped
 // constants but also want implicit conversions to integral types.
 namespace HandleType {
-    enum Enum {
-        kAttachmentView,
-        kBufferView,
-        kCmdPool,
-        kDescriptorPool,
-        kDescriptorSet,
-        kDescriptorSetLayout,
-        kDynamicColorBlendState,
-        kDynamicDepthStencilState,
-        kDynamicRasterState,
-        kDynamicViewportState,
-        kEvent,
-        kFence,
-        kFramebuffer,
-        kImageView,
-        kPipeline,
-        kPipelineCache,
-        kPipelineLayout,
-        kQueryPool,
-        kRenderPass,
-        kSampler,
-        kSemaphore,
-        kShader,
-        kShaderModule,
+enum Enum {
+    kAttachmentView,
+    kBufferView,
+    kCmdPool,
+    kDescriptorPool,
+    kDescriptorSet,
+    kDescriptorSetLayout,
+    kDynamicColorBlendState,
+    kDynamicDepthStencilState,
+    kDynamicRasterState,
+    kDynamicViewportState,
+    kEvent,
+    kFence,
+    kFramebuffer,
+    kImageView,
+    kPipeline,
+    kPipelineCache,
+    kPipelineLayout,
+    kQueryPool,
+    kRenderPass,
+    kSampler,
+    kSemaphore,
+    kShader,
+    kShaderModule,
 
-        kNumTypes
-    };
-} // namespace HandleType
+    kNumTypes
+};
+}  // namespace HandleType
 uint64_t AllocHandle(VkDevice device, HandleType::Enum type);
-} // anonymous namespace
+}  // anonymous namespace
 
 struct VkDevice_T {
     hwvulkan_dispatch_t dispatch;
@@ -299,6 +299,29 @@
 }
 
 // -----------------------------------------------------------------------------
+// CmdBuffer
+
+VkResult CreateCommandBuffer(VkDevice device,
+                             const VkCmdBufferCreateInfo*,
+                             VkCmdBuffer* out_cmdbuf) {
+    const VkAllocCallbacks* alloc = device->instance->alloc;
+    VkCmdBuffer_T* cmdbuf = static_cast<VkCmdBuffer_T*>(alloc->pfnAlloc(
+        alloc->pUserData, sizeof(VkCmdBuffer_T), alignof(VkCmdBuffer_T),
+        VK_SYSTEM_ALLOC_TYPE_API_OBJECT));
+    if (!cmdbuf)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    cmdbuf->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    *out_cmdbuf = cmdbuf;
+    return VK_SUCCESS;
+}
+
+VkResult DestroyCommandBuffer(VkDevice device, VkCmdBuffer cmdbuf) {
+    const VkAllocCallbacks* alloc = device->instance->alloc;
+    alloc->pfnFree(alloc->pUserData, cmdbuf);
+    return VK_SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
 // DeviceMemory
 
 struct DeviceMemory {
@@ -629,7 +652,6 @@
 }
 
 VkResult QueueSubmit(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }
 
@@ -706,7 +728,6 @@
 }
 
 VkResult ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }
 
@@ -716,7 +737,6 @@
 }
 
 VkResult WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }
 
@@ -889,23 +909,11 @@
     return VK_SUCCESS;
 }
 
-VkResult CreateCommandBuffer(VkDevice device, const VkCmdBufferCreateInfo* pCreateInfo, VkCmdBuffer* pCmdBuffer) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
-    return VK_SUCCESS;
-}
-
-VkResult DestroyCommandBuffer(VkDevice device, VkCmdBuffer commandBuffer) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
-    return VK_SUCCESS;
-}
-
 VkResult BeginCommandBuffer(VkCmdBuffer cmdBuffer, const VkCmdBufferBeginInfo* pBeginInfo) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }
 
 VkResult EndCommandBuffer(VkCmdBuffer cmdBuffer) {
-    ALOGV("TODO: vk%s", __FUNCTION__);
     return VK_SUCCESS;
 }