--- src/intel/vulkan/anv_batch_chain.c | 91 ++++++++++++++++++++++++++++++++++++-- src/intel/vulkan/anv_device.c | 26 +++++++++++ src/intel/vulkan/anv_gem.c | 36 +++++++++++++++ src/intel/vulkan/anv_private.h | 9 +++- src/intel/vulkan/anv_queue.c | 68 +++++++++++++++++++++++++--- 5 files changed, 220 insertions(+), 10 deletions(-)
diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c index 3640588..004594a 100644 --- a/src/intel/vulkan/anv_batch_chain.c +++ b/src/intel/vulkan/anv_batch_chain.c @@ -1352,6 +1352,28 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf, } } +static void +setup_empty_execbuf(struct anv_execbuf *execbuf, struct anv_device *device) +{ + anv_execbuf_add_bo(execbuf, &device->trivial_batch_bo, NULL, 0, + &device->alloc); + + execbuf->execbuf = (struct drm_i915_gem_execbuffer2) { + .buffers_ptr = (uintptr_t) execbuf->objects, + .buffer_count = execbuf->bo_count, + .batch_start_offset = 0, + .batch_len = 8, /* GEN8_MI_BATCH_BUFFER_END and NOOP */ + .cliprects_ptr = 0, + .num_cliprects = 0, + .DR1 = 0, + .DR4 = 0, + .flags = I915_EXEC_HANDLE_LUT | I915_EXEC_RENDER | + I915_EXEC_CONSTANTS_REL_GENERAL, + .rsvd1 = device->context_id, + .rsvd2 = 0, + }; +} + VkResult anv_cmd_buffer_execbuf(struct anv_device *device, struct anv_cmd_buffer *cmd_buffer, @@ -1363,22 +1385,50 @@ anv_cmd_buffer_execbuf(struct anv_device *device, struct anv_execbuf execbuf; anv_execbuf_init(&execbuf); + int in_fence = -1; for (uint32_t i = 0; i < num_in_semaphores; i++) { ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]); - assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE); - struct anv_semaphore_impl *impl = &semaphore->permanent; + struct anv_semaphore_impl *impl = + semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE ? + &semaphore->temporary : &semaphore->permanent; switch (impl->type) { case ANV_SEMAPHORE_TYPE_BO: anv_execbuf_add_bo(&execbuf, &impl->bo, NULL, 0, &device->alloc); break; + case ANV_SEMAPHORE_TYPE_SYNC_FILE: + if (in_fence == -1) { + in_fence = impl->fd; + } else { + int merge = anv_gem_sync_file_merge(device, in_fence, impl->fd); + if (merge == -1) + return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); + + close(impl->fd); + close(in_fence); + in_fence = merge; + } + + impl->fd = -1; default: break; } + + /* Waiting on a semaphore with temporary state implicitly resets it back + * to the permanent state. + */ + if (semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE) { + assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_SYNC_FILE); + semaphore->temporary.type = ANV_SEMAPHORE_TYPE_NONE; + } } + bool need_out_fence = false; for (uint32_t i = 0; i < num_out_semaphores; i++) { ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]); + /* Out fences can't have temporary state because that would imply + * that we imported a sync file and are trying to signal it. + */ assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE); struct anv_semaphore_impl *impl = &semaphore->permanent; @@ -1387,15 +1437,50 @@ anv_cmd_buffer_execbuf(struct anv_device *device, anv_execbuf_add_bo(&execbuf, &impl->bo, NULL, EXEC_OBJECT_WRITE, &device->alloc); break; + + case ANV_SEMAPHORE_TYPE_SYNC_FILE: + need_out_fence = true; + break; + default: break; } } - setup_execbuf_for_cmd_buffer(&execbuf, cmd_buffer); + if (cmd_buffer) { + setup_execbuf_for_cmd_buffer(&execbuf, cmd_buffer); + } else { + setup_empty_execbuf(&execbuf, device); + } + + if (in_fence != -1) { + execbuf.execbuf.flags |= I915_EXEC_FENCE_IN; + execbuf.execbuf.rsvd2 |= (uint32_t)in_fence; + } + + if (need_out_fence) + execbuf.execbuf.flags |= I915_EXEC_FENCE_OUT; VkResult result = anv_device_execbuf(device, &execbuf.execbuf, execbuf.bos); + if (need_out_fence) { + int out_fence = execbuf.execbuf.rsvd2 >> 32; + for (uint32_t i = 0; i < num_out_semaphores; i++) { + ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]); + /* Out fences can't have temporary state because that would imply + * that we imported a sync file and are trying to signal it. + */ + assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE); + struct anv_semaphore_impl *impl = &semaphore->permanent; + + if (impl->type == ANV_SEMAPHORE_TYPE_SYNC_FILE) { + assert(impl->fd == -1); + impl->fd = dup(out_fence); + } + } + close(out_fence); + } + anv_execbuf_finish(&execbuf, &device->alloc); return result; diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 323e17a..5ac3c5d 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -190,6 +190,8 @@ anv_physical_device_init(struct anv_physical_device *device, goto fail; } + device->has_exec_fence = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_FENCE); + bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X); /* GENs prior to 8 do not support EU/Subslice info */ @@ -969,6 +971,26 @@ anv_device_init_border_colors(struct anv_device *device) border_colors); } +static void +anv_device_init_trivial_batch(struct anv_device *device) +{ + anv_bo_init_new(&device->trivial_batch_bo, device, 4096); + void *map = anv_gem_mmap(device, device->trivial_batch_bo.gem_handle, + 0, 4096, 0); + + struct anv_batch batch; + batch.start = batch.next = map; + batch.end = map + 4096; + + anv_batch_emit(&batch, GEN7_MI_BATCH_BUFFER_END, bbe); + anv_batch_emit(&batch, GEN7_MI_NOOP, noop); + + if (!device->info.has_llc) + anv_clflush_range(map, batch.next - map); + + anv_gem_munmap(map, device->trivial_batch_bo.size); +} + VkResult anv_CreateDevice( VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, @@ -1061,6 +1083,8 @@ VkResult anv_CreateDevice( anv_bo_init_new(&device->workaround_bo, device, 1024); + anv_device_init_trivial_batch(device); + anv_scratch_pool_init(device, &device->scratch_pool); anv_queue_init(device, &device->queue); @@ -1124,6 +1148,8 @@ void anv_DestroyDevice( anv_gem_munmap(device->workaround_bo.map, device->workaround_bo.size); anv_gem_close(device, device->workaround_bo.gem_handle); + anv_gem_close(device, device->trivial_batch_bo.gem_handle); + anv_state_pool_finish(&device->surface_state_pool); anv_block_pool_finish(&device->surface_state_block_pool); anv_state_pool_finish(&device->instruction_state_pool); diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c index d8beab1..a26ea7c 100644 --- a/src/intel/vulkan/anv_gem.c +++ b/src/intel/vulkan/anv_gem.c @@ -22,6 +22,7 @@ */ #include <sys/ioctl.h> +#include <sys/types.h> #include <sys/mman.h> #include <string.h> #include <errno.h> @@ -332,3 +333,38 @@ anv_gem_fd_to_handle(struct anv_device *device, int fd) return args.handle; } + +#ifndef SYNC_IOC_MAGIC +/* duplicated from linux/sync_file.h to avoid build-time depnedency + * on new (v4.7) kernel headers. Once distro's are mostly using + * something newer than v4.7 drop this and #include <linux/sync_file.h> + * instead. + */ +struct sync_merge_data { + char name[32]; + __s32 fd2; + __s32 fence; + __u32 flags; + __u32 pad; +}; + +#define SYNC_IOC_MAGIC '>' +#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) +#endif + +int +anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2) +{ + const char name[] = "anv merge fence"; + struct sync_merge_data args = { + .fd2 = fd2, + .fence = -1, + }; + memcpy(args.name, name, sizeof(name)); + + int ret = anv_ioctl(device->fd, SYNC_IOC_MERGE, &args); + if (ret == -1) + return -1; + + return args.fence; +} diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 8763cbb..5c374d8 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -526,6 +526,7 @@ struct anv_physical_device { struct brw_compiler * compiler; struct isl_device isl_dev; int cmd_parser_version; + bool has_exec_fence; uint32_t eu_total; uint32_t subslice_total; @@ -610,6 +611,7 @@ struct anv_device { struct anv_state_pool surface_state_pool; struct anv_bo workaround_bo; + struct anv_bo trivial_batch_bo; struct anv_pipeline_cache blorp_shader_cache; struct blorp_context blorp; @@ -663,6 +665,7 @@ uint32_t anv_gem_fd_to_handle(struct anv_device *device, int fd); int anv_gem_set_caching(struct anv_device *device, uint32_t gem_handle, uint32_t caching); int anv_gem_set_domain(struct anv_device *device, uint32_t gem_handle, uint32_t read_domains, uint32_t write_domain); +int anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2); VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size); @@ -1373,12 +1376,16 @@ enum anv_semaphore_type { ANV_SEMAPHORE_TYPE_NONE = 0, ANV_SEMAPHORE_TYPE_DUMMY, ANV_SEMAPHORE_TYPE_BO, + ANV_SEMAPHORE_TYPE_SYNC_FILE, }; struct anv_semaphore_impl { enum anv_semaphore_type type; - struct anv_bo bo; + union { + struct anv_bo bo; + int fd; + }; }; struct anv_semaphore { diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index 656ab1a..6bd1435 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -156,6 +156,23 @@ VkResult anv_QueueSubmit( pthread_mutex_lock(&device->mutex); for (uint32_t i = 0; i < submitCount; i++) { + if (pSubmits[i].commandBufferCount == 0) { + /* If we don't have any command buffers, we need to submit a dummy + * batch to give GEM something to wait on. We could, potentially, + * come up with something more efficient but this shouldn't be a + * common case. + */ + result = anv_cmd_buffer_execbuf(device, NULL, + pSubmits[i].pWaitSemaphores, + pSubmits[i].waitSemaphoreCount, + pSubmits[i].pSignalSemaphores, + pSubmits[i].signalSemaphoreCount); + if (result != VK_SUCCESS) + goto out; + + continue; + } + for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) { ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, pSubmits[i].pCommandBuffers[j]); @@ -503,6 +520,11 @@ VkResult anv_CreateSemaphore( vk_free2(&device->alloc, pAllocator, semaphore); return result; } + } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX) { + assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX); + + semaphore->permanent.type = ANV_SEMAPHORE_TYPE_SYNC_FILE; + semaphore->permanent.fd = -1; } else { assert(!"Unknown handle type"); vk_free2(&device->alloc, pAllocator, semaphore); @@ -530,6 +552,10 @@ anv_semaphore_impl_cleanup(struct anv_device *device, anv_gem_close(device, impl->bo.gem_handle); break; + case ANV_SEMAPHORE_TYPE_SYNC_FILE: + close(impl->fd); + break; + default: unreachable("Invalid semaphore type"); } @@ -554,6 +580,8 @@ void anv_GetPhysicalDeviceExternalSemaphorePropertiesKHX( const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties) { + ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice); + switch (pExternalSemaphoreInfo->handleType) { case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX: pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; @@ -562,13 +590,27 @@ void anv_GetPhysicalDeviceExternalSemaphorePropertiesKHX( pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX; + return; + + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX: + if (device->has_exec_fence) { + pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; + pExternalSemaphoreProperties->compatibleHandleTypes = + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX; + pExternalSemaphoreProperties->externalSemaphoreFeatures = + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX; + return; + } break; default: - pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; - pExternalSemaphoreProperties->compatibleHandleTypes = 0; - pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; + break; } + + pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; + pExternalSemaphoreProperties->compatibleHandleTypes = 0; + pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; } VkResult anv_ImportSemaphoreFdKHX( @@ -596,12 +638,21 @@ VkResult anv_ImportSemaphoreFdKHX( */ close(pImportSemaphoreFdInfo->fd); - anv_semaphore_impl_cleanup(device, &semaphore->permanent); - semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO; - anv_bo_init(&semaphore->permanent.bo, gem_handle, 4096); + if (semaphore->permanent.type != ANV_SEMAPHORE_TYPE_BO || + semaphore->permanent.bo.gem_handle != gem_handle) { + anv_semaphore_impl_cleanup(device, &semaphore->permanent); + semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO; + anv_bo_init(&semaphore->permanent.bo, gem_handle, 4096); + } return VK_SUCCESS; } + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX: + anv_semaphore_impl_cleanup(device, &semaphore->temporary); + semaphore->temporary.type = ANV_SEMAPHORE_TYPE_SYNC_FILE; + semaphore->temporary.fd = pImportSemaphoreFdInfo->fd; + return VK_SUCCESS; + default: return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); } @@ -624,6 +675,11 @@ VkResult anv_GetSemaphoreFdKHX( return vk_error(VK_ERROR_TOO_MANY_OBJECTS); break; + case ANV_SEMAPHORE_TYPE_SYNC_FILE: + fd = semaphore->permanent.fd; + semaphore->permanent.fd = -1; + break; + default: return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX); } -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev