diff --git a/src/virtio/vulkan/vn_command_buffer.c b/src/virtio/vulkan/vn_command_buffer.c index 7909795384d..5f90343e831 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 9dc5c71c50c..66e93aa74a1 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 3bd8c05f978..989b0f5d433 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 96ce612c2eb..bf27631cdde 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 800554961b9..a0cbc98d608 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 */