venus: requires asyncRoundtrip

Signed-off-by: Yiwei Zhang <zzyiwei@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22323>
This commit is contained in:
Yiwei Zhang
2023-04-05 14:42:26 -07:00
committed by Marge Bot
parent 3cbd4fb61b
commit 5fcb2830e6
4 changed files with 38 additions and 80 deletions
+4 -35
View File
@@ -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 {
+1
View File
@@ -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;
};
+30 -38
View File
@@ -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);
+3 -7
View File
@@ -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,