Switch from cElementTree to ElementTree.
[mesa.git] / src / intel / vulkan / anv_queue.c
index 791975d1fcf2011a30876af35823ca008a977e80..f6e3fdd6177cf960aea352a260d26fa49df5d9b1 100644 (file)
@@ -139,13 +139,13 @@ anv_timeline_finish(struct anv_device *device,
                             &timeline->free_points, link) {
       list_del(&point->link);
       anv_device_release_bo(device, point->bo);
-      vk_free(&device->alloc, point);
+      vk_free(&device->vk.alloc, point);
    }
    list_for_each_entry_safe(struct anv_timeline_point, point,
                             &timeline->points, link) {
       list_del(&point->link);
       anv_device_release_bo(device, point->bo);
-      vk_free(&device->alloc, point);
+      vk_free(&device->vk.alloc, point);
    }
 }
 
@@ -159,7 +159,7 @@ anv_timeline_add_point_locked(struct anv_device *device,
 
    if (list_is_empty(&timeline->free_points)) {
       *point =
-         vk_zalloc(&device->alloc, sizeof(**point),
+         vk_zalloc(&device->vk.alloc, sizeof(**point),
                    8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
       if (!(*point))
          result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -170,7 +170,7 @@ anv_timeline_add_point_locked(struct anv_device *device,
                                       0 /* explicit_address */,
                                       &(*point)->bo);
          if (result != VK_SUCCESS)
-            vk_free(&device->alloc, *point);
+            vk_free(&device->vk.alloc, *point);
       }
    } else {
       *point = list_first_entry(&timeline->free_points,
@@ -348,7 +348,8 @@ anv_device_submit_deferred_locked(struct anv_device *device)
 }
 
 static VkResult
-_anv_queue_submit(struct anv_queue *queue, struct anv_queue_submit **_submit)
+_anv_queue_submit(struct anv_queue *queue, struct anv_queue_submit **_submit,
+                  bool flush_queue)
 {
    struct anv_queue_submit *submit = *_submit;
 
@@ -361,6 +362,18 @@ _anv_queue_submit(struct anv_queue *queue, struct anv_queue_submit **_submit)
    pthread_mutex_lock(&queue->device->mutex);
    list_addtail(&submit->link, &queue->queued_submits);
    VkResult result = anv_device_submit_deferred_locked(queue->device);
+   if (flush_queue) {
+      while (result == VK_SUCCESS && !list_is_empty(&queue->queued_submits)) {
+         int ret = pthread_cond_wait(&queue->device->queue_submit,
+                                     &queue->device->mutex);
+         if (ret != 0) {
+            result = anv_device_set_lost(queue->device, "wait timeout");
+            break;
+         }
+
+         result = anv_device_submit_deferred_locked(queue->device);
+      }
+   }
    pthread_mutex_unlock(&queue->device->mutex);
    return result;
 }
@@ -368,7 +381,7 @@ _anv_queue_submit(struct anv_queue *queue, struct anv_queue_submit **_submit)
 VkResult
 anv_queue_init(struct anv_device *device, struct anv_queue *queue)
 {
-   queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
+   vk_object_base_init(&device->vk, &queue->base, VK_OBJECT_TYPE_QUEUE);
    queue->device = device;
    queue->flags = 0;
 
@@ -380,6 +393,7 @@ anv_queue_init(struct anv_device *device, struct anv_queue *queue)
 void
 anv_queue_finish(struct anv_queue *queue)
 {
+   vk_object_base_finish(&queue->base);
 }
 
 static VkResult
@@ -530,9 +544,9 @@ anv_queue_submit_add_timeline_signal(struct anv_queue_submit* submit,
 }
 
 static struct anv_queue_submit *
-anv_queue_submit_alloc(struct anv_device *device)
+anv_queue_submit_alloc(struct anv_device *device, int perf_query_pass)
 {
-   const VkAllocationCallbacks *alloc = &device->alloc;
+   const VkAllocationCallbacks *alloc = &device->vk.alloc;
    VkSystemAllocationScope alloc_scope = VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
 
    struct anv_queue_submit *submit = vk_zalloc(alloc, sizeof(*submit), 8, alloc_scope);
@@ -543,6 +557,7 @@ anv_queue_submit_alloc(struct anv_device *device)
    submit->alloc_scope = alloc_scope;
    submit->in_fence = -1;
    submit->out_fence = -1;
+   submit->perf_query_pass = perf_query_pass;
 
    return submit;
 }
@@ -551,12 +566,15 @@ VkResult
 anv_queue_submit_simple_batch(struct anv_queue *queue,
                               struct anv_batch *batch)
 {
+   if (queue->device->no_hw)
+      return VK_SUCCESS;
+
    struct anv_device *device = queue->device;
-   struct anv_queue_submit *submit = anv_queue_submit_alloc(device);
+   struct anv_queue_submit *submit = anv_queue_submit_alloc(device, -1);
    if (!submit)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   bool has_syncobj_wait = device->instance->physicalDevice.has_syncobj_wait;
+   bool has_syncobj_wait = device->physical->has_syncobj_wait;
    VkResult result;
    uint32_t syncobj;
    struct anv_bo *batch_bo, *sync_bo;
@@ -599,7 +617,7 @@ anv_queue_submit_simple_batch(struct anv_queue *queue,
       submit->simple_bo_size = size;
    }
 
-   result = _anv_queue_submit(queue, &submit);
+   result = _anv_queue_submit(queue, &submit, true);
 
    if (result == VK_SUCCESS) {
       if (has_syncobj_wait) {
@@ -702,12 +720,14 @@ anv_queue_submit(struct anv_queue *queue,
                  const VkSemaphore *out_semaphores,
                  const uint64_t *out_values,
                  uint32_t num_out_semaphores,
-                 VkFence _fence)
+                 struct anv_bo *wsi_signal_bo,
+                 VkFence _fence,
+                 int perf_query_pass)
 {
    ANV_FROM_HANDLE(anv_fence, fence, _fence);
    struct anv_device *device = queue->device;
-   UNUSED struct anv_physical_device *pdevice = &device->instance->physicalDevice;
-   struct anv_queue_submit *submit = anv_queue_submit_alloc(device);
+   UNUSED struct anv_physical_device *pdevice = device->physical;
+   struct anv_queue_submit *submit = anv_queue_submit_alloc(device, perf_query_pass);
    if (!submit)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -731,6 +751,18 @@ anv_queue_submit(struct anv_queue *queue,
             goto error;
          break;
 
+      case ANV_SEMAPHORE_TYPE_WSI_BO:
+         /* When using a window-system buffer as a semaphore, always enable
+          * EXEC_OBJECT_WRITE.  This gives us a WaR hazard with the display or
+          * compositor's read of the buffer and enforces that we don't start
+          * rendering until they are finished.  This is exactly the
+          * synchronization we want with vkAcquireNextImage.
+          */
+         result = anv_queue_submit_add_fence_bo(submit, impl->bo, true /* signal */);
+         if (result != VK_SUCCESS)
+            goto error;
+         break;
+
       case ANV_SEMAPHORE_TYPE_SYNC_FILE:
          assert(!pdevice->has_syncobj);
          if (submit->in_fence == -1) {
@@ -829,6 +861,12 @@ anv_queue_submit(struct anv_queue *queue,
       }
    }
 
+   if (wsi_signal_bo) {
+      result = anv_queue_submit_add_fence_bo(submit, wsi_signal_bo, true /* signal */);
+      if (result != VK_SUCCESS)
+         goto error;
+   }
+
    if (fence) {
       /* Under most circumstances, out fences won't be temporary.  However,
        * the spec does allow it for opaque_fd.  From the Vulkan 1.0.53 spec:
@@ -870,12 +908,21 @@ anv_queue_submit(struct anv_queue *queue,
       }
    }
 
-   result = _anv_queue_submit(queue, &submit);
+   result = _anv_queue_submit(queue, &submit, false);
    if (result != VK_SUCCESS)
       goto error;
 
    if (fence && fence->permanent.type == ANV_FENCE_TYPE_BO) {
-      /* BO fences can't be shared, so they can't be temporary. */
+      /* If we have permanent BO fence, the only type of temporary possible
+       * would be BO_WSI (because BO fences are not shareable). The Vulkan spec
+       * also requires that the fence passed to vkQueueSubmit() be :
+       *
+       *    * unsignaled
+       *    * not be associated with any other queue command that has not yet
+       *      completed execution on that queue
+       *
+       * So the only acceptable type for the temporary is NONE.
+       */
       assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
 
       /* Once the execbuf has returned, we need to set the fence state to
@@ -906,6 +953,9 @@ VkResult anv_QueueSubmit(
 {
    ANV_FROM_HANDLE(anv_queue, queue, _queue);
 
+   if (queue->device->no_hw)
+      return VK_SUCCESS;
+
    /* Query for device status prior to submitting.  Technically, we don't need
     * to do this.  However, if we have a client that's submitting piles of
     * garbage, we would rather break as early as possible to keep the GPU
@@ -923,7 +973,8 @@ VkResult anv_QueueSubmit(
        * come up with something more efficient but this shouldn't be a
        * common case.
        */
-      result = anv_queue_submit(queue, NULL, NULL, NULL, 0, NULL, NULL, 0, fence);
+      result = anv_queue_submit(queue, NULL, NULL, NULL, 0, NULL, NULL, 0,
+                                NULL, fence, -1);
       goto out;
    }
 
@@ -931,9 +982,19 @@ VkResult anv_QueueSubmit(
       /* Fence for this submit.  NULL for all but the last one */
       VkFence submit_fence = (i == submitCount - 1) ? fence : VK_NULL_HANDLE;
 
+      const struct wsi_memory_signal_submit_info *mem_signal_info =
+         vk_find_struct_const(pSubmits[i].pNext,
+                              WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA);
+      struct anv_bo *wsi_signal_bo =
+         mem_signal_info && mem_signal_info->memory != VK_NULL_HANDLE ?
+         anv_device_memory_from_handle(mem_signal_info->memory)->bo : NULL;
+
       const VkTimelineSemaphoreSubmitInfoKHR *timeline_info =
          vk_find_struct_const(pSubmits[i].pNext,
                               TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR);
+      const VkPerformanceQuerySubmitInfoKHR *perf_info =
+         vk_find_struct_const(pSubmits[i].pNext,
+                              PERFORMANCE_QUERY_SUBMIT_INFO_KHR);
       const uint64_t *wait_values =
          timeline_info && timeline_info->waitSemaphoreValueCount ?
          timeline_info->pWaitSemaphoreValues : NULL;
@@ -954,7 +1015,9 @@ VkResult anv_QueueSubmit(
                                    pSubmits[i].pSignalSemaphores,
                                    signal_values,
                                    pSubmits[i].signalSemaphoreCount,
-                                   submit_fence);
+                                   wsi_signal_bo,
+                                   submit_fence,
+                                   -1);
          if (result != VK_SUCCESS)
             goto out;
 
@@ -992,7 +1055,8 @@ VkResult anv_QueueSubmit(
          result = anv_queue_submit(queue, cmd_buffer,
                                    in_semaphores, in_values, num_in_semaphores,
                                    out_semaphores, out_values, num_out_semaphores,
-                                   execbuf_fence);
+                                   wsi_signal_bo, execbuf_fence,
+                                   perf_info ? perf_info->counterPassIndex : 0);
          if (result != VK_SUCCESS)
             goto out;
       }
@@ -1044,12 +1108,14 @@ VkResult anv_CreateFence(
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
 
-   fence = vk_zalloc2(&device->alloc, pAllocator, sizeof(*fence), 8,
+   fence = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (fence == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   if (device->instance->physicalDevice.has_syncobj_wait) {
+   vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
+
+   if (device->physical->has_syncobj_wait) {
       fence->permanent.type = ANV_FENCE_TYPE_SYNCOBJ;
 
       uint32_t create_flags = 0;
@@ -1092,6 +1158,10 @@ anv_fence_impl_cleanup(struct anv_device *device,
       anv_bo_pool_free(&device->batch_bo_pool, impl->bo.bo);
       break;
 
+   case ANV_FENCE_TYPE_WSI_BO:
+      anv_device_release_bo(device, impl->bo.bo);
+      break;
+
    case ANV_FENCE_TYPE_SYNCOBJ:
       anv_gem_syncobj_destroy(device, impl->syncobj);
       break;
@@ -1107,6 +1177,16 @@ anv_fence_impl_cleanup(struct anv_device *device,
    impl->type = ANV_FENCE_TYPE_NONE;
 }
 
+void
+anv_fence_reset_temporary(struct anv_device *device,
+                          struct anv_fence *fence)
+{
+   if (fence->temporary.type == ANV_FENCE_TYPE_NONE)
+      return;
+
+   anv_fence_impl_cleanup(device, &fence->temporary);
+}
+
 void anv_DestroyFence(
     VkDevice                                    _device,
     VkFence                                     _fence,
@@ -1121,7 +1201,8 @@ void anv_DestroyFence(
    anv_fence_impl_cleanup(device, &fence->temporary);
    anv_fence_impl_cleanup(device, &fence->permanent);
 
-   vk_free2(&device->alloc, pAllocator, fence);
+   vk_object_base_finish(&fence->base);
+   vk_free2(&device->vk.alloc, pAllocator, fence);
 }
 
 VkResult anv_ResetFences(
@@ -1141,8 +1222,7 @@ VkResult anv_ResetFences(
        *    first restored. The remaining operations described therefore
        *    operate on the restored payload.
        */
-      if (fence->temporary.type != ANV_FENCE_TYPE_NONE)
-         anv_fence_impl_cleanup(device, &fence->temporary);
+      anv_fence_reset_temporary(device, fence);
 
       struct anv_fence_impl *impl = &fence->permanent;
 
@@ -1179,8 +1259,7 @@ VkResult anv_GetFenceStatus(
 
    switch (impl->type) {
    case ANV_FENCE_TYPE_BO:
-      /* BO fences don't support import/export */
-      assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
+   case ANV_FENCE_TYPE_WSI_BO:
       switch (impl->bo.state) {
       case ANV_BO_FENCE_STATE_RESET:
          /* If it hasn't even been sent off to the GPU yet, it's not ready */
@@ -1229,7 +1308,7 @@ anv_wait_for_syncobj_fences(struct anv_device *device,
                             bool waitAll,
                             uint64_t abs_timeout_ns)
 {
-   uint32_t *syncobjs = vk_zalloc(&device->alloc,
+   uint32_t *syncobjs = vk_zalloc(&device->vk.alloc,
                                   sizeof(*syncobjs) * fenceCount, 8,
                                   VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    if (!syncobjs)
@@ -1257,7 +1336,7 @@ anv_wait_for_syncobj_fences(struct anv_device *device,
                                  abs_timeout_ns, waitAll);
    } while (ret == -1 && errno == ETIME && anv_gettime_ns() < abs_timeout_ns);
 
-   vk_free(&device->alloc, syncobjs);
+   vk_free(&device->vk.alloc, syncobjs);
 
    if (ret == -1) {
       if (errno == ETIME) {
@@ -1286,13 +1365,11 @@ anv_wait_for_bo_fences(struct anv_device *device,
       for (uint32_t i = 0; i < fenceCount; i++) {
          ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
 
-         /* This function assumes that all fences are BO fences and that they
-          * have no temporary state.  Since BO fences will never be exported,
-          * this should be a safe assumption.
-          */
-         assert(fence->permanent.type == ANV_FENCE_TYPE_BO);
-         assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
-         struct anv_fence_impl *impl = &fence->permanent;
+         struct anv_fence_impl *impl =
+            fence->temporary.type != ANV_FENCE_TYPE_NONE ?
+            &fence->temporary : &fence->permanent;
+         assert(impl->type == ANV_FENCE_TYPE_BO ||
+                impl->type == ANV_FENCE_TYPE_WSI_BO);
 
          switch (impl->bo.state) {
          case ANV_BO_FENCE_STATE_RESET:
@@ -1387,12 +1464,9 @@ done:
 
 static VkResult
 anv_wait_for_wsi_fence(struct anv_device *device,
-                       const VkFence _fence,
+                       struct anv_fence_impl *impl,
                        uint64_t abs_timeout)
 {
-   ANV_FROM_HANDLE(anv_fence, fence, _fence);
-   struct anv_fence_impl *impl = &fence->permanent;
-
    return impl->fence_wsi->wait(impl->fence_wsi, abs_timeout);
 }
 
@@ -1408,8 +1482,13 @@ anv_wait_for_fences(struct anv_device *device,
    if (fenceCount <= 1 || waitAll) {
       for (uint32_t i = 0; i < fenceCount; i++) {
          ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
-         switch (fence->permanent.type) {
+         struct anv_fence_impl *impl =
+            fence->temporary.type != ANV_FENCE_TYPE_NONE ?
+            &fence->temporary : &fence->permanent;
+
+         switch (impl->type) {
          case ANV_FENCE_TYPE_BO:
+         case ANV_FENCE_TYPE_WSI_BO:
             result = anv_wait_for_bo_fences(device, 1, &pFences[i],
                                             true, abs_timeout);
             break;
@@ -1418,7 +1497,7 @@ anv_wait_for_fences(struct anv_device *device,
                                                  true, abs_timeout);
             break;
          case ANV_FENCE_TYPE_WSI:
-            result = anv_wait_for_wsi_fence(device, pFences[i], abs_timeout);
+            result = anv_wait_for_wsi_fence(device, impl, abs_timeout);
             break;
          case ANV_FENCE_TYPE_NONE:
             result = VK_SUCCESS;
@@ -1443,7 +1522,10 @@ static bool anv_all_fences_syncobj(uint32_t fenceCount, const VkFence *pFences)
 {
    for (uint32_t i = 0; i < fenceCount; ++i) {
       ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
-      if (fence->permanent.type != ANV_FENCE_TYPE_SYNCOBJ)
+      struct anv_fence_impl *impl =
+         fence->temporary.type != ANV_FENCE_TYPE_NONE ?
+         &fence->temporary : &fence->permanent;
+      if (impl->type != ANV_FENCE_TYPE_SYNCOBJ)
          return false;
    }
    return true;
@@ -1453,7 +1535,11 @@ static bool anv_all_fences_bo(uint32_t fenceCount, const VkFence *pFences)
 {
    for (uint32_t i = 0; i < fenceCount; ++i) {
       ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
-      if (fence->permanent.type != ANV_FENCE_TYPE_BO)
+      struct anv_fence_impl *impl =
+         fence->temporary.type != ANV_FENCE_TYPE_NONE ?
+         &fence->temporary : &fence->permanent;
+      if (impl->type != ANV_FENCE_TYPE_BO &&
+          impl->type != ANV_FENCE_TYPE_WSI_BO)
          return false;
    }
    return true;
@@ -1468,6 +1554,9 @@ VkResult anv_WaitForFences(
 {
    ANV_FROM_HANDLE(anv_device, device, _device);
 
+   if (device->no_hw)
+      return VK_SUCCESS;
+
    if (anv_device_is_lost(device))
       return VK_ERROR_DEVICE_LOST;
 
@@ -1555,8 +1644,7 @@ VkResult anv_ImportFenceFdKHR(
 
       if (anv_gem_syncobj_import_sync_file(device, new_impl.syncobj, fd)) {
          anv_gem_syncobj_destroy(device, new_impl.syncobj);
-         return vk_errorf(device->instance, NULL,
-                          VK_ERROR_INVALID_EXTERNAL_HANDLE,
+         return vk_errorf(device, NULL, VK_ERROR_INVALID_EXTERNAL_HANDLE,
                           "syncobj sync file import failed: %m");
       }
       break;
@@ -1659,7 +1747,7 @@ binary_semaphore_create(struct anv_device *device,
                         struct anv_semaphore_impl *impl,
                         bool exportable)
 {
-   if (device->instance->physicalDevice.has_syncobj) {
+   if (device->physical->has_syncobj) {
       impl->type = ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ;
       impl->syncobj = anv_gem_syncobj_create(device, 0);
       if (!impl->syncobj)
@@ -1705,11 +1793,13 @@ VkResult anv_CreateSemaphore(
    uint64_t timeline_value = 0;
    VkSemaphoreTypeKHR sem_type = get_semaphore_type(pCreateInfo->pNext, &timeline_value);
 
-   semaphore = vk_alloc(&device->alloc, sizeof(*semaphore), 8,
+   semaphore = vk_alloc(&device->vk.alloc, sizeof(*semaphore), 8,
                         VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
    if (semaphore == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
+   vk_object_base_init(&device->vk, &semaphore->base, VK_OBJECT_TYPE_SEMAPHORE);
+
    p_atomic_set(&semaphore->refcount, 1);
 
    const VkExportSemaphoreCreateInfo *export =
@@ -1724,7 +1814,7 @@ VkResult anv_CreateSemaphore(
       else
          result = timeline_semaphore_create(device, &semaphore->permanent, timeline_value);
       if (result != VK_SUCCESS) {
-         vk_free2(&device->alloc, pAllocator, semaphore);
+         vk_free2(&device->vk.alloc, pAllocator, semaphore);
          return result;
       }
    } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) {
@@ -1732,17 +1822,17 @@ VkResult anv_CreateSemaphore(
       assert(sem_type == VK_SEMAPHORE_TYPE_BINARY_KHR);
       result = binary_semaphore_create(device, &semaphore->permanent, true);
       if (result != VK_SUCCESS) {
-         vk_free2(&device->alloc, pAllocator, semaphore);
+         vk_free2(&device->vk.alloc, pAllocator, semaphore);
          return result;
       }
    } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) {
       assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT);
       assert(sem_type == VK_SEMAPHORE_TYPE_BINARY_KHR);
-      if (device->instance->physicalDevice.has_syncobj) {
+      if (device->physical->has_syncobj) {
          semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ;
          semaphore->permanent.syncobj = anv_gem_syncobj_create(device, 0);
          if (!semaphore->permanent.syncobj) {
-            vk_free2(&device->alloc, pAllocator, semaphore);
+            vk_free2(&device->vk.alloc, pAllocator, semaphore);
             return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
          }
       } else {
@@ -1751,7 +1841,7 @@ VkResult anv_CreateSemaphore(
       }
    } else {
       assert(!"Unknown handle type");
-      vk_free2(&device->alloc, pAllocator, semaphore);
+      vk_free2(&device->vk.alloc, pAllocator, semaphore);
       return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE);
    }
 
@@ -1773,11 +1863,13 @@ anv_semaphore_impl_cleanup(struct anv_device *device,
       break;
 
    case ANV_SEMAPHORE_TYPE_BO:
+   case ANV_SEMAPHORE_TYPE_WSI_BO:
       anv_device_release_bo(device, impl->bo);
       break;
 
    case ANV_SEMAPHORE_TYPE_SYNC_FILE:
-      close(impl->fd);
+      if (impl->fd >= 0)
+         close(impl->fd);
       break;
 
    case ANV_SEMAPHORE_TYPE_TIMELINE:
@@ -1821,7 +1913,9 @@ anv_semaphore_unref(struct anv_device *device, struct anv_semaphore *semaphore)
 
    anv_semaphore_impl_cleanup(device, &semaphore->temporary);
    anv_semaphore_impl_cleanup(device, &semaphore->permanent);
-   vk_free(&device->alloc, semaphore);
+
+   vk_object_base_finish(&semaphore->base);
+   vk_free(&device->vk.alloc, semaphore);
 }
 
 void anv_DestroySemaphore(
@@ -1899,7 +1993,7 @@ VkResult anv_ImportSemaphoreFdKHR(
 
    switch (pImportSemaphoreFdInfo->handleType) {
    case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
-      if (device->instance->physicalDevice.has_syncobj) {
+      if (device->physical->has_syncobj) {
          new_impl.type = ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ;
 
          new_impl.syncobj = anv_gem_syncobj_fd_to_handle(device, fd);
@@ -1940,7 +2034,7 @@ VkResult anv_ImportSemaphoreFdKHR(
       break;
 
    case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
-      if (device->instance->physicalDevice.has_syncobj) {
+      if (device->physical->has_syncobj) {
          new_impl = (struct anv_semaphore_impl) {
             .type = ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ,
             .syncobj = anv_gem_syncobj_create(device, 0),
@@ -1949,8 +2043,7 @@ VkResult anv_ImportSemaphoreFdKHR(
             return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
          if (anv_gem_syncobj_import_sync_file(device, new_impl.syncobj, fd)) {
             anv_gem_syncobj_destroy(device, new_impl.syncobj);
-            return vk_errorf(device->instance, NULL,
-                             VK_ERROR_INVALID_EXTERNAL_HANDLE,
+            return vk_errorf(device, NULL, VK_ERROR_INVALID_EXTERNAL_HANDLE,
                              "syncobj sync file import failed: %m");
          }
          /* Ownership of the FD is transfered to Anv. Since we don't need it
@@ -2074,7 +2167,7 @@ VkResult anv_GetSemaphoreFdKHR(
    return VK_SUCCESS;
 }
 
-VkResult anv_GetSemaphoreCounterValueKHR(
+VkResult anv_GetSemaphoreCounterValue(
     VkDevice                                    _device,
     VkSemaphore                                 _semaphore,
     uint64_t*                                   pValue)
@@ -2160,9 +2253,10 @@ anv_timelines_wait(struct anv_device *device,
                    uint64_t abs_timeout_ns)
 {
    if (!wait_all && n_timelines > 1) {
+      pthread_mutex_lock(&device->mutex);
+
       while (1) {
          VkResult result;
-         pthread_mutex_lock(&device->mutex);
          for (uint32_t i = 0; i < n_timelines; i++) {
             result =
                anv_timeline_wait_locked(device, timelines[i], serials[i], 0);
@@ -2206,25 +2300,28 @@ anv_timelines_wait(struct anv_device *device,
    }
 }
 
-VkResult anv_WaitSemaphoresKHR(
+VkResult anv_WaitSemaphores(
     VkDevice                                    _device,
     const VkSemaphoreWaitInfoKHR*               pWaitInfo,
     uint64_t                                    timeout)
 {
    ANV_FROM_HANDLE(anv_device, device, _device);
 
+   if (device->no_hw)
+      return VK_SUCCESS;
+
    struct anv_timeline **timelines =
-      vk_alloc(&device->alloc,
+      vk_alloc(&device->vk.alloc,
                pWaitInfo->semaphoreCount * sizeof(*timelines),
                8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    if (!timelines)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   uint64_t *values = vk_alloc(&device->alloc,
+   uint64_t *values = vk_alloc(&device->vk.alloc,
                                pWaitInfo->semaphoreCount * sizeof(*values),
                                8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
    if (!values) {
-      vk_free(&device->alloc, timelines);
+      vk_free(&device->vk.alloc, timelines);
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
    }
 
@@ -2249,16 +2346,16 @@ VkResult anv_WaitSemaphoresKHR(
    if (handle_count > 0) {
       result = anv_timelines_wait(device, timelines, values, handle_count,
                                   !(pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT_KHR),
-                                  timeout);
+                                  anv_get_absolute_timeout(timeout));
    }
 
-   vk_free(&device->alloc, timelines);
-   vk_free(&device->alloc, values);
+   vk_free(&device->vk.alloc, timelines);
+   vk_free(&device->vk.alloc, values);
 
    return result;
 }
 
-VkResult anv_SignalSemaphoreKHR(
+VkResult anv_SignalSemaphore(
     VkDevice                                    _device,
     const VkSemaphoreSignalInfoKHR*             pSignalInfo)
 {