turnip: use image tile_mode for gmem configuration
[mesa.git] / src / freedreno / vulkan / tu_device.c
index c7550ae03de7b92e99665052b8459d77d43f4aee..8799f4109fb92583be7921fe590a0296797d4d26 100644 (file)
@@ -28,6 +28,7 @@
 #include "tu_private.h"
 
 #include <fcntl.h>
+#include <libsync.h>
 #include <stdbool.h>
 #include <string.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <xf86drm.h>
 
+#include "compiler/glsl_types.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"
+#include "drm-uapi/msm_drm.h"
 
 static int
 tu_device_get_cache_uuid(uint16_t family, void *uuid)
@@ -72,6 +74,25 @@ tu_get_device_uuid(void *uuid)
    memset(uuid, 0, VK_UUID_SIZE);
 }
 
+static VkResult
+tu_bo_init(struct tu_device *dev,
+           struct tu_bo *bo,
+           uint32_t gem_handle,
+           uint64_t size)
+{
+   uint64_t iova = tu_gem_info_iova(dev, gem_handle);
+   if (!iova)
+      return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+
+   *bo = (struct tu_bo) {
+      .gem_handle = gem_handle,
+      .size = size,
+      .iova = iova,
+   };
+
+   return VK_SUCCESS;
+}
+
 VkResult
 tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
 {
@@ -80,39 +101,40 @@ tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
     */
    uint32_t gem_handle = tu_gem_new(dev, size, MSM_BO_WC);
    if (!gem_handle)
-      goto fail_new;
+      return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
 
-   /* Calling DRM_MSM_GEM_INFO forces the kernel to allocate backing pages. We
-    * want immediate backing pages because vkAllocateMemory and friends must
-    * not lazily fail.
-    *
-    * TODO(chadv): Must we really call DRM_MSM_GEM_INFO to acquire backing
-    * pages? I infer so from reading comments in msm_bo.c:bo_allocate(), but
-    * maybe I misunderstand.
-    */
+   VkResult result = tu_bo_init(dev, bo, gem_handle, size);
+   if (result != VK_SUCCESS) {
+      tu_gem_close(dev, gem_handle);
+      return vk_error(dev->instance, result);
+   }
 
-   /* TODO: Do we need 'offset' if we have 'iova'? */
-   uint64_t offset = tu_gem_info_offset(dev, gem_handle);
-   if (!offset)
-      goto fail_info;
+   return VK_SUCCESS;
+}
 
-   uint64_t iova = tu_gem_info_iova(dev, gem_handle);
-   if (!iova)
-      goto fail_info;
+VkResult
+tu_bo_init_dmabuf(struct tu_device *dev,
+                  struct tu_bo *bo,
+                  uint64_t size,
+                  int fd)
+{
+   uint32_t gem_handle = tu_gem_import_dmabuf(dev, fd, size);
+   if (!gem_handle)
+      return vk_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
 
-   *bo = (struct tu_bo) {
-      .gem_handle = gem_handle,
-      .size = size,
-      .offset = offset,
-      .iova = iova,
-   };
+   VkResult result = tu_bo_init(dev, bo, gem_handle, size);
+   if (result != VK_SUCCESS) {
+      tu_gem_close(dev, gem_handle);
+      return vk_error(dev->instance, result);
+   }
 
    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);
+int
+tu_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo)
+{
+   return tu_gem_export_dmabuf(dev, bo->gem_handle);
 }
 
 VkResult
@@ -121,9 +143,13 @@ 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, bo->offset);
+                    dev->physical_device->local_fd, offset);
    if (map == MAP_FAILED)
       return vk_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
 
