X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fintel%2Fvulkan%2Fanv_queue.c;h=7ba64af54c46d580c9fe8fd765f4852bcfaf84d4;hb=32e0f7e09721d4097f7b134b679053f48c216668;hp=76fc93fde371ffc3e6424fb9b52cf51df751b470;hpb=2c5eb1df681e28c23e24219eab803b6d4da5aa38;p=mesa.git diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index 76fc93fde37..7ba64af54c4 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -29,6 +29,8 @@ #include #include +#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,12 +568,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; @@ -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->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); @@ -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,12 +1110,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; @@ -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,24 +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->instance, NULL, - VK_ERROR_INVALID_EXTERNAL_HANDLE, + 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); @@ -1728,7 +1761,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) @@ -1774,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 = @@ -1793,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) { @@ -1801,17 +1836,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 { @@ -1820,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); } @@ -1847,7 +1882,8 @@ anv_semaphore_impl_cleanup(struct anv_device *device, break; case ANV_SEMAPHORE_TYPE_SYNC_FILE: - close(impl->fd); + if (impl->fd >= 0) + close(impl->fd); break; case ANV_SEMAPHORE_TYPE_TIMELINE: @@ -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( @@ -1969,7 +2007,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); @@ -2010,7 +2048,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), @@ -2019,8 +2057,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 @@ -2144,7 +2181,7 @@ VkResult anv_GetSemaphoreFdKHR( return VK_SUCCESS; } -VkResult anv_GetSemaphoreCounterValueKHR( +VkResult anv_GetSemaphoreCounterValue( VkDevice _device, VkSemaphore _semaphore, uint64_t* pValue) @@ -2159,6 +2196,7 @@ VkResult anv_GetSemaphoreCounterValueKHR( 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; @@ -2230,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); @@ -2276,25 +2315,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); } @@ -2319,16 +2361,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) {