turnip: add tu_cs_add_bo
[mesa.git] / src / freedreno / vulkan / tu_device.c
index 235aa44dbd70da4071d22d03993fa13fa835f282..d5533028a6216095c4414b40a7ac276647404eee 100644 (file)
  * 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.
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  */
 
 #include "tu_private.h"
-#include "util/debug.h"
-#include "util/disk_cache.h"
-#include "util/strtod.h"
-#include "vk_format.h"
-#include "vk_util.h"
+
 #include <fcntl.h>
+#include <libsync.h>
 #include <stdbool.h>
 #include <string.h>
+#include <sys/mman.h>
 #include <sys/sysinfo.h>
 #include <unistd.h>
 #include <xf86drm.h>
 
+#include "util/debug.h"
+#include "util/disk_cache.h"
+#include "util/strtod.h"
+#include "vk_format.h"
+#include "vk_util.h"
+
+#include "drm/msm_drm.h"
+
 static int
 tu_device_get_cache_uuid(uint16_t family, void *uuid)
 {
@@ -49,8 +55,8 @@ tu_device_get_cache_uuid(uint16_t family, void *uuid)
       return -1;
 
    memcpy(uuid, &mesa_timestamp, 4);
-   memcpy((char *)uuid + 4, &f, 2);
-   snprintf((char *)uuid + 6, VK_UUID_SIZE - 10, "tu");
+   memcpy((char *) uuid + 4, &f, 2);
+   snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "tu");
    return 0;
 }
 
@@ -58,46 +64,100 @@ static void
 tu_get_driver_uuid(void *uuid)
 {
    memset(uuid, 0, VK_UUID_SIZE);
+   snprintf(uuid, VK_UUID_SIZE, "freedreno");
 }
 
 static void
 tu_get_device_uuid(void *uuid)
 {
-   stub();
+   memset(uuid, 0, VK_UUID_SIZE);
+}
+
+VkResult
+tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
+{
+   /* TODO: Choose better flags. As of 2018-11-12, freedreno/drm/msm_bo.c
+    * always sets `flags = MSM_BO_WC`, and we copy that behavior here.
+    */
+   uint32_t gem_handle = tu_gem_new(dev, size, MSM_BO_WC);
+   if (!gem_handle)
+      goto fail_new;
+
+   uint64_t iova = tu_gem_info_iova(dev, gem_handle);
+   if (!iova)
+      goto fail_info;
+
+   *bo = (struct tu_bo) {
+      .gem_handle = gem_handle,
+      .size = size,
+      .iova = iova,
+   };
+
+   return VK_SUCCESS;
+
+fail_info:
+   tu_gem_close(dev, bo->gem_handle);
+fail_new:
+   return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+}
+
+VkResult
+tu_bo_map(struct tu_device *dev, struct tu_bo *bo)
+{
+   if (bo->map)
+      return VK_SUCCESS;
+
+   uint64_t offset = tu_gem_info_offset(dev, bo->gem_handle);
+   if (!offset)
+          return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+
+   /* TODO: Should we use the wrapper os_mmap() like Freedreno does? */
+   void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                    dev->physical_device->local_fd, offset);
+   if (map == MAP_FAILED)
+      return vk_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
+
+   bo->map = map;
+   return VK_SUCCESS;
+}
+
+void
+tu_bo_finish(struct tu_device *dev, struct tu_bo *bo)
+{
+   assert(bo->gem_handle);
+
+   if (bo->map)
+      munmap(bo->map, bo->size);
+
+   tu_gem_close(dev, bo->gem_handle);
 }
 
 static VkResult
 tu_physical_device_init(struct tu_physical_device *device,
-                         struct tu_instance *instance,
-                         drmDevicePtr drm_device)
+                        struct tu_instance *instance,
+                        drmDevicePtr drm_device)
 {
    const char *path = drm_device->nodes[DRM_NODE_RENDER];
-   VkResult result;
+   VkResult result = VK_SUCCESS;
    drmVersionPtr version;
    int fd;
    int master_fd = -1;
-   struct fd_pipe *tmp_pipe = NULL;
-   uint64_t val;
 
    fd = open(path, O_RDWR | O_CLOEXEC);
    if (fd < 0) {
-      if (instance->debug_flags & TU_DEBUG_STARTUP)
-         tu_logi("Could not open device '%s'", path);
-
-      return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);
+      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
+                       "failed to open device %s", path);
    }
 
+   /* Version 1.3 added MSM_INFO_IOVA. */
+   const int min_version_major = 1;
+   const int min_version_minor = 3;
+
    version = drmGetVersion(fd);
    if (!version) {
       close(fd);
-
-      if (instance->debug_flags & TU_DEBUG_STARTUP)
-         tu_logi("Could not get the kernel driver version for device '%s'",
-                  path);
-
-      return vk_errorf(instance,
-                       VK_ERROR_INCOMPATIBLE_DRIVER,
-                       "failed to get version %s: %m",
+      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
+                       "failed to query kernel driver version for device %s",
                        path);
    }
 
@@ -106,12 +166,22 @@ tu_physical_device_init(struct tu_physical_device *device,
       if (master_fd != -1)
          close(master_fd);
       close(fd);
+      return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
+                       "device %s does not use the msm kernel driver", path);
+   }
 
-      if (instance->debug_flags & TU_DEBUG_STARTUP)
-         tu_logi("Device '%s' is not using the msm kernel driver.", path);
-
-      return VK_ERROR_INCOMPATIBLE_DRIVER;
+   if (version->version_major != min_version_major ||
+       version->version_minor < min_version_minor) {
+      result = vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
+                         "kernel driver for device %s has version %d.%d, "
+                         "but Vulkan requires version >= %d.%d",
+                         path, version->version_major, version->version_minor,
+                         min_version_major, min_version_minor);
+      drmFreeVersion(version);
+      close(fd);
+      return result;
    }
+
    drmFreeVersion(version);
 
    if (instance->debug_flags & TU_DEBUG_STARTUP)
@@ -123,7 +193,8 @@ tu_physical_device_init(struct tu_physical_device *device,
    strncpy(device->path, path, ARRAY_SIZE(device->path));
 
    if (instance->enabled_extensions.KHR_display) {
-      master_fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
+      master_fd =
+         open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
       if (master_fd >= 0) {
          /* TODO: free master_fd is accel is not working? */
       }
@@ -132,53 +203,37 @@ tu_physical_device_init(struct tu_physical_device *device,
    device->master_fd = master_fd;
    device->local_fd = fd;
 
-   device->drm_device = fd_device_new_dup(fd);
-   if (!device->drm_device) {
-      result = vk_errorf(
-        instance, VK_ERROR_INITIALIZATION_FAILED, "could not create the libdrm device");
-       goto fail;
-   }
-
-   tmp_pipe = fd_pipe_new(device->drm_device, FD_PIPE_3D);
-   if (!tmp_pipe) {
-      result = vk_errorf(
-        instance, VK_ERROR_INITIALIZATION_FAILED, "could not open the 3D pipe");
-      goto fail;
-   }
-
-   if (fd_pipe_get_param(tmp_pipe, FD_GPU_ID, &val)) {
-      result = vk_errorf(
-        instance, VK_ERROR_INITIALIZATION_FAILED, "could not get GPU ID");
+   if (tu_drm_get_gpu_id(device, &device->gpu_id)) {
+      if (instance->debug_flags & TU_DEBUG_STARTUP)
+         tu_logi("Could not query the GPU ID");
+      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
+                         "could not get GPU ID");
       goto fail;
    }
-   device->gpu_id = val;
 
-   if (fd_pipe_get_param(tmp_pipe, FD_GMEM_SIZE, &val)) {
-      result = vk_errorf(
-        instance, VK_ERROR_INITIALIZATION_FAILED, "could not get GMEM size");
+   if (tu_drm_get_gmem_size(device, &device->gmem_size)) {
+      if (instance->debug_flags & TU_DEBUG_STARTUP)
+         tu_logi("Could not query the GMEM size");
+      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
+                         "could not get GMEM size");
       goto fail;
    }
-   device->gmem_size = val;
-
-   fd_pipe_del(tmp_pipe);
-   tmp_pipe = NULL;
 
    memset(device->name, 0, sizeof(device->name));
    sprintf(device->name, "FD%d", device->gpu_id);
 
-   switch(device->gpu_id) {
+   switch (device->gpu_id) {
    case 530:
+   case 630:
       break;
    default:
-      if (instance->debug_flags & TU_DEBUG_STARTUP)
-         tu_logi("Device '%s' is not supported.", device->name);
-      result = vk_errorf(
-        instance, VK_ERROR_INITIALIZATION_FAILED, "unsupported device");
+      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
+                         "device %s is unsupported", device->name);
       goto fail;
    }
    if (tu_device_get_cache_uuid(device->gpu_id, device->cache_uuid)) {
-      result = vk_errorf(
-        instance, VK_ERROR_INITIALIZATION_FAILED, "cannot generate UUID");
+      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
+                         "cannot generate UUID");
       goto fail;
    }
 
@@ -189,9 +244,8 @@ tu_physical_device_init(struct tu_physical_device *device,
    disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2);
    device->disk_cache = disk_cache_create(device->name, buf, 0);
 
-   fprintf(stderr,
-           "WARNING: tu is not a conformant vulkan implementation, "
-           "testing use only.\n");
+   fprintf(stderr, "WARNING: tu is not a conformant vulkan implementation, "
+                   "testing use only.\n");
 
    tu_get_driver_uuid(&device->device_uuid);
    tu_get_device_uuid(&device->device_uuid);
@@ -206,10 +260,6 @@ tu_physical_device_init(struct tu_physical_device *device,
    return VK_SUCCESS;
 
 fail:
-   if (tmp_pipe)
-      fd_pipe_del(tmp_pipe);
-   if (device->drm_device)
-      fd_device_del(device->drm_device);
    close(fd);
    if (master_fd != -1)
       close(master_fd);
@@ -257,9 +307,9 @@ static const VkAllocationCallbacks default_alloc = {
    .pfnFree = default_free_func,
 };
 
-static const struct debug_control tu_debug_options[] = { { "startup",
-                                                            TU_DEBUG_STARTUP },
-                                                          { NULL, 0 } };
+static const struct debug_control tu_debug_options[] = {
+   { "startup", TU_DEBUG_STARTUP }, { NULL, 0 }
+};
 
 const char *
 tu_get_debug_option_name(int id)
@@ -280,8 +330,8 @@ tu_get_instance_extension_index(const char *name)
 
 VkResult
 tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
-                   const VkAllocationCallbacks *pAllocator,
-                   VkInstance *pInstance)
+                  const VkAllocationCallbacks *pAllocator,
+                  VkInstance *pInstance)
 {
    struct tu_instance *instance;
    VkResult result;
@@ -296,10 +346,7 @@ tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
       tu_EnumerateInstanceVersion(&client_version);
    }
 
-   instance = vk_zalloc2(&default_alloc,
-                         pAllocator,
-                         sizeof(*instance),
-                         8,
+   instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
                          VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    if (!instance)
       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -315,7 +362,7 @@ tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
    instance->physical_device_count = -1;
 
    instance->debug_flags =
-     parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);
+      parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);
 
    if (instance->debug_flags & TU_DEBUG_STARTUP)
       tu_logi("Created an instance");