@@ -152,7 +178,6 @@ tu_physical_device_init(struct tu_physical_device *device,
    drmVersionPtr version;
    int fd;
    int master_fd = -1;
-   uint64_t val;
 
    fd = open(path, O_RDWR | O_CLOEXEC);
    if (fd < 0) {
@@ -174,8 +199,6 @@ tu_physical_device_init(struct tu_physical_device *device,
 
    if (strcmp(version->name, "msm")) {
       drmFreeVersion(version);
-      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);
@@ -214,39 +237,29 @@ 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) {
-      if (instance->debug_flags & TU_DEBUG_STARTUP)
-         tu_logi("Could not create the libdrm device");
-      result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
-                         "could not create the libdrm device");
-      goto fail;
-   }
-
-   if (tu_drm_query_param(device, MSM_PARAM_GPU_ID, &val)) {
+   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 (tu_drm_query_param(device, MSM_PARAM_GMEM_SIZE, &val)) {
+   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;
 
    memset(device->name, 0, sizeof(device->name));
    sprintf(device->name, "FD%d", device->gpu_id);
 
    switch (device->gpu_id) {
-   case 530:
    case 630:
+      device->tile_align_w = 32;
+      device->tile_align_h = 32;
       break;
    default:
       result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
@@ -279,11 +292,15 @@ tu_physical_device_init(struct tu_physical_device *device,
       goto fail;
    }
 
+   result = tu_wsi_init(device);
+   if (result != VK_SUCCESS) {
+      vk_error(instance, result);
+      goto fail;
+   }
+
    return VK_SUCCESS;
 
 fail:
-   if (device->drm_device)
-      fd_device_del(device->drm_device);
    close(fd);
    if (master_fd != -1)
       close(master_fd);
@@ -293,6 +310,8 @@ fail:
 static void
 tu_physical_device_finish(struct tu_physical_device *device)
 {
+   tu_wsi_finish(device);
+
    disk_cache_destroy(device->disk_cache);
    close(device->local_fd);
    if (device->master_fd != -1)
@@ -332,7 +351,10 @@ static const VkAllocationCallbacks default_alloc = {
 };
 
 static const struct debug_control tu_debug_options[] = {
-   { "startup", TU_DEBUG_STARTUP }, { NULL, 0 }
+   { "startup", TU_DEBUG_STARTUP },
+   { "nir", TU_DEBUG_NIR },
+   { "ir3", TU_DEBUG_IR3 },
+   { NULL, 0 }
 };
 
 const char *
@@ -410,6 +432,7 @@ tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
    }
 
    _mesa_locale_init();
+   glsl_type_singleton_init_or_ref();
 
    VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
 
@@ -433,6 +456,7 @@ tu_DestroyInstance(VkInstance _instance,
 
    VG(VALGRIND_DESTROY_MEMPOOL(instance));
 
+   glsl_type_singleton_decref();
    _mesa_locale_fini();
 
    vk_debug_report_instance_destroy(&instance->debug_report_callbacks);
@@ -589,28 +613,28 @@ tu_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
 
 void
 tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
-                              VkPhysicalDeviceFeatures2KHR *pFeatures)
+                              VkPhysicalDeviceFeatures2 *pFeatures)
 {
    vk_foreach_struct(ext, pFeatures->pNext)
    {
       switch (ext->sType) {
-      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR: {
-         VkPhysicalDeviceVariablePointerFeaturesKHR *features = (void *) ext;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
+         VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;
          features->variablePointersStorageBuffer = false;
          features->variablePointers = false;
          break;
       }
-      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR: {
-         VkPhysicalDeviceMultiviewFeaturesKHR *features =
-            (VkPhysicalDeviceMultiviewFeaturesKHR *) ext;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
+         VkPhysicalDeviceMultiviewFeatures *features =
+            (VkPhysicalDeviceMultiviewFeatures *) 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;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
+         VkPhysicalDeviceShaderDrawParametersFeatures *features =
+            (VkPhysicalDeviceShaderDrawParametersFeatures *) ext;
          features->shaderDrawParameters = false;
          break;
       }
@@ -819,7 +843,7 @@ tu_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
 
 void
 tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
-                                VkPhysicalDeviceProperties2KHR *pProperties)
+                                VkPhysicalDeviceProperties2 *pProperties)
 {
    TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
    tu_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
@@ -833,26 +857,26 @@ tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
          properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
          break;
       }
-      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: {
-         VkPhysicalDeviceIDPropertiesKHR *properties =
-            (VkPhysicalDeviceIDPropertiesKHR *) ext;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
+         VkPhysicalDeviceIDProperties *properties =
+            (VkPhysicalDeviceIDProperties *) 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;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
+         VkPhysicalDeviceMultiviewProperties *properties =
+            (VkPhysicalDeviceMultiviewProperties *) ext;
          properties->maxMultiviewViewCount = MAX_VIEWS;
          properties->maxMultiviewInstanceIndex = INT_MAX;
          break;
       }
-      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR: {
-         VkPhysicalDevicePointClippingPropertiesKHR *properties =
-            (VkPhysicalDevicePointClippingPropertiesKHR *) ext;
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
+         VkPhysicalDevicePointClippingProperties *properties =
+            (VkPhysicalDevicePointClippingProperties *) ext;
          properties->pointClippingBehavior =
-            VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR;
+            VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
          break;
       }
       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
@@ -876,7 +900,7 @@ static const VkQueueFamilyProperties tu_queue_family_properties = {
       VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
    .queueCount = 1,
    .timestampValidBits = 64,
-   .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
+   .minImageTransferGranularity = { 1, 1, 1 },
 };
 
 void
@@ -894,7 +918,7 @@ void
 tu_GetPhysicalDeviceQueueFamilyProperties2(
    VkPhysicalDevice physicalDevice,
    uint32_t *pQueueFamilyPropertyCount,
-   VkQueueFamilyProperties2KHR *pQueueFamilyProperties)
+   VkQueueFamilyProperties2 *pQueueFamilyProperties)
 {
    VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
 
@@ -944,7 +968,7 @@ tu_GetPhysicalDeviceMemoryProperties(
 void
 tu_GetPhysicalDeviceMemoryProperties2(
    VkPhysicalDevice physicalDevice,
-   VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties)
+   VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
 {
    return tu_GetPhysicalDeviceMemoryProperties(
       physicalDevice, &pMemoryProperties->memoryProperties);
@@ -963,27 +987,20 @@ tu_queue_init(struct tu_device *device,
    queue->queue_idx = idx;
    queue->flags = flags;
 
-   struct drm_msm_submitqueue req = {
-      .flags = 0,
-      .prio = 0,
-   };
-
-   int ret = drmCommandWriteRead(device->physical_device->local_fd,
-                                 DRM_MSM_SUBMITQUEUE_NEW,
-                                 &req, sizeof(req));
+   int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);
    if (ret)
       return VK_ERROR_INITIALIZATION_FAILED;
 
-   queue->msm_queue_id = req.id;
+   tu_fence_init(&queue->submit_fence, false);
+
    return VK_SUCCESS;
 }
 
 static void
 tu_queue_finish(struct tu_queue *queue)
 {
-   drmCommandWrite(queue->device->physical_device->local_fd,
-                   DRM_MSM_SUBMITQUEUE_CLOSE,
-                   &queue->msm_queue_id, sizeof(uint32_t));
+   tu_fence_finish(&queue->submit_fence);
+   tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
 }
 
 static int
@@ -1073,6 +1090,10 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
       }
    }
 
+   device->compiler = ir3_compiler_create(NULL, physical_device->gpu_id);
+   if (!device->compiler)
+      goto fail;
+
    VkPipelineCacheCreateInfo ci;
    ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
    ci.pNext = NULL;
@@ -1098,6 +1119,9 @@ fail:
          vk_free(&device->alloc, device->queues[i]);
    }
 
+   if (device->compiler)
+      ralloc_free(device->compiler);
+
    vk_free(&device->alloc, device);
    return result;
 }
@@ -1117,6 +1141,9 @@ tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
          vk_free(&device->alloc, device->queues[i]);
    }
 
