diff --git a/src/virtio/vulkan/vn_instance.c b/src/virtio/vulkan/vn_instance.c index ad73f850d90..a7fcf74a56f 100644 --- a/src/virtio/vulkan/vn_instance.c +++ b/src/virtio/vulkan/vn_instance.c @@ -19,6 +19,8 @@ #include "vn_physical_device.h" #include "vn_renderer.h" +#define VN_INSTANCE_RING_DIRECT_THRESHOLD (256) + /* * Instance extensions add instance-level or physical-device-level * functionalities. It seems renderer support is either unnecessary or @@ -322,18 +324,24 @@ vn_instance_wait_roundtrip(struct vn_instance *instance, } struct vn_instance_submission { - uint32_t local_cs_data[64]; - - void *cs_data; - size_t cs_size; + const struct vn_cs_encoder *cs; struct vn_ring_submit *submit; + + struct { + struct vn_cs_encoder cs; + struct vn_cs_encoder_buffer buffer; + uint32_t data[64]; + } indirect; }; -static void * -vn_instance_submission_indirect_cs(struct vn_instance_submission *submit, - const struct vn_cs_encoder *cs, - size_t *cs_size) +static const struct vn_cs_encoder * +vn_instance_submission_get_cs(struct vn_instance_submission *submit, + const struct vn_cs_encoder *cs, + bool direct) { + if (direct) + return cs; + VkCommandStreamDescriptionMESA local_descs[8]; VkCommandStreamDescriptionMESA *descs = local_descs; if (cs->buffer_count > ARRAY_SIZE(local_descs)) { @@ -357,47 +365,27 @@ vn_instance_submission_indirect_cs(struct vn_instance_submission *submit, const size_t exec_size = vn_sizeof_vkExecuteCommandStreamsMESA( desc_count, descs, NULL, 0, NULL, 0); - void *exec_data = submit->local_cs_data; - if (exec_size > sizeof(submit->local_cs_data)) { + void *exec_data = submit->indirect.data; + if (exec_size > sizeof(submit->indirect.data)) { exec_data = malloc(exec_size); - if (!exec_data) - goto out; + if (!exec_data) { + if (descs != local_descs) + free(descs); + return NULL; + } } - struct vn_cs_encoder local_enc = - VN_CS_ENCODER_INITIALIZER_LOCAL(exec_data, exec_size); - vn_encode_vkExecuteCommandStreamsMESA(&local_enc, 0, desc_count, descs, - NULL, 0, NULL, 0); + submit->indirect.buffer = VN_CS_ENCODER_BUFFER_INITIALIZER(exec_data); + submit->indirect.cs = + VN_CS_ENCODER_INITIALIZER(&submit->indirect.buffer, exec_size); + vn_encode_vkExecuteCommandStreamsMESA(&submit->indirect.cs, 0, desc_count, + descs, NULL, 0, NULL, 0); + vn_cs_encoder_commit(&submit->indirect.cs); - *cs_size = vn_cs_encoder_get_len(&local_enc); - -out: if (descs != local_descs) free(descs); - return exec_data; -} - -static void * -vn_instance_submission_direct_cs(struct vn_instance_submission *submit, - const struct vn_cs_encoder *cs, - size_t *cs_size) -{ - if (cs->buffer_count == 1) { - *cs_size = cs->buffers[0].committed_size; - return cs->buffers[0].base; - } - - assert(vn_cs_encoder_get_len(cs) <= sizeof(submit->local_cs_data)); - void *dst = submit->local_cs_data; - for (uint32_t i = 0; i < cs->buffer_count; i++) { - const struct vn_cs_encoder_buffer *buf = &cs->buffers[i]; - memcpy(dst, buf->base, buf->committed_size); - dst += buf->committed_size; - } - - *cs_size = dst - (void *)submit->local_cs_data; - return submit->local_cs_data; + return &submit->indirect.cs; } static struct vn_ring_submit * @@ -428,12 +416,11 @@ vn_instance_submission_get_ring_submit(struct vn_ring *ring, } static void -vn_instance_submission_cleanup(struct vn_instance_submission *submit, - const struct vn_cs_encoder *cs) +vn_instance_submission_cleanup(struct vn_instance_submission *submit) { - if (submit->cs_data != submit->local_cs_data && - submit->cs_data != cs->buffers[0].base) - free(submit->cs_data); + if (submit->cs == &submit->indirect.cs && + submit->indirect.buffer.base != submit->indirect.data) + free(submit->indirect.buffer.base); } static VkResult @@ -443,20 +430,14 @@ vn_instance_submission_prepare(struct vn_instance_submission *submit, struct vn_renderer_shmem *extra_shmem, bool direct) { - if (direct) { - submit->cs_data = - vn_instance_submission_direct_cs(submit, cs, &submit->cs_size); - } else { - submit->cs_data = - vn_instance_submission_indirect_cs(submit, cs, &submit->cs_size); - } - if (!submit->cs_data) + submit->cs = vn_instance_submission_get_cs(submit, cs, direct); + if (!submit->cs) return VK_ERROR_OUT_OF_HOST_MEMORY; submit->submit = vn_instance_submission_get_ring_submit(ring, cs, extra_shmem, direct); if (!submit->submit) { - vn_instance_submission_cleanup(submit, cs); + vn_instance_submission_cleanup(submit); return VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -466,8 +447,7 @@ vn_instance_submission_prepare(struct vn_instance_submission *submit, static bool vn_instance_submission_can_direct(const struct vn_cs_encoder *cs) { - struct vn_instance_submission submit; - return vn_cs_encoder_get_len(cs) <= sizeof(submit.local_cs_data); + return vn_cs_encoder_get_len(cs) <= VN_INSTANCE_RING_DIRECT_THRESHOLD; } static struct vn_cs_encoder * @@ -515,8 +495,7 @@ vn_instance_ring_submit_locked(struct vn_instance *instance, return result; uint32_t seqno; - const bool notify = vn_ring_submit(ring, submit.submit, submit.cs_data, - submit.cs_size, &seqno); + const bool notify = vn_ring_submit(ring, submit.submit, submit.cs, &seqno); if (notify) { uint32_t notify_ring_data[8]; struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( @@ -526,7 +505,7 @@ vn_instance_ring_submit_locked(struct vn_instance *instance, vn_cs_encoder_get_len(&local_enc)); } - vn_instance_submission_cleanup(&submit, cs); + vn_instance_submission_cleanup(&submit); if (ring_seqno) *ring_seqno = seqno; diff --git a/src/virtio/vulkan/vn_ring.c b/src/virtio/vulkan/vn_ring.c index 4f1b99db4c5..b6fabc4868d 100644 --- a/src/virtio/vulkan/vn_ring.c +++ b/src/virtio/vulkan/vn_ring.c @@ -5,6 +5,7 @@ #include "vn_ring.h" +#include "vn_cs.h" #include "vn_renderer.h" /* must be power-of-two */ @@ -203,12 +204,18 @@ vn_ring_get_submit(struct vn_ring *ring, uint32_t shmem_count) bool vn_ring_submit(struct vn_ring *ring, struct vn_ring_submit *submit, - const void *cs_data, - uint32_t cs_size, + const struct vn_cs_encoder *cs, uint32_t *seqno) { - const uint32_t cur_seqno = vn_ring_wait_space(ring, cs_size); - vn_ring_write_buffer(ring, cs_data, cs_size); + /* write cs to the ring */ + assert(!vn_cs_encoder_is_empty(cs)); + uint32_t cur_seqno; + for (uint32_t i = 0; i < cs->buffer_count; i++) { + const struct vn_cs_encoder_buffer *buf = &cs->buffers[i]; + cur_seqno = vn_ring_wait_space(ring, buf->committed_size); + vn_ring_write_buffer(ring, buf->base, buf->committed_size); + } + vn_ring_store_tail(ring); const bool notify = vn_ring_load_status(ring) & VN_RING_STATUS_IDLE; diff --git a/src/virtio/vulkan/vn_ring.h b/src/virtio/vulkan/vn_ring.h index 3d3d2afbe6e..3e63efaf16a 100644 --- a/src/virtio/vulkan/vn_ring.h +++ b/src/virtio/vulkan/vn_ring.h @@ -87,8 +87,7 @@ vn_ring_get_submit(struct vn_ring *ring, uint32_t shmem_count); bool vn_ring_submit(struct vn_ring *ring, struct vn_ring_submit *submit, - const void *cs_data, - uint32_t cs_size, + const struct vn_cs_encoder *cs, uint32_t *seqno); void