@@ -349,7 +396,7 @@ tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
 
 void
 tu_DestroyInstance(VkInstance _instance,
-                    const VkAllocationCallbacks *pAllocator)
+                   const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
 
@@ -387,14 +434,13 @@ tu_enumerate_devices(struct tu_instance *instance)
    if (max_devices < 1)
       return vk_error(instance, VK_ERROR_INCOMPATIBLE_DRIVER);
 
-   for (unsigned i = 0; i < (unsigned)max_devices; i++) {
+   for (unsigned i = 0; i < (unsigned) max_devices; i++) {
       if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
           devices[i]->bustype == DRM_BUS_PLATFORM) {
 
-         result = tu_physical_device_init(instance->physical_devices +
-                                             instance->physical_device_count,
-                                           instance,
-                                           devices[i]);
+         result = tu_physical_device_init(
+            instance->physical_devices + instance->physical_device_count,
+            instance, devices[i]);
          if (result == VK_SUCCESS)
             ++instance->physical_device_count;
          else if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
@@ -408,10 +454,12 @@ tu_enumerate_devices(struct tu_instance *instance)
 
 VkResult
 tu_EnumeratePhysicalDevices(VkInstance _instance,
-                             uint32_t *pPhysicalDeviceCount,
-                             VkPhysicalDevice *pPhysicalDevices)
+                            uint32_t *pPhysicalDeviceCount,
+                            VkPhysicalDevice *pPhysicalDevices)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
+   VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
+
    VkResult result;
 
    if (instance->physical_device_count < 0) {
@@ -420,28 +468,25 @@ tu_EnumeratePhysicalDevices(VkInstance _instance,
          return result;
    }
 
-   if (!pPhysicalDevices) {
-      *pPhysicalDeviceCount = instance->physical_device_count;
-   } else {
-      *pPhysicalDeviceCount =
-        MIN2(*pPhysicalDeviceCount, instance->physical_device_count);
-      for (unsigned i = 0; i < *pPhysicalDeviceCount; ++i)
-         pPhysicalDevices[i] =
-           tu_physical_device_to_handle(instance->physical_devices + i);
+   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
+      vk_outarray_append(&out, p)
+      {
+         *p = tu_physical_device_to_handle(instance->physical_devices + i);
+      }
    }
 
-   return *pPhysicalDeviceCount < instance->physical_device_count
-            ? VK_INCOMPLETE
-            : VK_SUCCESS;
+   return vk_outarray_status(&out);
 }
 
 VkResult
 tu_EnumeratePhysicalDeviceGroups(
-  VkInstance _instance,
-  uint32_t *pPhysicalDeviceGroupCount,
-  VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
+   VkInstance _instance,
+   uint32_t *pPhysicalDeviceGroupCount,
+   VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
+   VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
+                    pPhysicalDeviceGroupCount);
    VkResult result;
 
    if (instance->physical_device_count < 0) {
@@ -450,30 +495,26 @@ tu_EnumeratePhysicalDeviceGroups(
          return result;
    }
 
-   if (!pPhysicalDeviceGroupProperties) {
-      *pPhysicalDeviceGroupCount = instance->physical_device_count;
-   } else {
-      *pPhysicalDeviceGroupCount =
-        MIN2(*pPhysicalDeviceGroupCount, instance->physical_device_count);
-      for (unsigned i = 0; i < *pPhysicalDeviceGroupCount; ++i) {
-         pPhysicalDeviceGroupProperties[i].physicalDeviceCount = 1;
-         pPhysicalDeviceGroupProperties[i].physicalDevices[0] =
-           tu_physical_device_to_handle(instance->physical_devices + i);
-         pPhysicalDeviceGroupProperties[i].subsetAllocation = false;
+   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
+      vk_outarray_append(&out, p)
+      {
+         p->physicalDeviceCount = 1;
+         p->physicalDevices[0] =
+            tu_physical_device_to_handle(instance->physical_devices + i);
+         p->subsetAllocation = false;
       }
    }
-   return *pPhysicalDeviceGroupCount < instance->physical_device_count
-            ? VK_INCOMPLETE
-            : VK_SUCCESS;
+
+   return vk_outarray_status(&out);
 }
 
 void
 tu_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
-                              VkPhysicalDeviceFeatures *pFeatures)
+                             VkPhysicalDeviceFeatures *pFeatures)
 {
    memset(pFeatures, 0, sizeof(*pFeatures));
 
-   *pFeatures = (VkPhysicalDeviceFeatures){
+   *pFeatures = (VkPhysicalDeviceFeatures) {
       .robustBufferAccess = false,
       .fullDrawIndexUint32 = false,
       .imageCubeArray = false,
@@ -524,86 +565,86 @@ tu_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
 
 void
 tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
-                               VkPhysicalDeviceFeatures2KHR *pFeatures)
+                              VkPhysicalDeviceFeatures2KHR *pFeatures)
 {
    vk_foreach_struct(ext, pFeatures->pNext)
    {
       switch (ext->sType) {
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR: {
-            VkPhysicalDeviceVariablePointerFeaturesKHR *features = (void *)ext;
-            features->variablePointersStorageBuffer = true;
-            features->variablePointers = false;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR: {
-            VkPhysicalDeviceMultiviewFeaturesKHR *features =
-              (VkPhysicalDeviceMultiviewFeaturesKHR *)ext;
-            features->multiview = true;
-            features->multiviewGeometryShader = true;
-            features->multiviewTessellationShader = true;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES: {
-            VkPhysicalDeviceShaderDrawParameterFeatures *features =
-              (VkPhysicalDeviceShaderDrawParameterFeatures *)ext;
-            features->shaderDrawParameters = true;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
-            VkPhysicalDeviceProtectedMemoryFeatures *features =
-              (VkPhysicalDeviceProtectedMemoryFeatures *)ext;
-            features->protectedMemory = false;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
-            VkPhysicalDevice16BitStorageFeatures *features =
-              (VkPhysicalDevice16BitStorageFeatures *)ext;
-            features->storageBuffer16BitAccess = false;
-            features->uniformAndStorageBuffer16BitAccess = false;
-            features->storagePushConstant16 = false;
-            features->storageInputOutput16 = false;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
-            VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
-              (VkPhysicalDeviceSamplerYcbcrConversionFeatures *)ext;
-            features->samplerYcbcrConversion = false;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
-            VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =
-              (VkPhysicalDeviceDescriptorIndexingFeaturesEXT *)ext;
-            features->shaderInputAttachmentArrayDynamicIndexing = true;
-            features->shaderUniformTexelBufferArrayDynamicIndexing = true;
-            features->shaderStorageTexelBufferArrayDynamicIndexing = true;
-            features->shaderUniformBufferArrayNonUniformIndexing = false;
-            features->shaderSampledImageArrayNonUniformIndexing = false;
-            features->shaderStorageBufferArrayNonUniformIndexing = false;
-            features->shaderStorageImageArrayNonUniformIndexing = false;
-            features->shaderInputAttachmentArrayNonUniformIndexing = false;
-            features->shaderUniformTexelBufferArrayNonUniformIndexing = false;
-            features->shaderStorageTexelBufferArrayNonUniformIndexing = false;
-            features->descriptorBindingUniformBufferUpdateAfterBind = true;
-            features->descriptorBindingSampledImageUpdateAfterBind = true;
-            features->descriptorBindingStorageImageUpdateAfterBind = true;
-            features->descriptorBindingStorageBufferUpdateAfterBind = true;
-            features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;
-            features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;
-            features->descriptorBindingUpdateUnusedWhilePending = true;
-            features->descriptorBindingPartiallyBound = true;
-            features->descriptorBindingVariableDescriptorCount = true;
-            features->runtimeDescriptorArray = true;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
-            VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
-              (VkPhysicalDeviceConditionalRenderingFeaturesEXT *)ext;
-            features->conditionalRendering = true;
-            features->inheritedConditionalRendering = false;
-            break;
-         }
-         default:
-            break;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR: {
+         VkPhysicalDeviceVariablePointerFeaturesKHR *features = (void *) ext;
+         features->variablePointersStorageBuffer = false;
+         features->variablePointers = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR: {
+         VkPhysicalDeviceMultiviewFeaturesKHR *features =
+            (VkPhysicalDeviceMultiviewFeaturesKHR *) ext;
+         features->multiview = false;
+         features->multiviewGeometryShader = false;
+         features->multiviewTessellationShader = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES: {
+         VkPhysicalDeviceShaderDrawParameterFeatures *features =
+            (VkPhysicalDeviceShaderDrawParameterFeatures *) ext;
+         features->shaderDrawParameters = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
+         VkPhysicalDeviceProtectedMemoryFeatures *features =
+            (VkPhysicalDeviceProtectedMemoryFeatures *) ext;
+         features->protectedMemory = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
+         VkPhysicalDevice16BitStorageFeatures *features =
+            (VkPhysicalDevice16BitStorageFeatures *) ext;
+         features->storageBuffer16BitAccess = false;
+         features->uniformAndStorageBuffer16BitAccess = false;
+         features->storagePushConstant16 = false;
+         features->storageInputOutput16 = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
+         VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
+            (VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;
+         features->samplerYcbcrConversion = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
+         VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =
+            (VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;
+         features->shaderInputAttachmentArrayDynamicIndexing = false;
+         features->shaderUniformTexelBufferArrayDynamicIndexing = false;
+         features->shaderStorageTexelBufferArrayDynamicIndexing = false;
+         features->shaderUniformBufferArrayNonUniformIndexing = false;
+         features->shaderSampledImageArrayNonUniformIndexing = false;
+         features->shaderStorageBufferArrayNonUniformIndexing = false;
+         features->shaderStorageImageArrayNonUniformIndexing = false;
+         features->shaderInputAttachmentArrayNonUniformIndexing = false;
+         features->shaderUniformTexelBufferArrayNonUniformIndexing = false;
+         features->shaderStorageTexelBufferArrayNonUniformIndexing = false;
+         features->descriptorBindingUniformBufferUpdateAfterBind = false;
+         features->descriptorBindingSampledImageUpdateAfterBind = false;
+         features->descriptorBindingStorageImageUpdateAfterBind = false;
+         features->descriptorBindingStorageBufferUpdateAfterBind = false;
+         features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
+         features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
+         features->descriptorBindingUpdateUnusedWhilePending = false;
+         features->descriptorBindingPartiallyBound = false;
+         features->descriptorBindingVariableDescriptorCount = false;
+         features->runtimeDescriptorArray = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
+         VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
+            (VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
+         features->conditionalRendering = false;
+         features->inheritedConditionalRendering = false;
+         break;
+      }
+      default:
+         break;
       }
    }
    return tu_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
@@ -611,7 +652,7 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
 
 void
 tu_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
-                                VkPhysicalDeviceProperties *pProperties)
+                               VkPhysicalDeviceProperties *pProperties)
 {
    TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
    VkSampleCountFlags sample_counts = 0xf;
@@ -623,11 +664,11 @@ tu_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
     * there is no set limit, so we just set a pipeline limit. I don't think
     * any app is going to hit this soon. */
    size_t max_descriptor_set_size =
-     ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) /
-     (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
-      32 /* storage buffer, 32 due to potential space wasted on alignment */ +
-      32 /* sampler, largest when combined with image */ +
-      64 /* sampled image */ + 64 /* storage image */);
+      ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) /
+      (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
+       32 /* storage buffer, 32 due to potential space wasted on alignment */ +
+       32 /* sampler, largest when combined with image */ +
+       64 /* sampled image */ + 64 /* storage image */);
 
    VkPhysicalDeviceLimits limits = {
       .maxImageDimension1D = (1 << 14),
@@ -738,7 +779,7 @@ tu_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
       .nonCoherentAtomSize = 64,
    };
 
-   *pProperties = (VkPhysicalDeviceProperties){
+   *pProperties = (VkPhysicalDeviceProperties) {
       .apiVersion = tu_physical_device_api_version(pdevice),
       .driverVersion = vk_get_driver_version(),
       .vendorID = 0, /* TODO */
@@ -754,7 +795,7 @@ tu_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
 
 void
 tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
-                                 VkPhysicalDeviceProperties2KHR *pProperties)
+                                VkPhysicalDeviceProperties2KHR *pProperties)
 {
    TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
    tu_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
@@ -762,117 +803,81 @@ tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
    vk_foreach_struct(ext, pProperties->pNext)
    {
       switch (ext->sType) {
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
-            VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
-              (VkPhysicalDevicePushDescriptorPropertiesKHR *)ext;
-            properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: {
-            VkPhysicalDeviceIDPropertiesKHR *properties =
-              (VkPhysicalDeviceIDPropertiesKHR *)ext;
-            memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
-            memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
-            properties->deviceLUIDValid = false;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR: {
-            VkPhysicalDeviceMultiviewPropertiesKHR *properties =
-              (VkPhysicalDeviceMultiviewPropertiesKHR *)ext;
-            properties->maxMultiviewViewCount = MAX_VIEWS;
-            properties->maxMultiviewInstanceIndex = INT_MAX;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR: {
-            VkPhysicalDevicePointClippingPropertiesKHR *properties =
-              (VkPhysicalDevicePointClippingPropertiesKHR *)ext;
-            properties->pointClippingBehavior =
-              VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR;
-            break;
-         }
-         case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
-            VkPhysicalDeviceMaintenance3Properties *properties =
-              (VkPhysicalDeviceMaintenance3Properties *)ext;
-            /* Make sure everything is addressable by a signed 32-bit int, and
-             * our largest descriptors are 96 bytes. */
-            properties->maxPerSetDescriptors = (1ull << 31) / 96;
-            /* Our buffer size fields allow only this much */
-            properties->maxMemoryAllocationSize = 0xFFFFFFFFull;
-            break;
-         }
-         default:
-            break;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+         VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
+            (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
+         properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: {
+         VkPhysicalDeviceIDPropertiesKHR *properties =
+            (VkPhysicalDeviceIDPropertiesKHR *) ext;
+         memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
+         memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
+         properties->deviceLUIDValid = false;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR: {
+         VkPhysicalDeviceMultiviewPropertiesKHR *properties =
+            (VkPhysicalDeviceMultiviewPropertiesKHR *) ext;
+         properties->maxMultiviewViewCount = MAX_VIEWS;
+         properties->maxMultiviewInstanceIndex = INT_MAX;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR: {
+         VkPhysicalDevicePointClippingPropertiesKHR *properties =
+            (VkPhysicalDevicePointClippingPropertiesKHR *) ext;
+         properties->pointClippingBehavior =
+            VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR;
+         break;
+      }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
+         VkPhysicalDeviceMaintenance3Properties *properties =
+            (VkPhysicalDeviceMaintenance3Properties *) ext;
+         /* Make sure everything is addressable by a signed 32-bit int, and
+          * our largest descriptors are 96 bytes. */
+         properties->maxPerSetDescriptors = (1ull << 31) / 96;
+         /* Our buffer size fields allow only this much */
+         properties->maxMemoryAllocationSize = 0xFFFFFFFFull;
+         break;
+      }
+      default:
+         break;
       }
    }
 }
 
-static void
-tu_get_physical_device_queue_family_properties(
-  struct tu_physical_device *pdevice,
-  uint32_t *pCount,
-  VkQueueFamilyProperties **pQueueFamilyProperties)
-{
-   int num_queue_families = 1;
-   int idx;
-   if (pQueueFamilyProperties == NULL) {
-      *pCount = num_queue_families;
-      return;
-   }
-
-   if (!*pCount)
-      return;
-
-   idx = 0;
-   if (*pCount >= 1) {
-      *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties){
-         .queueFlags =
-           VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
-         .queueCount = 1,
-         .timestampValidBits = 64,
-         .minImageTransferGranularity = (VkExtent3D){ 1, 1, 1 },
-      };
-      idx++;
-   }
-
-   *pCount = idx;
-}
+static const VkQueueFamilyProperties tu_queue_family_properties = {
+   .queueFlags =
+      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
+   .queueCount = 1,
+   .timestampValidBits = 64,
+   .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
+};
 
 void
 tu_GetPhysicalDeviceQueueFamilyProperties(
-  VkPhysicalDevice physicalDevice,
-  uint32_t *pCount,
-  VkQueueFamilyProperties *pQueueFamilyProperties)
+   VkPhysicalDevice physicalDevice,
+   uint32_t *pQueueFamilyPropertyCount,
+   VkQueueFamilyProperties *pQueueFamilyProperties)
 {
-   TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
-   if (!pQueueFamilyProperties) {
-      return tu_get_physical_device_queue_family_properties(
-        pdevice, pCount, NULL);
-      return;
-   }
-   VkQueueFamilyProperties *properties[] = {
-      pQueueFamilyProperties + 0,
-   };
-   tu_get_physical_device_queue_family_properties(pdevice, pCount, properties);
-   assert(*pCount <= 1);
+   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
+
+   vk_outarray_append(&out, p) { *p = tu_queue_family_properties; }
 }
 
 void
 tu_GetPhysicalDeviceQueueFamilyProperties2(
-  VkPhysicalDevice physicalDevice,
-  uint32_t *pCount,
-  VkQueueFamilyProperties2KHR *pQueueFamilyProperties)
+   VkPhysicalDevice physicalDevice,
+   uint32_t *pQueueFamilyPropertyCount,
+   VkQueueFamilyProperties2KHR *pQueueFamilyProperties)
 {
-   TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
-   if (!pQueueFamilyProperties) {
-      return tu_get_physical_device_queue_family_properties(
-        pdevice, pCount, NULL);
-      return;
+   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
+
+   vk_outarray_append(&out, p)
+   {
+      p->queueFamilyProperties = tu_queue_family_properties;
    }
-   VkQueueFamilyProperties *properties[] = {
-      &pQueueFamilyProperties[0].queueFamilyProperties,
-   };
-   tu_get_physical_device_queue_family_properties(pdevice, pCount, properties);
-   assert(*pCount <= 1);
 }
 
 static uint64_t
@@ -881,7 +886,7 @@ tu_get_system_heap_size()
    struct sysinfo info;
    sysinfo(&info);
 
-   uint64_t total_ram = (uint64_t)info.totalram * (uint64_t)info.mem_unit;
+   uint64_t total_ram = (uint64_t) info.totalram * (uint64_t) info.mem_unit;
 
    /* We don't want to burn too much ram with the GPU.  If the user has 4GiB
     * or less, we use at most half.  If they have more than 4GiB, we use 3/4.
@@ -897,35 +902,36 @@ tu_get_system_heap_size()
 
 void
 tu_GetPhysicalDeviceMemoryProperties(
-  VkPhysicalDevice physicalDevice,
-  VkPhysicalDeviceMemoryProperties *pMemoryProperties)
+   VkPhysicalDevice physicalDevice,
+   VkPhysicalDeviceMemoryProperties *pMemoryProperties)
 {
    pMemoryProperties->memoryHeapCount = 1;
    pMemoryProperties->memoryHeaps[0].size = tu_get_system_heap_size();
    pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
 
    pMemoryProperties->memoryTypeCount = 1;
-   pMemoryProperties->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                                                     VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                                                     VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+   pMemoryProperties->memoryTypes[0].propertyFlags =
+      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+      VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
    pMemoryProperties->memoryTypes[0].heapIndex = 0;
 }
 
 void
 tu_GetPhysicalDeviceMemoryProperties2(
-  VkPhysicalDevice physicalDevice,
-  VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties)
+   VkPhysicalDevice physicalDevice,
+   VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties)
 {
    return tu_GetPhysicalDeviceMemoryProperties(
-     physicalDevice, &pMemoryProperties->memoryProperties);
+      physicalDevice, &pMemoryProperties->memoryProperties);
 }
 
-static int
+static VkResult
 tu_queue_init(struct tu_device *device,
-               struct tu_queue *queue,
-               uint32_t queue_family_index,
-               int idx,
-               VkDeviceQueueCreateFlags flags)
+              struct tu_queue *queue,
+              uint32_t queue_family_index,
+              int idx,
+              VkDeviceQueueCreateFlags flags)
 {
    queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
    queue->device = device;
@@ -933,12 +939,22 @@ tu_queue_init(struct tu_device *device,
    queue->queue_idx = idx;
    queue->flags = flags;
 
+   int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);
+   if (ret)
+      return VK_ERROR_INITIALIZATION_FAILED;
+
+   queue->submit_fence_fd = -1;
+
    return VK_SUCCESS;
 }
 
 static void
 tu_queue_finish(struct tu_queue *queue)
 {
+   if (queue->submit_fence_fd >= 0) {
+      close(queue->submit_fence_fd);
+   }
+   tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
 }
 
 static int
@@ -953,9 +969,9 @@ tu_get_device_extension_index(const char *name)
 
 VkResult
 tu_CreateDevice(VkPhysicalDevice physicalDevice,
-                 const VkDeviceCreateInfo *pCreateInfo,
-                 const VkAllocationCallbacks *pAllocator,
-                 VkDevice *pDevice)
+                const VkDeviceCreateInfo *pCreateInfo,
+                const VkAllocationCallbacks *pAllocator,
+                VkDevice *pDevice)
 {
    TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
    VkResult result;
@@ -965,10 +981,10 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
    if (pCreateInfo->pEnabledFeatures) {
       VkPhysicalDeviceFeatures supported_features;
       tu_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
-      VkBool32 *supported_feature = (VkBool32 *)&supported_features;
-      VkBool32 *enabled_feature = (VkBool32 *)pCreateInfo->pEnabledFeatures;
+      VkBool32 *supported_feature = (VkBool32 *) &supported_features;
+      VkBool32 *enabled_feature = (VkBool32 *) pCreateInfo->pEnabledFeatures;
       unsigned num_features =
-        sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
+         sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
       for (uint32_t i = 0; i < num_features; i++) {
          if (enabled_feature[i] && !supported_feature[i])
             return vk_error(physical_device->instance,
@@ -976,11 +992,8 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
       }
    }
 
-   device = vk_zalloc2(&physical_device->instance->alloc,
-                       pAllocator,
-                       sizeof(*device),
-                       8,
-                       VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+   device = vk_zalloc2(&physical_device->instance->alloc, pAllocator,
+                       sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
    if (!device)
       return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -1008,27 +1021,24 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
 
    for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
       const VkDeviceQueueCreateInfo *queue_create =
-        &pCreateInfo->pQueueCreateInfos[i];
+         &pCreateInfo->pQueueCreateInfos[i];
       uint32_t qfi = queue_create->queueFamilyIndex;
-      device->queues[qfi] =
-        vk_alloc(&device->alloc,
-                 queue_create->queueCount * sizeof(struct tu_queue),
-                 8,
-                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+      device->queues[qfi] = vk_alloc(
+         &device->alloc, queue_create->queueCount * sizeof(struct tu_queue),
+         8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
       if (!device->queues[qfi]) {
          result = VK_ERROR_OUT_OF_HOST_MEMORY;
          goto fail;
       }
 
-      memset(device->queues[qfi],
-             0,
+      memset(device->queues[qfi], 0,
              queue_create->queueCount * sizeof(struct tu_queue));
 
       device->queue_count[qfi] = queue_create->queueCount;
 
       for (unsigned q = 0; q < queue_create->queueCount; q++) {
-         result = tu_queue_init(
-           device, &device->queues[qfi][q], qfi, q, queue_create->flags);
+         result = tu_queue_init(device, &device->queues[qfi][q], qfi, q,
+                                queue_create->flags);
          if (result != VK_SUCCESS)
             goto fail;
       }
@@ -1042,7 +1052,7 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
    ci.initialDataSize = 0;
    VkPipelineCache pc;
    result =
-     tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);
+      tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);
    if (result != VK_SUCCESS)
       goto fail;
 
@@ -1086,41 +1096,31 @@ tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
 
 VkResult
 tu_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
-                                     VkLayerProperties *pProperties)
+                                    VkLayerProperties *pProperties)
 {
-   if (pProperties == NULL) {
-      *pPropertyCount = 0;
-      return VK_SUCCESS;
-   }
-
-   /* None supported at this time */
-   return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
+   *pPropertyCount = 0;
+   return VK_SUCCESS;
 }
 
 VkResult
 tu_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
-                                   uint32_t *pPropertyCount,
-                                   VkLayerProperties *pProperties)
+                                  uint32_t *pPropertyCount,
+                                  VkLayerProperties *pProperties)
 {
-   if (pProperties == NULL) {
-      *pPropertyCount = 0;
-      return VK_SUCCESS;
-   }
-
-   /* None supported at this time */
-   return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
+   *pPropertyCount = 0;
+   return VK_SUCCESS;
 }
 
 void
 tu_GetDeviceQueue2(VkDevice _device,
-                    const VkDeviceQueueInfo2 *pQueueInfo,
-                    VkQueue *pQueue)
+                   const VkDeviceQueueInfo2 *pQueueInfo,
+                   VkQueue *pQueue)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    struct tu_queue *queue;
 
    queue =
-     &device->queues[pQueueInfo->queueFamilyIndex][pQueueInfo->queueIndex];
+      &device->queues[pQueueInfo->queueFamilyIndex][pQueueInfo->queueIndex];
    if (pQueueInfo->flags != queue->flags) {
       /* From the Vulkan 1.1.70 spec:
        *
@@ -1139,30 +1139,111 @@ tu_GetDeviceQueue2(VkDevice _device,
 
 void
 tu_GetDeviceQueue(VkDevice _device,
-                   uint32_t queueFamilyIndex,
-                   uint32_t queueIndex,
-                   VkQueue *pQueue)
+                  uint32_t queueFamilyIndex,
+                  uint32_t queueIndex,
+                  VkQueue *pQueue)
 {
    const VkDeviceQueueInfo2 info =
-     (VkDeviceQueueInfo2){.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
-                          .queueFamilyIndex = queueFamilyIndex,
-                          .queueIndex = queueIndex };
+      (VkDeviceQueueInfo2) { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
+                             .queueFamilyIndex = queueFamilyIndex,
+                             .queueIndex = queueIndex };
 
    tu_GetDeviceQueue2(_device, &info, pQueue);
 }
 
 VkResult
 tu_QueueSubmit(VkQueue _queue,
-                uint32_t submitCount,
-                const VkSubmitInfo *pSubmits,
-                VkFence _fence)
-{
+               uint32_t submitCount,
+               const VkSubmitInfo *pSubmits,
+               VkFence _fence)
+{
+   TU_FROM_HANDLE(tu_queue, queue, _queue);
+
+   for (uint32_t i = 0; i < submitCount; ++i) {
+      const VkSubmitInfo *submit = pSubmits + i;
+      const bool last_submit = (i == submitCount - 1);
+      struct tu_bo_list bo_list;
+      tu_bo_list_init(&bo_list);
+
+      uint32_t entry_count = 0;
+      for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {
+         TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]);
+         entry_count += cmdbuf->cs.entry_count;
+      }
+
+      struct drm_msm_gem_submit_cmd cmds[entry_count];
+      uint32_t entry_idx = 0;
+      for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {
+         TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]);
+         struct tu_cs *cs = &cmdbuf->cs;
+         for (unsigned i = 0; i < cs->entry_count; ++i, ++entry_idx) {
+            cmds[entry_idx].type = MSM_SUBMIT_CMD_BUF;
+            cmds[entry_idx].submit_idx =
+               tu_bo_list_add(&bo_list, cs->entries[i].bo);
+            cmds[entry_idx].submit_offset = cs->entries[i].offset;
+            cmds[entry_idx].size = cs->entries[i].size;
+            cmds[entry_idx].pad = 0;
+            cmds[entry_idx].nr_relocs = 0;
+            cmds[entry_idx].relocs = 0;
+         }
+      }
+
+      struct drm_msm_gem_submit_bo bos[bo_list.count];
+      for (unsigned i = 0; i < bo_list.count; ++i) {
+         bos[i].flags = MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE;
+         bos[i].handle = bo_list.handles[i];
+         bos[i].presumed = 0;
+      }
+
+      uint32_t flags = MSM_PIPE_3D0;
+      if (last_submit) {
+         flags |= MSM_SUBMIT_FENCE_FD_OUT;
+      }
+
+      struct drm_msm_gem_submit req = {
+         .flags = flags,
+         .queueid = queue->msm_queue_id,
+         .bos = (uint64_t)(uintptr_t)bos,
+         .nr_bos = bo_list.count,
+         .cmds = (uint64_t)(uintptr_t)cmds,
+         .nr_cmds = entry_count,
+      };
+
+      int ret = drmCommandWriteRead(queue->device->physical_device->local_fd,
+                                    DRM_MSM_GEM_SUBMIT,
+                                    &req, sizeof(req));
+      if (ret) {
+         fprintf(stderr, "submit failed: %s\n", strerror(errno));
+         abort();
+      }
+
+      tu_bo_list_destroy(&bo_list);
+
+      if (last_submit) {
+         /* no need to merge fences as queue execution is serialized */
+         if (queue->submit_fence_fd >= 0) {
+            close(queue->submit_fence_fd);
+         }
+         queue->submit_fence_fd = req.fence_fd;
+      }
+   }
    return VK_SUCCESS;
 }
 
 VkResult
 tu_QueueWaitIdle(VkQueue _queue)
 {
+   TU_FROM_HANDLE(tu_queue, queue, _queue);
+
+   if (queue->submit_fence_fd >= 0) {
+      int ret = sync_wait(queue->submit_fence_fd, -1);
+      if (ret)
+         tu_loge("sync_wait on fence fd %d failed", queue->submit_fence_fd);
+
+      close(queue->submit_fence_fd);
+      queue->submit_fence_fd = -1;
+   }
+
    return VK_SUCCESS;
 }
 
@@ -1181,11 +1262,15 @@ tu_DeviceWaitIdle(VkDevice _device)
 
 VkResult
 tu_EnumerateInstanceExtensionProperties(const char *pLayerName,
-                                         uint32_t *pPropertyCount,
-                                         VkExtensionProperties *pProperties)
+                                        uint32_t *pPropertyCount,
+                                        VkExtensionProperties *pProperties)
 {
    VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
 
+   /* We spport no lyaers */
+   if (pLayerName)
+      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
+
    for (int i = 0; i < TU_INSTANCE_EXTENSION_COUNT; i++) {
       if (tu_supported_instance_extensions.extensions[i]) {
          vk_outarray_append(&out, prop) { *prop = tu_instance_extensions[i]; }
@@ -1197,13 +1282,18 @@ tu_EnumerateInstanceExtensionProperties(const char *pLayerName,
 
 VkResult
 tu_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
-                                       const char *pLayerName,
-                                       uint32_t *pPropertyCount,
-                                       VkExtensionProperties *pProperties)
+                                      const char *pLayerName,
+                                      uint32_t *pPropertyCount,
+                                      VkExtensionProperties *pProperties)
 {
+   /* We spport no lyaers */
    TU_FROM_HANDLE(tu_physical_device, device, physicalDevice);
    VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
 
+   /* We spport no lyaers */
+   if (pLayerName)
+      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
+
    for (int i = 0; i < TU_DEVICE_EXTENSION_COUNT; i++) {
       if (device->supported_extensions.extensions[i]) {
          vk_outarray_append(&out, prop) { *prop = tu_device_extensions[i]; }
@@ -1218,11 +1308,9 @@ tu_GetInstanceProcAddr(VkInstance _instance, const char *pName)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
 
-   return tu_lookup_entrypoint_checked(pName,
-                                        instance ? instance->api_version : 0,
-                                        instance ? &instance->enabled_extensions
-                                                 : NULL,
-                                        NULL);
+   return tu_lookup_entrypoint_checked(
+      pName, instance ? instance->api_version : 0,
+      instance ? &instance->enabled_extensions : NULL, NULL);
 }
 
 /* The loader wants us to expose a second GetInstanceProcAddr function
@@ -1244,19 +1332,19 @@ tu_GetDeviceProcAddr(VkDevice _device, const char *pName)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
 
-   return tu_lookup_entrypoint_checked(pName,
-                                        device->instance->api_version,
-                                        &device->instance->enabled_extensions,
-                                        &device->enabled_extensions);
+   return tu_lookup_entrypoint_checked(pName, device->instance->api_version,
+                                       &device->instance->enabled_extensions,
+                                       &device->enabled_extensions);
 }
 
 static VkResult
 tu_alloc_memory(struct tu_device *device,
-                 const VkMemoryAllocateInfo *pAllocateInfo,
-                 const VkAllocationCallbacks *pAllocator,
-                 VkDeviceMemory *pMem)
+                const VkMemoryAllocateInfo *pAllocateInfo,
+                const VkAllocationCallbacks *pAllocator,
+                VkDeviceMemory *pMem)
 {
    struct tu_device_memory *mem;
+   VkResult result;
 
    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
 
@@ -1266,21 +1354,17 @@ tu_alloc_memory(struct tu_device *device,
       return VK_SUCCESS;
    }
 
-   mem = vk_alloc2(&device->alloc,
-                   pAllocator,
-                   sizeof(*mem),
-                   8,
+   mem = vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (mem == NULL)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   mem->bo = fd_bo_new(device->physical_device->drm_device, pAllocateInfo->allocationSize,
-                       DRM_FREEDRENO_GEM_CACHE_WCOMBINE |
-                       DRM_FREEDRENO_GEM_TYPE_KMEM);
-   if (!mem->bo) {
+   result = tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize);
+   if (result != VK_SUCCESS) {
       vk_free2(&device->alloc, pAllocator, mem);
-      return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+      return result;
    }
+
    mem->size = pAllocateInfo->allocationSize;
    mem->type_index = pAllocateInfo->memoryTypeIndex;
 
@@ -1294,9 +1378,9 @@ tu_alloc_memory(struct tu_device *device,
 
 VkResult
 tu_AllocateMemory(VkDevice _device,
-                   const VkMemoryAllocateInfo *pAllocateInfo,
-                   const VkAllocationCallbacks *pAllocator,
-                   VkDeviceMemory *pMem)
+                  const VkMemoryAllocateInfo *pAllocateInfo,
+                  const VkAllocationCallbacks *pAllocator,
+                  VkDeviceMemory *pMem)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    return tu_alloc_memory(device, pAllocateInfo, pAllocator, pMem);
@@ -1304,8 +1388,8 @@ tu_AllocateMemory(VkDevice _device,
 
 void
 tu_FreeMemory(VkDevice _device,
-               VkDeviceMemory _mem,
-               const VkAllocationCallbacks *pAllocator)
+              VkDeviceMemory _mem,
+              const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_device_memory, mem, _mem);
@@ -1313,22 +1397,21 @@ tu_FreeMemory(VkDevice _device,
    if (mem == NULL)
       return;
 
-   if (mem->bo)
-      fd_bo_del(mem->bo);
-
+   tu_bo_finish(device, &mem->bo);
    vk_free2(&device->alloc, pAllocator, mem);
 }
 
 VkResult
 tu_MapMemory(VkDevice _device,
-              VkDeviceMemory _memory,
-              VkDeviceSize offset,
-              VkDeviceSize size,
-              VkMemoryMapFlags flags,
-              void **ppData)
+             VkDeviceMemory _memory,
+             VkDeviceSize offset,
+             VkDeviceSize size,
+             VkMemoryMapFlags flags,
+             void **ppData)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_device_memory, mem, _memory);
+   VkResult result;
 
    if (mem == NULL) {
       *ppData = NULL;
@@ -1337,8 +1420,11 @@ tu_MapMemory(VkDevice _device,
 
    if (mem->user_ptr) {
       *ppData = mem->user_ptr;
-   } else  if (!mem->map){
-      *ppData = mem->map = fd_bo_map(mem->bo);
+   } else if (!mem->map) {
+      result = tu_bo_map(device, &mem->bo);
+      if (result != VK_SUCCESS)
+         return result;
+      *ppData = mem->map = mem->bo.map;
    } else
       *ppData = mem->map;
 
@@ -1358,47 +1444,47 @@ tu_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
 
 VkResult
 tu_FlushMappedMemoryRanges(VkDevice _device,
-                            uint32_t memoryRangeCount,
-                            const VkMappedMemoryRange *pMemoryRanges)
+                           uint32_t memoryRangeCount,
+                           const VkMappedMemoryRange *pMemoryRanges)
 {
    return VK_SUCCESS;
 }
 
 VkResult
 tu_InvalidateMappedMemoryRanges(VkDevice _device,
-                                 uint32_t memoryRangeCount,
-                                 const VkMappedMemoryRange *pMemoryRanges)
+                                uint32_t memoryRangeCount,
+                                const VkMappedMemoryRange *pMemoryRanges)
 {
    return VK_SUCCESS;
 }
 
 void
 tu_GetBufferMemoryRequirements(VkDevice _device,
-                                VkBuffer _buffer,
-                                VkMemoryRequirements *pMemoryRequirements)
+                               VkBuffer _buffer,
+                               VkMemoryRequirements *pMemoryRequirements)
 {
    TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
 
    pMemoryRequirements->memoryTypeBits = 1;
    pMemoryRequirements->alignment = 16;
    pMemoryRequirements->size =
-     align64(buffer->size, pMemoryRequirements->alignment);
+      align64(buffer->size, pMemoryRequirements->alignment);
 }
 
 void
 tu_GetBufferMemoryRequirements2(
-  VkDevice device,
-  const VkBufferMemoryRequirementsInfo2KHR *pInfo,
-  VkMemoryRequirements2KHR *pMemoryRequirements)
+   VkDevice device,
+   const VkBufferMemoryRequirementsInfo2KHR *pInfo,
+   VkMemoryRequirements2KHR *pMemoryRequirements)
 {
-   tu_GetBufferMemoryRequirements(
-     device, pInfo->buffer, &pMemoryRequirements->memoryRequirements);
+   tu_GetBufferMemoryRequirements(device, pInfo->buffer,
+                                  &pMemoryRequirements->memoryRequirements);
 }
 
 void
 tu_GetImageMemoryRequirements(VkDevice _device,
-                               VkImage _image,
-                               VkMemoryRequirements *pMemoryRequirements)
+                              VkImage _image,
+                              VkMemoryRequirements *pMemoryRequirements)
 {
    TU_FROM_HANDLE(tu_image, image, _image);
 
@@ -1409,54 +1495,54 @@ tu_GetImageMemoryRequirements(VkDevice _device,
 
 void
 tu_GetImageMemoryRequirements2(VkDevice device,
-                                const VkImageMemoryRequirementsInfo2KHR *pInfo,
-                                VkMemoryRequirements2KHR *pMemoryRequirements)
+                               const VkImageMemoryRequirementsInfo2KHR *pInfo,
+                               VkMemoryRequirements2KHR *pMemoryRequirements)
 {
-   tu_GetImageMemoryRequirements(
-     device, pInfo->image, &pMemoryRequirements->memoryRequirements);
+   tu_GetImageMemoryRequirements(device, pInfo->image,
+                                 &pMemoryRequirements->memoryRequirements);
 }
 
 void
 tu_GetImageSparseMemoryRequirements(
-  VkDevice device,
-  VkImage image,
-  uint32_t *pSparseMemoryRequirementCount,
-  VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
+   VkDevice device,
+   VkImage image,
+   uint32_t *pSparseMemoryRequirementCount,
+   VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
 {
-   stub();
+   tu_stub();
 }
 
 void
 tu_GetImageSparseMemoryRequirements2(
-  VkDevice device,
-  const VkImageSparseMemoryRequirementsInfo2KHR *pInfo,
-  uint32_t *pSparseMemoryRequirementCount,
-  VkSparseImageMemoryRequirements2KHR *pSparseMemoryRequirements)
+   VkDevice device,
+   const VkImageSparseMemoryRequirementsInfo2KHR *pInfo,
+   uint32_t *pSparseMemoryRequirementCount,
+   VkSparseImageMemoryRequirements2KHR *pSparseMemoryRequirements)
 {
-   stub();
+   tu_stub();
 }
 
 void
 tu_GetDeviceMemoryCommitment(VkDevice device,
-                              VkDeviceMemory memory,
-                              VkDeviceSize *pCommittedMemoryInBytes)
+                             VkDeviceMemory memory,
+                             VkDeviceSize *pCommittedMemoryInBytes)
 {
    *pCommittedMemoryInBytes = 0;
 }
 
 VkResult
 tu_BindBufferMemory2(VkDevice device,
-                      uint32_t bindInfoCount,
-                      const VkBindBufferMemoryInfoKHR *pBindInfos)
+                     uint32_t bindInfoCount,
+                     const VkBindBufferMemoryInfoKHR *pBindInfos)
 {
    return VK_SUCCESS;
 }
 
 VkResult
 tu_BindBufferMemory(VkDevice device,
-                     VkBuffer buffer,
-                     VkDeviceMemory memory,
-                     VkDeviceSize memoryOffset)
+                    VkBuffer buffer,
+                    VkDeviceMemory memory,
+                    VkDeviceSize memoryOffset)
 {
    const VkBindBufferMemoryInfoKHR info = {
       .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,
@@ -1470,17 +1556,17 @@ tu_BindBufferMemory(VkDevice device,
 
 VkResult
 tu_BindImageMemory2(VkDevice device,
-                     uint32_t bindInfoCount,
-                     const VkBindImageMemoryInfoKHR *pBindInfos)
+                    uint32_t bindInfoCount,
+                    const VkBindImageMemoryInfoKHR *pBindInfos)
 {
    return VK_SUCCESS;
 }
 
 VkResult
 tu_BindImageMemory(VkDevice device,
-                    VkImage image,
-                    VkDeviceMemory memory,
-                    VkDeviceSize memoryOffset)
+                   VkImage image,
+                   VkDeviceMemory memory,
+                   VkDeviceSize memoryOffset)
 {
    const VkBindImageMemoryInfoKHR info = {
       .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,
@@ -1494,26 +1580,24 @@ tu_BindImageMemory(VkDevice device,
 
 VkResult
 tu_QueueBindSparse(VkQueue _queue,
-                    uint32_t bindInfoCount,
-                    const VkBindSparseInfo *pBindInfo,
-                    VkFence _fence)
+                   uint32_t bindInfoCount,
+                   const VkBindSparseInfo *pBindInfo,
+                   VkFence _fence)
 {
    return VK_SUCCESS;
 }
 
 VkResult
 tu_CreateFence(VkDevice _device,
-                const VkFenceCreateInfo *pCreateInfo,
-                const VkAllocationCallbacks *pAllocator,
-                VkFence *pFence)
+               const VkFenceCreateInfo *pCreateInfo,
+               const VkAllocationCallbacks *pAllocator,
+               VkFence *pFence)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
 
-   struct tu_fence *fence = vk_alloc2(&device->alloc,
-                                       pAllocator,
-                                       sizeof(*fence),
-                                       8,
-                                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   struct tu_fence *fence =
+      vk_alloc2(&device->alloc, pAllocator, sizeof(*fence), 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 
    if (!fence)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1525,8 +1609,8 @@ tu_CreateFence(VkDevice _device,
 
 void
 tu_DestroyFence(VkDevice _device,
-                 VkFence _fence,
-                 const VkAllocationCallbacks *pAllocator)
+                VkFence _fence,
+                const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_fence, fence, _fence);
@@ -1539,10 +1623,10 @@ tu_DestroyFence(VkDevice _device,
 
 VkResult
 tu_WaitForFences(VkDevice _device,
-                  uint32_t fenceCount,
-                  const VkFence *pFences,
-                  VkBool32 waitAll,
-                  uint64_t timeout)
+                 uint32_t fenceCount,
+                 const VkFence *pFences,
+                 VkBool32 waitAll,
+                 uint64_t timeout)
 {
    return VK_SUCCESS;
 }
@@ -1563,17 +1647,15 @@ tu_GetFenceStatus(VkDevice _device, VkFence _fence)
 
 VkResult
 tu_CreateSemaphore(VkDevice _device,
-                    const VkSemaphoreCreateInfo *pCreateInfo,
-                    const VkAllocationCallbacks *pAllocator,
-                    VkSemaphore *pSemaphore)
+                   const VkSemaphoreCreateInfo *pCreateInfo,
+                   const VkAllocationCallbacks *pAllocator,
+                   VkSemaphore *pSemaphore)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
 
-   struct tu_semaphore *sem = vk_alloc2(&device->alloc,
-                                         pAllocator,
-                                         sizeof(*sem),
-                                         8,
-                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   struct tu_semaphore *sem =
+      vk_alloc2(&device->alloc, pAllocator, sizeof(*sem), 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (!sem)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -1583,8 +1665,8 @@ tu_CreateSemaphore(VkDevice _device,
 
 void
 tu_DestroySemaphore(VkDevice _device,
-                     VkSemaphore _semaphore,
-                     const VkAllocationCallbacks *pAllocator)
+                    VkSemaphore _semaphore,
+                    const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_semaphore, sem, _semaphore);
@@ -1596,16 +1678,14 @@ tu_DestroySemaphore(VkDevice _device,
 
 VkResult
 tu_CreateEvent(VkDevice _device,
-                const VkEventCreateInfo *pCreateInfo,
-                const VkAllocationCallbacks *pAllocator,
-                VkEvent *pEvent)
+               const VkEventCreateInfo *pCreateInfo,
+               const VkAllocationCallbacks *pAllocator,
+               VkEvent *pEvent)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
-   struct tu_event *event = vk_alloc2(&device->alloc,
-                                       pAllocator,
-                                       sizeof(*event),
-                                       8,
-                                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   struct tu_event *event =
+      vk_alloc2(&device->alloc, pAllocator, sizeof(*event), 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 
    if (!event)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1617,8 +1697,8 @@ tu_CreateEvent(VkDevice _device,
 
 void
 tu_DestroyEvent(VkDevice _device,
-                 VkEvent _event,
-                 const VkAllocationCallbacks *pAllocator)
+                VkEvent _event,
+                const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_event, event, _event);
@@ -1658,19 +1738,16 @@ tu_ResetEvent(VkDevice _device, VkEvent _event)
 
 VkResult
 tu_CreateBuffer(VkDevice _device,
-                 const VkBufferCreateInfo *pCreateInfo,
-                 const VkAllocationCallbacks *pAllocator,
-                 VkBuffer *pBuffer)
+                const VkBufferCreateInfo *pCreateInfo,
+                const VkAllocationCallbacks *pAllocator,
+                VkBuffer *pBuffer)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    struct tu_buffer *buffer;
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
 
-   buffer = vk_alloc2(&device->alloc,
-                      pAllocator,
-                      sizeof(*buffer),
-                      8,
+   buffer = vk_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8,
                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (buffer == NULL)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1686,8 +1763,8 @@ tu_CreateBuffer(VkDevice _device,
 
 void
 tu_DestroyBuffer(VkDevice _device,
-                  VkBuffer _buffer,
-                  const VkAllocationCallbacks *pAllocator)
+                 VkBuffer _buffer,
+                 const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
@@ -1702,26 +1779,25 @@ static uint32_t
 tu_surface_max_layer_count(struct tu_image_view *iview)
 {
    return iview->type == VK_IMAGE_VIEW_TYPE_3D
-            ? iview->extent.depth
-            : (iview->base_layer + iview->layer_count);
+             ? iview->extent.depth
+             : (iview->base_layer + iview->layer_count);
 }
 
 VkResult
 tu_CreateFramebuffer(VkDevice _device,
-                      const VkFramebufferCreateInfo *pCreateInfo,
-                      const VkAllocationCallbacks *pAllocator,
-                      VkFramebuffer *pFramebuffer)
+                     const VkFramebufferCreateInfo *pCreateInfo,
+                     const VkAllocationCallbacks *pAllocator,
+                     VkFramebuffer *pFramebuffer)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    struct tu_framebuffer *framebuffer;
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
 
-   size_t size =
-     sizeof(*framebuffer) +
-     sizeof(struct tu_attachment_info) * pCreateInfo->attachmentCount;
-   framebuffer = vk_alloc2(
-     &device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   size_t size = sizeof(*framebuffer) + sizeof(struct tu_attachment_info) *
+                                           pCreateInfo->attachmentCount;
+   framebuffer = vk_alloc2(&device->alloc, pAllocator, size, 8,
+                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (framebuffer == NULL)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -1737,7 +1813,7 @@ tu_CreateFramebuffer(VkDevice _device,
       framebuffer->width = MIN2(framebuffer->width, iview->extent.width);
       framebuffer->height = MIN2(framebuffer->height, iview->extent.height);
       framebuffer->layers =
-        MIN2(framebuffer->layers, tu_surface_max_layer_count(iview));
+         MIN2(framebuffer->layers, tu_surface_max_layer_count(iview));
    }
 
    *pFramebuffer = tu_framebuffer_to_handle(framebuffer);
@@ -1746,8 +1822,8 @@ tu_CreateFramebuffer(VkDevice _device,
 
 void
 tu_DestroyFramebuffer(VkDevice _device,
-                       VkFramebuffer _fb,
-                       const VkAllocationCallbacks *pAllocator)
+                      VkFramebuffer _fb,
+                      const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_framebuffer, fb, _fb);
@@ -1759,26 +1835,23 @@ tu_DestroyFramebuffer(VkDevice _device,
 
 static void
 tu_init_sampler(struct tu_device *device,
-                 struct tu_sampler *sampler,
-                 const VkSamplerCreateInfo *pCreateInfo)
+                struct tu_sampler *sampler,
+                const VkSamplerCreateInfo *pCreateInfo)
 {
 }
 
 VkResult
 tu_CreateSampler(VkDevice _device,
-                  const VkSamplerCreateInfo *pCreateInfo,
-                  const VkAllocationCallbacks *pAllocator,
-                  VkSampler *pSampler)
+                 const VkSamplerCreateInfo *pCreateInfo,
+                 const VkAllocationCallbacks *pAllocator,
+                 VkSampler *pSampler)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    struct tu_sampler *sampler;
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
 
-   sampler = vk_alloc2(&device->alloc,
-                       pAllocator,
-                       sizeof(*sampler),
-                       8,
+   sampler = vk_alloc2(&device->alloc, pAllocator, sizeof(*sampler), 8,
                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (!sampler)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1791,8 +1864,8 @@ tu_CreateSampler(VkDevice _device,
 
 void
 tu_DestroySampler(VkDevice _device,
-                   VkSampler _sampler,
-                   const VkAllocationCallbacks *pAllocator)
+                  VkSampler _sampler,
+                  const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
    TU_FROM_HANDLE(tu_sampler, sampler, _sampler);
@@ -1812,45 +1885,46 @@ PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
 {
    /* For the full details on loader interface versioning, see
-   * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
-   * What follows is a condensed summary, to help you navigate the large and
-   * confusing official doc.
-   *
-   *   - Loader interface v0 is incompatible with later versions. We don't
-   *     support it.
-   *
-   *   - In loader interface v1:
-   *       - The first ICD entrypoint called by the loader is
-   *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
-   *         entrypoint.
-   *       - The ICD must statically expose no other Vulkan symbol unless it is
-   *         linked with -Bsymbolic.
-   *       - Each dispatchable Vulkan handle created by the ICD must be
-   *         a pointer to a struct whose first member is VK_LOADER_DATA. The
-   *         ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
-   *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
-   *         vkDestroySurfaceKHR(). The ICD must be capable of working with
-   *         such loader-managed surfaces.
-   *
-   *    - Loader interface v2 differs from v1 in:
-   *       - The first ICD entrypoint called by the loader is
-   *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
-   *         statically expose this entrypoint.
-   *
-   *    - Loader interface v3 differs from v2 in:
-   *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
-   *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
-   *          because the loader no longer does so.
-   */
+    * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
+    * What follows is a condensed summary, to help you navigate the large and
+    * confusing official doc.
+    *
+    *   - Loader interface v0 is incompatible with later versions. We don't
+    *     support it.
+    *
+    *   - In loader interface v1:
+    *       - The first ICD entrypoint called by the loader is
+    *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
+    *         entrypoint.
+    *       - The ICD must statically expose no other Vulkan symbol unless it
+    * is linked with -Bsymbolic.
+    *       - Each dispatchable Vulkan handle created by the ICD must be
+    *         a pointer to a struct whose first member is VK_LOADER_DATA. The
+    *         ICD must initialize VK_LOADER_DATA.loadMagic to
+    * ICD_LOADER_MAGIC.
+    *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
+    *         vkDestroySurfaceKHR(). The ICD must be capable of working with
+    *         such loader-managed surfaces.
+    *
+    *    - Loader interface v2 differs from v1 in:
+    *       - The first ICD entrypoint called by the loader is
+    *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
+    *         statically expose this entrypoint.
+    *
+    *    - Loader interface v3 differs from v2 in:
+    *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
+    *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
+    *          because the loader no longer does so.
+    */
    *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
    return VK_SUCCESS;
 }
 
 void
 tu_GetPhysicalDeviceExternalSemaphoreProperties(
-  VkPhysicalDevice physicalDevice,
-  const VkPhysicalDeviceExternalSemaphoreInfoKHR *pExternalSemaphoreInfo,
-  VkExternalSemaphorePropertiesKHR *pExternalSemaphoreProperties)
+   VkPhysicalDevice physicalDevice,
+   const VkPhysicalDeviceExternalSemaphoreInfoKHR *pExternalSemaphoreInfo,
+   VkExternalSemaphorePropertiesKHR *pExternalSemaphoreProperties)
 {
    pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
    pExternalSemaphoreProperties->compatibleHandleTypes = 0;
@@ -1859,9 +1933,9 @@ tu_GetPhysicalDeviceExternalSemaphoreProperties(
 
 void
 tu_GetPhysicalDeviceExternalFenceProperties(
-  VkPhysicalDevice physicalDevice,
-  const VkPhysicalDeviceExternalFenceInfoKHR *pExternalFenceInfo,
-  VkExternalFencePropertiesKHR *pExternalFenceProperties)
+   VkPhysicalDevice physicalDevice,
+   const VkPhysicalDeviceExternalFenceInfoKHR *pExternalFenceInfo,
+   VkExternalFencePropertiesKHR *pExternalFenceProperties)
 {
    pExternalFenceProperties->exportFromImportedHandleTypes = 0;
    pExternalFenceProperties->compatibleHandleTypes = 0;
@@ -1870,59 +1944,49 @@ tu_GetPhysicalDeviceExternalFenceProperties(
 
 VkResult
 tu_CreateDebugReportCallbackEXT(
-  VkInstance _instance,
-  const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
-  const VkAllocationCallbacks *pAllocator,
-  VkDebugReportCallbackEXT *pCallback)
+   VkInstance _instance,
+   const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+   const VkAllocationCallbacks *pAllocator,
+   VkDebugReportCallbackEXT *pCallback)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
    return vk_create_debug_report_callback(&instance->debug_report_callbacks,
-                                          pCreateInfo,
-                                          pAllocator,
-                                          &instance->alloc,
-                                          pCallback);
+                                          pCreateInfo, pAllocator,
+                                          &instance->alloc, pCallback);
 }
 
 void
 tu_DestroyDebugReportCallbackEXT(VkInstance _instance,
-                                  VkDebugReportCallbackEXT _callback,
-                                  const VkAllocationCallbacks *pAllocator)
+                                 VkDebugReportCallbackEXT _callback,
+                                 const VkAllocationCallbacks *pAllocator)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
    vk_destroy_debug_report_callback(&instance->debug_report_callbacks,
-                                    _callback,
-                                    pAllocator,
-                                    &instance->alloc);
+                                    _callback, pAllocator, &instance->alloc);
 }
 
 void
 tu_DebugReportMessageEXT(VkInstance _instance,
-                          VkDebugReportFlagsEXT flags,
-                          VkDebugReportObjectTypeEXT objectType,
-                          uint64_t object,
-                          size_t location,
-                          int32_t messageCode,
-                          const char *pLayerPrefix,
-                          const char *pMessage)
+                         VkDebugReportFlagsEXT flags,
+                         VkDebugReportObjectTypeEXT objectType,
+                         uint64_t object,
+                         size_t location,
+                         int32_t messageCode,
+                         const char *pLayerPrefix,
+                         const char *pMessage)
 {
    TU_FROM_HANDLE(tu_instance, instance, _instance);
-   vk_debug_report(&instance->debug_report_callbacks,
-                   flags,
-                   objectType,
-                   object,
-                   location,
-                   messageCode,
-                   pLayerPrefix,
-                   pMessage);
+   vk_debug_report(&instance->debug_report_callbacks, flags, objectType,
+                   object, location, messageCode, pLayerPrefix, pMessage);
 }
 
 void
 tu_GetDeviceGroupPeerMemoryFeatures(
-  VkDevice device,
-  uint32_t heapIndex,
-  uint32_t localDeviceIndex,
-  uint32_t remoteDeviceIndex,
-  VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
+   VkDevice device,
+   uint32_t heapIndex,
+   uint32_t localDeviceIndex,
+   uint32_t remoteDeviceIndex,
+   VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
 {
    assert(localDeviceIndex == remoteDeviceIndex);