+   /* the compiler does not use pAllocator */
+   ralloc_free(device->compiler);
+
    VkPipelineCache pc = tu_pipeline_cache_to_handle(device->mem_cache);
    tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
 
@@ -1190,43 +1217,45 @@ tu_QueueSubmit(VkQueue _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) {
+      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) {
+      for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {
          TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]);
-         struct tu_cmd_stream *stream = &cmdbuf->cs;
-         for (unsigned i = 0; i < stream->entry_count; ++i, ++entry_idx) {
+         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, stream->entries[i].bo);
-            cmds[entry_idx].submit_offset = stream->entries[i].offset;
-            cmds[entry_idx].size = stream->entries[i].size;
+            cmds[entry_idx].submit_idx =
+               tu_bo_list_add(&bo_list, cs->entries[i].bo,
+                              MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_DUMP);
+            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;
-
          }
+
+         tu_bo_list_merge(&bo_list, &cmdbuf->bo_list);
       }
 
-      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 = MSM_PIPE_3D0,
+         .flags = flags,
          .queueid = queue->msm_queue_id,
-         .bos = (uint64_t)(uintptr_t)bos,
+         .bos = (uint64_t)(uintptr_t) bo_list.bo_infos,
          .nr_bos = bo_list.count,
          .cmds = (uint64_t)(uintptr_t)cmds,
          .nr_cmds = entry_count,
@@ -1241,13 +1270,28 @@ tu_QueueSubmit(VkQueue _queue,
       }
 
       tu_bo_list_destroy(&bo_list);
+
+      if (last_submit) {
+         /* no need to merge fences as queue execution is serialized */
+         tu_fence_update_fd(&queue->submit_fence, req.fence_fd);
+      }
+   }
+
+   if (_fence != VK_NULL_HANDLE) {
+      TU_FROM_HANDLE(tu_fence, fence, _fence);
+      tu_fence_copy(fence, &queue->submit_fence);
    }
