nir: Add a nir_foreach_uniform_variable helper
[mesa.git] / src / intel / vulkan / anv_queue.c
index b93d070711de22c2027b46fb1aea167cdf6418c0..7ba64af54c46d580c9fe8fd765f4852bcfaf84d4 100644 (file)
@@ -29,6 +29,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include "util/os_file.h"
+
 #include "anv_private.h"
 #include "vk_util.h"
 
@@ -139,13 +141,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 +161,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 +172,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,
@@ -295,7 +297,7 @@ anv_queue_submit_timeline_locked(struct anv_queue *queue,
          struct anv_semaphore_impl *impl = &semaphore->permanent;
 
          assert(impl->type == ANV_SEMAPHORE_TYPE_SYNC_FILE);
-         impl->fd = dup(submit->out_fence);
+         impl->fd = os_dupfd_cloexec(submit->out_fence);
       }
    } else {
       /* Unblock any waiter by signaling the points, the application will get
@@ -381,7 +383,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;
 
@@ -393,6 +395,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
@@ -543,9 +546,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);
@@ -556,6 +559,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;
 }
@@ -564,8 +568,11 @@ 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);
 
@@ -716,12 +723,13 @@ anv_queue_submit(struct anv_queue *queue,
                  const uint64_t *out_values,
                  uint32_t num_out_semaphores,
                  struct anv_bo *wsi_signal_bo,
-                 VkFence _fence)
+                 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->physical;
-   struct anv_queue_submit *submit = anv_queue_submit_alloc(device);
+   struct anv_queue_submit *submit = anv_queue_submit_alloc(device, perf_query_pass);
    if (!submit)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -947,6 +955,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
@@ -965,7 +976,7 @@ VkResult anv_QueueSubmit(
        * common case.
        */
       result = anv_queue_submit(queue, NULL, NULL, NULL, 0, NULL, NULL, 0,
-                                NULL, fence);
+                                NULL, fence, -1);
       goto out;
    }
 
@@ -983,6 +994,9 @@ VkResult anv_QueueSubmit(
       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;
@@ -1004,7 +1018,8 @@ VkResult anv_QueueSubmit(
                                    signal_values,
                                    pSubmits[i].signalSemaphoreCount,
                                    wsi_signal_bo,
-                                   submit_fence);
+                                   submit_fence,
+                                   -1);
          if (result != VK_SUCCESS)
             goto out;
 
@@ -1042,7 +1057,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,
-                                   wsi_signal_bo, execbuf_fence);
+                                   wsi_signal_bo, execbuf_fence,
+                                   perf_info ? perf_info->counterPassIndex : 0);
          if (result != VK_SUCCESS)
             goto out;
       }
@@ -1094,11 +1110,13 @@ 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);
 
+   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;
 
@@ -1185,7 +1203,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(
@@ -1291,7 +1310,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)
@@ -1319,7 +1338,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) {
@@ -1537,6 +1556,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;
 
@@ -1611,23 +1633,35 @@ VkResult anv_ImportFenceFdKHR(
 
       break;
 
-   case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
+   case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT: {
       /* Sync files are a bit tricky.  Because we want to continue using the
        * syncobj implementation of WaitForFences, we don't use the sync file
        * directly but instead import it into a syncobj.
        */
       new_impl.type = ANV_FENCE_TYPE_SYNCOBJ;
 
-      new_impl.syncobj = anv_gem_syncobj_create(device, 0);
+      /* "If handleType is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, the
+       *  special value -1 for fd is treated like a valid sync file descriptor
+       *  referring to an object that has already signaled. The import
+       *  operation will succeed and the VkFence will have a temporarily
+       *  imported payload as if a valid file descriptor had been provided."
+       */
+      uint32_t create_flags = 0;
+      if (fd == -1)
+         create_flags |= DRM_SYNCOBJ_CREATE_SIGNALED;
+
+      new_impl.syncobj = anv_gem_syncobj_create(device, create_flags);
       if (!new_impl.syncobj)
          return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-      if (anv_gem_syncobj_import_sync_file(device, new_impl.syncobj, fd)) {
+      if (fd != -1 &&
+          anv_gem_syncobj_import_sync_file(device, new_impl.syncobj, fd)) {
          anv_gem_syncobj_destroy(device, new_impl.syncobj);
          return vk_errorf(device, NULL, VK_ERROR_INVALID_EXTERNAL_HANDLE,
                           "syncobj sync file import failed: %m");
       }
       break;
+   }
 
    default:
       return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE);
@@ -1773,11 +1807,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 =
@@ -1792,7 +1828,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) {
@@ -1800,7 +1836,7 @@ 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) {
@@ -1810,7 +1846,7 @@ VkResult anv_CreateSemaphore(
          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 {
@@ -1819,7 +1855,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);
    }
 
@@ -1891,7 +1927,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(
@@ -2158,6 +2196,7 @@ VkResult anv_GetSemaphoreCounterValue(
    switch (impl->type) {
    case ANV_SEMAPHORE_TYPE_TIMELINE: {
       pthread_mutex_lock(&device->mutex);
+      anv_timeline_gc_locked(device, &impl->timeline);
       *pValue = impl->timeline.highest_past;
       pthread_mutex_unlock(&device->mutex);
       return VK_SUCCESS;
@@ -2229,9 +2268,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);
@@ -2282,18 +2322,21 @@ VkResult anv_WaitSemaphores(
 {
    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);
    }
 
@@ -2318,11 +2361,11 @@ VkResult anv_WaitSemaphores(
    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;
 }