diff --git a/src/virtio/vulkan/vn_instance.c b/src/virtio/vulkan/vn_instance.c index ad0b9bf3850..b4617921acb 100644 --- a/src/virtio/vulkan/vn_instance.c +++ b/src/virtio/vulkan/vn_instance.c @@ -232,7 +232,7 @@ vn_instance_init_experimental_features(struct vn_instance *instance) if (!exp_feats->memoryResourceAllocationSize || !exp_feats->globalFencing || !exp_feats->largeRing || - !exp_feats->syncFdFencing) + !exp_feats->syncFdFencing || !exp_feats->asyncRoundtrip) return VK_ERROR_INITIALIZATION_FAILED; if (VN_DEBUG(INIT)) { @@ -334,14 +334,8 @@ vn_instance_submit_roundtrip(struct vn_instance *instance, mtx_lock(&instance->ring.roundtrip_mutex); const uint64_t seqno = instance->ring.roundtrip_next++; - if (instance->experimental.asyncRoundtrip) { - vn_encode_vkSubmitVirtqueueSeqno100000MESA(&local_enc, 0, - instance->ring.id, seqno); - } else { - /* clamp to 32bit for legacy ring extra based roundtrip waiting */ - vn_encode_vkWriteRingExtraMESA(&local_enc, 0, instance->ring.id, 0, - seqno); - } + vn_encode_vkSubmitVirtqueueSeqno100000MESA(&local_enc, 0, + instance->ring.id, seqno); VkResult result = vn_renderer_submit_simple( instance->renderer, local_data, vn_cs_encoder_get_len(&local_enc)); mtx_unlock(&instance->ring.roundtrip_mutex); @@ -350,36 +344,11 @@ vn_instance_submit_roundtrip(struct vn_instance *instance, return result; } -static bool -roundtrip_seqno_ge(uint32_t a, uint32_t b) -{ - /* a >= b, but deal with wrapping as well */ - return (a - b) <= INT32_MAX; -} - void vn_instance_wait_roundtrip(struct vn_instance *instance, uint64_t roundtrip_seqno) { - VN_TRACE_FUNC(); - - if (instance->experimental.asyncRoundtrip) { - vn_async_vkWaitVirtqueueSeqno100000MESA(instance, roundtrip_seqno); - return; - } - - struct vn_ring *ring = &instance->ring.ring; - const volatile atomic_uint *ptr = ring->shared.extra; - struct vn_relax_state relax_state = vn_relax_init(ring, "roundtrip"); - do { - const uint32_t cur = atomic_load_explicit(ptr, memory_order_acquire); - /* clamp to 32bit for legacy ring extra based roundtrip waiting */ - if (roundtrip_seqno_ge(cur, roundtrip_seqno)) { - vn_relax_fini(&relax_state); - break; - } - vn_relax(&relax_state); - } while (true); + vn_async_vkWaitVirtqueueSeqno100000MESA(instance, roundtrip_seqno); } struct vn_instance_submission { diff --git a/src/virtio/vulkan/vn_instance.h b/src/virtio/vulkan/vn_instance.h index 86d2001957c..bff0d5b5b56 100644 --- a/src/virtio/vulkan/vn_instance.h +++ b/src/virtio/vulkan/vn_instance.h @@ -129,6 +129,7 @@ struct vn_instance_submit_command { struct vn_renderer_shmem *reply_shmem; struct vn_cs_decoder reply; + /* valid when instance ring submission succeeds */ bool ring_seqno_valid; uint32_t ring_seqno; }; diff --git a/src/virtio/vulkan/vn_queue.c b/src/virtio/vulkan/vn_queue.c index fb6f4021d04..3a0b8168525 100644 --- a/src/virtio/vulkan/vn_queue.c +++ b/src/virtio/vulkan/vn_queue.c @@ -58,13 +58,11 @@ struct vn_queue_submission { }; VkFence fence_handle; - /* TODO remove synchronous when asyncRoundtrip is required */ - bool synchronous; bool has_feedback_fence; bool has_feedback_semaphore; const struct vn_device_memory *wsi_mem; uint32_t sem_cmd_buffer_count; - struct vn_sync_payload_external external; + struct vn_sync_payload_external external_payload; /* Temporary storage allocation for submission * A single alloc for storage is performed and the offsets inside @@ -231,10 +229,6 @@ vn_queue_submission_fix_batch_semaphores(struct vn_queue_submission *submit, for (uint32_t i = 0; i < signal_count; i++) { struct vn_semaphore *sem = vn_semaphore_from_handle( vn_get_signal_semaphore(submit, batch_index, i)); - - /* see vn_queue_submission_prepare */ - submit->synchronous |= sem->is_external; - if (sem->feedback.slot) { batch_has_sem_feedback = true; submit->sem_cmd_buffer_count++; @@ -254,9 +248,11 @@ vn_queue_submission_fix_batch_semaphores(struct vn_queue_submission *submit, static VkResult vn_queue_submission_prepare(struct vn_queue_submission *submit) { + struct vn_queue *queue = vn_queue_from_handle(submit->queue_handle); struct vn_fence *fence = vn_fence_from_handle(submit->fence_handle); const bool has_external_fence = fence && fence->is_external; + submit->external_payload.ring_idx = queue->ring_idx; submit->has_feedback_fence = fence && fence->feedback.slot; assert(!has_external_fence || !submit->has_feedback_fence); @@ -270,21 +266,6 @@ vn_queue_submission_prepare(struct vn_queue_submission *submit) } } - /* To ensure external components waiting on the correct fence payload, - * below sync primitives must be installed after the submission: - * - explicit fencing: sync file export - * - implicit fencing: dma-fence attached to the wsi bo - * - * We enforce above via an asynchronous vkQueueSubmit(2) via ring followed - * by an asynchronous renderer submission to wait for the ring submission: - * - struct wsi_memory_signal_submit_info - * - fence is an external fence - * - has an external signal semaphore - */ - struct vn_queue *queue = vn_queue_from_handle(submit->queue_handle); - submit->external.ring_idx = queue->ring_idx; - submit->synchronous = has_external_fence || submit->wsi_mem; - for (uint32_t i = 0; i < submit->batch_count; i++) { VkResult result = vn_queue_submission_fix_batch_semaphores(submit, i); if (result != VK_SUCCESS) @@ -800,15 +781,16 @@ vn_queue_wsi_present(struct vn_queue_submission *submit) if (dev->instance->renderer->info.has_implicit_fencing) { struct vn_renderer_submit_batch batch = { - .ring_idx = submit->external.ring_idx, + .ring_idx = submit->external_payload.ring_idx, }; uint32_t local_data[8]; struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(local_data, sizeof(local_data)); - if (submit->external.ring_seqno_valid) { - vn_encode_vkWaitRingSeqno100000MESA(&local_enc, 0, instance->ring.id, - submit->external.ring_seqno); + if (submit->external_payload.ring_seqno_valid) { + vn_encode_vkWaitRingSeqno100000MESA( + &local_enc, 0, instance->ring.id, + submit->external_payload.ring_seqno); batch.cs_data = local_data; batch.cs_size = vn_cs_encoder_get_len(&local_enc); } @@ -840,6 +822,17 @@ vn_queue_submit(struct vn_queue_submission *submit) struct vn_instance *instance = dev->instance; VkResult result; + /* To ensure external components waiting on the correct fence payload, + * below sync primitives must be installed after the submission: + * - explicit fencing: sync file export + * - implicit fencing: dma-fence attached to the wsi bo + * + * We enforce above via an asynchronous vkQueueSubmit(2) via ring followed + * by an asynchronous renderer submission to wait for the ring submission: + * - struct wsi_memory_signal_submit_info + * - fence is an external fence + * - has an external signal semaphore + */ result = vn_queue_submission_prepare_submit(submit); if (result != VK_SUCCESS) return vn_error(dev->instance, result); @@ -848,8 +841,7 @@ vn_queue_submit(struct vn_queue_submission *submit) if (!submit->batch_count && submit->fence_handle == VK_NULL_HANDLE) return VK_SUCCESS; - if ((!instance->experimental.asyncRoundtrip && submit->synchronous) || - VN_PERF(NO_ASYNC_QUEUE_SUBMIT)) { + if (VN_PERF(NO_ASYNC_QUEUE_SUBMIT)) { if (submit->batch_type == VK_STRUCTURE_TYPE_SUBMIT_INFO_2) { result = vn_call_vkQueueSubmit2( instance, submit->queue_handle, submit->batch_count, @@ -879,8 +871,8 @@ vn_queue_submit(struct vn_queue_submission *submit) vn_queue_submission_cleanup(submit); return vn_error(dev->instance, VK_ERROR_DEVICE_LOST); } - submit->external.ring_seqno_valid = true; - submit->external.ring_seqno = instance_submit.ring_seqno; + submit->external_payload.ring_seqno_valid = true; + submit->external_payload.ring_seqno = instance_submit.ring_seqno; } /* If external fence, track the submission's ring_idx to facilitate @@ -892,7 +884,7 @@ vn_queue_submit(struct vn_queue_submission *submit) struct vn_fence *fence = vn_fence_from_handle(submit->fence_handle); if (fence && fence->is_external) { assert(fence->payload->type == VN_SYNC_TYPE_DEVICE_ONLY); - fence->external = submit->external; + fence->external_payload = submit->external_payload; } for (uint32_t i = 0; i < submit->batch_count; i++) { @@ -903,7 +895,7 @@ vn_queue_submit(struct vn_queue_submission *submit) vn_semaphore_from_handle(vn_get_signal_semaphore(submit, i, j)); if (sem->is_external) { assert(sem->payload->type == VN_SYNC_TYPE_DEVICE_ONLY); - sem->external = submit->external; + sem->external_payload = submit->external_payload; } } } @@ -1356,7 +1348,7 @@ vn_WaitForFences(VkDevice device, static VkResult vn_create_sync_file(struct vn_device *dev, - struct vn_sync_payload_external *payload, + struct vn_sync_payload_external *external_payload, int *out_fd) { struct vn_renderer_sync *sync; @@ -1369,15 +1361,15 @@ vn_create_sync_file(struct vn_device *dev, .syncs = &sync, .sync_values = &(const uint64_t){ 1 }, .sync_count = 1, - .ring_idx = payload->ring_idx, + .ring_idx = external_payload->ring_idx, }; uint32_t local_data[8]; struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL(local_data, sizeof(local_data)); - if (payload->ring_seqno_valid) { + if (external_payload->ring_seqno_valid) { vn_encode_vkWaitRingSeqno100000MESA( - &local_enc, 0, dev->instance->ring.id, payload->ring_seqno); + &local_enc, 0, dev->instance->ring.id, external_payload->ring_seqno); batch.cs_data = local_data; batch.cs_size = vn_cs_encoder_get_len(&local_enc); } @@ -1450,7 +1442,7 @@ vn_GetFenceFdKHR(VkDevice device, int fd = -1; if (payload->type == VN_SYNC_TYPE_DEVICE_ONLY) { - result = vn_create_sync_file(dev, &fence->external, &fd); + result = vn_create_sync_file(dev, &fence->external_payload, &fd); if (result != VK_SUCCESS) return vn_error(dev->instance, result); @@ -1912,7 +1904,7 @@ vn_GetSemaphoreFdKHR(VkDevice device, int fd = -1; if (payload->type == VN_SYNC_TYPE_DEVICE_ONLY) { - VkResult result = vn_create_sync_file(dev, &sem->external, &fd); + VkResult result = vn_create_sync_file(dev, &sem->external_payload, &fd); if (result != VK_SUCCESS) return vn_error(dev->instance, result); diff --git a/src/virtio/vulkan/vn_queue.h b/src/virtio/vulkan/vn_queue.h index 935ebe13eb5..b3bf2145875 100644 --- a/src/virtio/vulkan/vn_queue.h +++ b/src/virtio/vulkan/vn_queue.h @@ -58,11 +58,7 @@ struct vn_sync_payload { struct vn_sync_payload_external { /* ring_idx of the last queue submission */ uint32_t ring_idx; - /* ring_seqno_valid is false when: - * - feature asyncRoundtrip is not supported by the renderer - * - NO_ASYNC_QUEUE_SUBMIT perf option is used - * - external fence and external semaphore - */ + /* valid when NO_ASYNC_QUEUE_SUBMIT perf option is not used */ bool ring_seqno_valid; /* ring seqno of the last queue submission */ uint32_t ring_seqno; @@ -83,7 +79,7 @@ struct vn_fence { } feedback; bool is_external; - struct vn_sync_payload_external external; + struct vn_sync_payload_external external_payload; }; VK_DEFINE_NONDISP_HANDLE_CASTS(vn_fence, base.base, @@ -133,7 +129,7 @@ struct vn_semaphore { } feedback; bool is_external; - struct vn_sync_payload_external external; + struct vn_sync_payload_external external_payload; }; VK_DEFINE_NONDISP_HANDLE_CASTS(vn_semaphore, base.base,