+
    return VK_SUCCESS;
 }
 
 VkResult
 tu_QueueWaitIdle(VkQueue _queue)
 {
+   TU_FROM_HANDLE(tu_queue, queue, _queue);
+
+   tu_fence_wait_idle(&queue->submit_fence);
+
    return VK_SUCCESS;
 }
 
@@ -1363,7 +1407,33 @@ tu_alloc_memory(struct tu_device *device,
    if (mem == NULL)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   result = tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize);
+   const VkImportMemoryFdInfoKHR *fd_info =
+      vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
+   if (fd_info && !fd_info->handleType)
+      fd_info = NULL;
+
+   if (fd_info) {
+      assert(fd_info->handleType ==
+                VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
+             fd_info->handleType ==
+                VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+
+      /*
+       * TODO Importing the same fd twice gives us the same handle without
+       * reference counting.  We need to maintain a per-instance handle-to-bo
+       * table and add reference count to tu_bo.
+       */
+      result = tu_bo_init_dmabuf(device, &mem->bo,
+                                 pAllocateInfo->allocationSize, fd_info->fd);
+      if (result == VK_SUCCESS) {
+         /* take ownership and close the fd */
+         close(fd_info->fd);
+      }
+   } else {
+      result =
+         tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize);
+   }
+
    if (result != VK_SUCCESS) {
       vk_free2(&device->alloc, pAllocator, mem);
       return result;
@@ -1478,8 +1548,8 @@ tu_GetBufferMemoryRequirements(VkDevice _device,
 void
 tu_GetBufferMemoryRequirements2(
    VkDevice device,
-   const VkBufferMemoryRequirementsInfo2KHR *pInfo,
-   VkMemoryRequirements2KHR *pMemoryRequirements)
+   const VkBufferMemoryRequirementsInfo2 *pInfo,
+   VkMemoryRequirements2 *pMemoryRequirements)
 {
    tu_GetBufferMemoryRequirements(device, pInfo->buffer,
                                   &pMemoryRequirements->memoryRequirements);
@@ -1499,8 +1569,8 @@ tu_GetImageMemoryRequirements(VkDevice _device,
 
 void
 tu_GetImageMemoryRequirements2(VkDevice device,
-                               const VkImageMemoryRequirementsInfo2KHR *pInfo,
-                               VkMemoryRequirements2KHR *pMemoryRequirements)
+                               const VkImageMemoryRequirementsInfo2 *pInfo,
+                               VkMemoryRequirements2 *pMemoryRequirements)
 {
    tu_GetImageMemoryRequirements(device, pInfo->image,
                                  &pMemoryRequirements->memoryRequirements);
@@ -1519,9 +1589,9 @@ tu_GetImageSparseMemoryRequirements(
 void
 tu_GetImageSparseMemoryRequirements2(
    VkDevice device,
-   const VkImageSparseMemoryRequirementsInfo2KHR *pInfo,
+   const VkImageSparseMemoryRequirementsInfo2 *pInfo,
    uint32_t *pSparseMemoryRequirementCount,
-   VkSparseImageMemoryRequirements2KHR *pSparseMemoryRequirements)
+   VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
 {
    tu_stub();
 }
@@ -1537,8 +1607,19 @@ tu_GetDeviceMemoryCommitment(VkDevice device,
 VkResult
 tu_BindBufferMemory2(VkDevice device,
                      uint32_t bindInfoCount,
-                     const VkBindBufferMemoryInfoKHR *pBindInfos)
+                     const VkBindBufferMemoryInfo *pBindInfos)
 {
+   for (uint32_t i = 0; i < bindInfoCount; ++i) {
+      TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
+      TU_FROM_HANDLE(tu_buffer, buffer, pBindInfos[i].buffer);
+
+      if (mem) {
+         buffer->bo = &mem->bo;
+         buffer->bo_offset = pBindInfos[i].memoryOffset;
+      } else {
+         buffer->bo = NULL;
+      }
+   }
    return VK_SUCCESS;
 }
 
@@ -1548,8 +1629,8 @@ tu_BindBufferMemory(VkDevice device,
                     VkDeviceMemory memory,
                     VkDeviceSize memoryOffset)
 {
-   const VkBindBufferMemoryInfoKHR info = {
-      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,
+   const VkBindBufferMemoryInfo info = {
+      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
       .buffer = buffer,
       .memory = memory,
       .memoryOffset = memoryOffset
@@ -1561,8 +1642,21 @@ tu_BindBufferMemory(VkDevice device,
 VkResult
 tu_BindImageMemory2(VkDevice device,
                     uint32_t bindInfoCount,
-                    const VkBindImageMemoryInfoKHR *pBindInfos)
-{
+                    const VkBindImageMemoryInfo *pBindInfos)
+{
+   for (uint32_t i = 0; i < bindInfoCount; ++i) {
+      TU_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
+      TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
+
+      if (mem) {
+         image->bo = &mem->bo;
+         image->bo_offset = pBindInfos[i].memoryOffset;
+      } else {
+         image->bo = NULL;
+         image->bo_offset = 0;
+      }
+   }
+
    return VK_SUCCESS;
 }
 
@@ -1572,8 +1666,8 @@ tu_BindImageMemory(VkDevice device,
                    VkDeviceMemory memory,
                    VkDeviceSize memoryOffset)
 {
-   const VkBindImageMemoryInfoKHR info = {
-      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,
+   const VkBindImageMemoryInfo info = {
+      .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
       .image = image,
       .memory = memory,
       .memoryOffset = memoryOffset
@@ -1591,62 +1685,6 @@ tu_QueueBindSparse(VkQueue _queue,
    return VK_SUCCESS;
 }
 
-VkResult
-tu_CreateFence(VkDevice _device,
-               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);
-
-   if (!fence)
-      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   *pFence = tu_fence_to_handle(fence);
-
-   return VK_SUCCESS;
-}
-
-void
-tu_DestroyFence(VkDevice _device,
-                VkFence _fence,
-                const VkAllocationCallbacks *pAllocator)
-{
-   TU_FROM_HANDLE(tu_device, device, _device);
-   TU_FROM_HANDLE(tu_fence, fence, _fence);
-
-   if (!fence)
-      return;
-
-   vk_free2(&device->alloc, pAllocator, fence);
-}
-
-VkResult
-tu_WaitForFences(VkDevice _device,
-                 uint32_t fenceCount,
-                 const VkFence *pFences,
-                 VkBool32 waitAll,
-                 uint64_t timeout)
-{
-   return VK_SUCCESS;
-}
-
-VkResult
-tu_ResetFences(VkDevice _device, uint32_t fenceCount, const VkFence *pFences)
-{
-   return VK_SUCCESS;
-}
-
-VkResult
-tu_GetFenceStatus(VkDevice _device, VkFence _fence)
-{
-   return VK_SUCCESS;
-}
-
 // Queue semaphore functions
 
 VkResult
@@ -1924,11 +1962,46 @@ vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
    return VK_SUCCESS;
 }
 
+VkResult
+tu_GetMemoryFdKHR(VkDevice _device,
+                  const VkMemoryGetFdInfoKHR *pGetFdInfo,
+                  int *pFd)
+{
+   TU_FROM_HANDLE(tu_device, device, _device);
+   TU_FROM_HANDLE(tu_device_memory, memory, pGetFdInfo->memory);
+
+   assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
+
+   /* At the moment, we support only the below handle types. */
+   assert(pGetFdInfo->handleType ==
+             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
+          pGetFdInfo->handleType ==
+             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+
+   int prime_fd = tu_bo_export_dmabuf(device, &memory->bo);
+   if (prime_fd < 0)
+      return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
+
+   *pFd = prime_fd;
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_GetMemoryFdPropertiesKHR(VkDevice _device,
+                            VkExternalMemoryHandleTypeFlagBits handleType,
+                            int fd,
+                            VkMemoryFdPropertiesKHR *pMemoryFdProperties)
+{
+   assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+   pMemoryFdProperties->memoryTypeBits = 1;
+   return VK_SUCCESS;
+}
+
 void
 tu_GetPhysicalDeviceExternalSemaphoreProperties(
    VkPhysicalDevice physicalDevice,
-   const VkPhysicalDeviceExternalSemaphoreInfoKHR *pExternalSemaphoreInfo,
-   VkExternalSemaphorePropertiesKHR *pExternalSemaphoreProperties)
+   const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
+   VkExternalSemaphoreProperties *pExternalSemaphoreProperties)
 {
    pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
    pExternalSemaphoreProperties->compatibleHandleTypes = 0;
@@ -1938,8 +2011,8 @@ tu_GetPhysicalDeviceExternalSemaphoreProperties(
 void
 tu_GetPhysicalDeviceExternalFenceProperties(
    VkPhysicalDevice physicalDevice,
-   const VkPhysicalDeviceExternalFenceInfoKHR *pExternalFenceInfo,
-   VkExternalFencePropertiesKHR *pExternalFenceProperties)
+   const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
+   VkExternalFenceProperties *pExternalFenceProperties)
 {
    pExternalFenceProperties->exportFromImportedHandleTypes = 0;
    pExternalFenceProperties->compatibleHandleTypes = 0;