From 7bec2a0b2397d73583bc678c7531ad82d5b28c90 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 8 Dec 2021 15:55:12 -0800 Subject: [PATCH] venus: add VN_CS_ENCODER_STORAGE_SHMEM_POOL for VkCommandBuffer It suballocates from a shmem pool owned by vn_instance. The goals are to speed up shmem allocations for VkCommandBuffer and to reduce the number of BOs. Both are crucial when shmems are HOST3D BOs, because they require roundtrips to the renderer to allocate and they take up KVM memslots. Signed-off-by: Chia-I Wu Reviewed-by: Ryan Neph Reviewed-by: Yiwei Zhang Part-of: --- src/virtio/vulkan/vn_command_buffer.c | 2 +- src/virtio/vulkan/vn_cs.c | 49 +++++++++++++++++++++++++++++------ src/virtio/vulkan/vn_cs.h | 2 ++ src/virtio/vulkan/vn_instance.c | 8 ++++++ src/virtio/vulkan/vn_instance.h | 21 +++++++++++++++ 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/virtio/vulkan/vn_command_buffer.c b/src/virtio/vulkan/vn_command_buffer.c index 7909795..5f90343 100644 --- a/src/virtio/vulkan/vn_command_buffer.c +++ b/src/virtio/vulkan/vn_command_buffer.c @@ -561,7 +561,7 @@ vn_AllocateCommandBuffers(VkDevice device, cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL; vn_cs_encoder_init(&cmd->cs, dev->instance, - VN_CS_ENCODER_STORAGE_SHMEM_ARRAY, 16 * 1024); + VN_CS_ENCODER_STORAGE_SHMEM_POOL, 16 * 1024); VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd); pCommandBuffers[i] = cmd_handle; diff --git a/src/virtio/vulkan/vn_cs.c b/src/virtio/vulkan/vn_cs.c index 9dc5c71..66e93aa 100644 --- a/src/virtio/vulkan/vn_cs.c +++ b/src/virtio/vulkan/vn_cs.c @@ -70,6 +70,23 @@ vn_cs_encoder_commit_buffer(struct vn_cs_encoder *enc) static void vn_cs_encoder_gc_buffers(struct vn_cs_encoder *enc) { + /* when the shmem pool is used, no need to cache the shmem in cs */ + if (enc->storage_type == VN_CS_ENCODER_STORAGE_SHMEM_POOL) { + for (uint32_t i = 0; i < enc->buffer_count; i++) { + vn_renderer_shmem_unref(enc->instance->renderer, + enc->buffers[i].shmem); + } + + enc->buffer_count = 0; + enc->total_committed_size = 0; + enc->current_buffer_size = 0; + + enc->cur = NULL; + enc->end = NULL; + + return; + } + /* free all but the current buffer */ assert(enc->buffer_count); struct vn_cs_encoder_buffer *cur_buf = @@ -180,22 +197,37 @@ vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size) if (likely(enc->buffer_count)) { vn_cs_encoder_commit_buffer(enc); - /* TODO better strategy to grow buffer size */ - const struct vn_cs_encoder_buffer *cur_buf = - &enc->buffers[enc->buffer_count - 1]; - if (cur_buf->offset) - buf_size = next_buffer_size(0, enc->current_buffer_size, size); + if (enc->storage_type == VN_CS_ENCODER_STORAGE_SHMEM_ARRAY) { + /* if the current buffer is reused from the last vn_cs_encoder_reset + * (i.e., offset != 0), do not double the size + * + * TODO better strategy to grow buffer size + */ + const struct vn_cs_encoder_buffer *cur_buf = + &enc->buffers[enc->buffer_count - 1]; + if (cur_buf->offset) + buf_size = next_buffer_size(0, enc->current_buffer_size, size); + } } if (!buf_size) { + /* double the size */ buf_size = next_buffer_size(enc->current_buffer_size, enc->min_buffer_size, size); if (!buf_size) return false; } - struct vn_renderer_shmem *shmem = - vn_renderer_shmem_create(enc->instance->renderer, buf_size); + struct vn_renderer_shmem *shmem; + size_t buf_offset; + if (enc->storage_type == VN_CS_ENCODER_STORAGE_SHMEM_ARRAY) { + shmem = vn_renderer_shmem_create(enc->instance->renderer, buf_size); + buf_offset = 0; + } else { + assert(enc->storage_type == VN_CS_ENCODER_STORAGE_SHMEM_POOL); + shmem = + vn_instance_cs_shmem_alloc(enc->instance, buf_size, &buf_offset); + } if (!shmem) return false; @@ -206,7 +238,8 @@ vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size) return false; } - vn_cs_encoder_add_buffer(enc, shmem, 0, shmem->mmap_ptr, buf_size); + vn_cs_encoder_add_buffer(enc, shmem, buf_offset, + shmem->mmap_ptr + buf_offset, buf_size); enc->current_buffer_size = buf_size; enc->current_buffer_roundtrip = roundtrip; diff --git a/src/virtio/vulkan/vn_cs.h b/src/virtio/vulkan/vn_cs.h index 3bd8c05..989b0f5 100644 --- a/src/virtio/vulkan/vn_cs.h +++ b/src/virtio/vulkan/vn_cs.h @@ -40,6 +40,8 @@ enum vn_cs_encoder_storage_type { VN_CS_ENCODER_STORAGE_POINTER, /* an array of dynamically allocated shmems */ VN_CS_ENCODER_STORAGE_SHMEM_ARRAY, + /* same as above, but shmems are suballocated from a pool */ + VN_CS_ENCODER_STORAGE_SHMEM_POOL, }; struct vn_cs_encoder_buffer { diff --git a/src/virtio/vulkan/vn_instance.c b/src/virtio/vulkan/vn_instance.c index 96ce612..bf27631 100644 --- a/src/virtio/vulkan/vn_instance.c +++ b/src/virtio/vulkan/vn_instance.c @@ -711,6 +711,7 @@ vn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, } mtx_init(&instance->physical_device.mutex, mtx_plain); + mtx_init(&instance->cs_shmem.mutex, mtx_plain); if (!vn_icd_supports_api_version( instance->base.base.app_info.api_version)) { @@ -742,6 +743,9 @@ vn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, if (result != VK_SUCCESS) goto fail; + vn_renderer_shmem_pool_init(instance->renderer, &instance->cs_shmem.pool, + 8u << 20); + VkInstanceCreateInfo local_create_info = *pCreateInfo; local_create_info.ppEnabledExtensionNames = NULL; local_create_info.enabledExtensionCount = 0; @@ -804,6 +808,7 @@ fail: vn_renderer_destroy(instance->renderer, alloc); mtx_destroy(&instance->physical_device.mutex); + mtx_destroy(&instance->cs_shmem.mutex); vn_instance_base_fini(&instance->base); vk_free(alloc, instance); @@ -832,6 +837,9 @@ vn_DestroyInstance(VkInstance _instance, vn_call_vkDestroyInstance(instance, _instance, NULL); + vn_renderer_shmem_pool_fini(instance->renderer, &instance->cs_shmem.pool); + mtx_destroy(&instance->cs_shmem.mutex); + uint32_t destroy_ring_data[4]; struct vn_cs_encoder local_enc = VN_CS_ENCODER_INITIALIZER_LOCAL( destroy_ring_data, sizeof(destroy_ring_data)); diff --git a/src/virtio/vulkan/vn_instance.h b/src/virtio/vulkan/vn_instance.h index 8005549..a0cbc98 100644 --- a/src/virtio/vulkan/vn_instance.h +++ b/src/virtio/vulkan/vn_instance.h @@ -70,6 +70,12 @@ struct vn_instance { uint32_t renderer_api_version; uint32_t renderer_version; + /* for VN_CS_ENCODER_STORAGE_SHMEM_POOL */ + struct { + mtx_t mutex; + struct vn_renderer_shmem_pool pool; + } cs_shmem; + struct { mtx_t mutex; bool initialized; @@ -152,4 +158,19 @@ vn_instance_free_command_reply(struct vn_instance *instance, vn_renderer_shmem_unref(instance->renderer, submit->reply_shmem); } +static inline struct vn_renderer_shmem * +vn_instance_cs_shmem_alloc(struct vn_instance *instance, + size_t size, + size_t *out_offset) +{ + struct vn_renderer_shmem *shmem; + + mtx_lock(&instance->cs_shmem.mutex); + shmem = vn_renderer_shmem_pool_alloc( + instance->renderer, &instance->cs_shmem.pool, size, out_offset); + mtx_unlock(&instance->cs_shmem.mutex); + + return shmem; +} + #endif /* VN_INSTANCE_H */ -- 2.7.4