From e6f01563ab744f032b45fbaa335291bed72dbf12 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 30 May 2022 18:34:31 +0200 Subject: [PATCH] vulkan: support multiple streams of buffers --- spa/plugins/vulkan/vulkan-compute-filter.c | 52 +++-- spa/plugins/vulkan/vulkan-compute-source.c | 20 +- spa/plugins/vulkan/vulkan-utils.c | 243 +++++++++++++-------- spa/plugins/vulkan/vulkan-utils.h | 36 ++- 4 files changed, 214 insertions(+), 137 deletions(-) diff --git a/spa/plugins/vulkan/vulkan-compute-filter.c b/spa/plugins/vulkan/vulkan-compute-filter.c index 4b41ed2aa..84f9d3a5e 100644 --- a/spa/plugins/vulkan/vulkan-compute-filter.c +++ b/spa/plugins/vulkan/vulkan-compute-filter.c @@ -47,8 +47,6 @@ #define NAME "vulkan-compute-filter" -#define MAX_PORTS 1 - struct buffer { uint32_t id; #define BUFFER_FLAG_OUT (1<<0) @@ -75,6 +73,7 @@ struct port { struct spa_list empty; struct spa_list ready; + uint32_t stream_id; }; struct impl { @@ -103,7 +102,7 @@ struct impl { struct port port[2]; }; -#define CHECK_PORT(this,d,p) ((p) < MAX_PORTS) +#define CHECK_PORT(this,d,p) ((p) < 1) static int impl_node_enum_params(void *object, int seq, uint32_t id, uint32_t start, uint32_t num, @@ -416,7 +415,7 @@ static int clear_buffers(struct impl *this, struct port *port) { if (port->n_buffers > 0) { spa_log_debug(this->log, NAME " %p: clear buffers", this); - spa_vulkan_use_buffers(&this->state, 0, 0, NULL); + spa_vulkan_use_buffers(&this->state, &this->state.streams[port->stream_id], 0, 0, NULL); port->n_buffers = 0; spa_list_init(&port->empty); spa_list_init(&port->ready); @@ -528,7 +527,7 @@ impl_node_port_use_buffers(void *object, spa_list_append(&port->empty, &b->link); } - spa_vulkan_use_buffers(&this->state, flags, n_buffers, buffers); + spa_vulkan_use_buffers(&this->state, &this->state.streams[port->stream_id], flags, n_buffers, buffers); port->n_buffers = n_buffers; return 0; @@ -693,24 +692,8 @@ impl_init(const struct spa_handle_factory *factory, this->info.params = this->params; this->info.n_params = 2; - port = &this->port[SPA_DIRECTION_OUTPUT]; - port->direction = SPA_DIRECTION_OUTPUT; - port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | - SPA_PORT_CHANGE_MASK_PARAMS | - SPA_PORT_CHANGE_MASK_PROPS; - port->info = SPA_PORT_INFO_INIT(); - port->info.flags = SPA_PORT_FLAG_NO_REF | SPA_PORT_FLAG_CAN_ALLOC_BUFFERS; - port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); - port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); - port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); - port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); - port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); - port->info.params = port->params; - port->info.n_params = 5; - spa_list_init(&port->empty); - spa_list_init(&port->ready); - - port = &this->port[SPA_DIRECTION_INPUT]; + port = &this->port[0]; + port->stream_id = 0; port->direction = SPA_DIRECTION_INPUT; port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PARAMS | @@ -727,7 +710,30 @@ impl_init(const struct spa_handle_factory *factory, spa_list_init(&port->empty); spa_list_init(&port->ready); + port = &this->port[1]; + port->stream_id = 1; + port->direction = SPA_DIRECTION_OUTPUT; + port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | + SPA_PORT_CHANGE_MASK_PARAMS | + SPA_PORT_CHANGE_MASK_PROPS; + port->info = SPA_PORT_INFO_INIT(); + port->info.flags = SPA_PORT_FLAG_NO_REF | SPA_PORT_FLAG_CAN_ALLOC_BUFFERS; + port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ); + port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ); + port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ); + port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); + port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); + port->info.params = port->params; + port->info.n_params = 5; + spa_list_init(&port->empty); + spa_list_init(&port->ready); + this->state.log = this->log; + spa_vulkan_init_stream(&this->state, &this->state.streams[0], + SPA_DIRECTION_INPUT, NULL); + spa_vulkan_init_stream(&this->state, &this->state.streams[1], + SPA_DIRECTION_OUTPUT, NULL); + this->state.n_streams = 2; return 0; } diff --git a/spa/plugins/vulkan/vulkan-compute-source.c b/spa/plugins/vulkan/vulkan-compute-source.c index 2606a32c4..5682da45f 100644 --- a/spa/plugins/vulkan/vulkan-compute-source.c +++ b/spa/plugins/vulkan/vulkan-compute-source.c @@ -61,8 +61,6 @@ static void reset_props(struct props *props) props->live = DEFAULT_LIVE; } -#define MAX_PORTS 1 - struct buffer { uint32_t id; #define BUFFER_FLAG_OUT (1<<0) @@ -122,7 +120,7 @@ struct impl { struct port port; }; -#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS) +#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < 1) static int impl_node_enum_params(void *object, int seq, uint32_t id, uint32_t start, uint32_t num, @@ -308,12 +306,13 @@ static int make_buffer(struct impl *this) this->state.constants.time = this->elapsed_time / (float) SPA_NSEC_PER_SEC; this->state.constants.frame = this->frame_count; - spa_vulkan_process(&this->state, b->id); + this->state.streams[0].pending_buffer_id = b->id; + spa_vulkan_process(&this->state); - if (this->state.ready_buffer_id != SPA_ID_INVALID) { - struct buffer *b = &port->buffers[this->state.ready_buffer_id]; + if (this->state.streams[0].ready_buffer_id != SPA_ID_INVALID) { + struct buffer *b = &port->buffers[this->state.streams[0].ready_buffer_id]; - this->state.ready_buffer_id = SPA_ID_INVALID; + this->state.streams[0].ready_buffer_id = SPA_ID_INVALID; spa_log_trace(this->log, NAME " %p: ready buffer %d", this, b->id); @@ -636,7 +635,7 @@ static int clear_buffers(struct impl *this, struct port *port) { if (port->n_buffers > 0) { spa_log_debug(this->log, NAME " %p: clear buffers", this); - spa_vulkan_use_buffers(&this->state, 0, 0, NULL); + spa_vulkan_use_buffers(&this->state, &this->state.streams[0], 0, 0, NULL); port->n_buffers = 0; spa_list_init(&port->empty); spa_list_init(&port->ready); @@ -749,7 +748,7 @@ impl_node_port_use_buffers(void *object, spa_list_append(&port->empty, &b->link); } - spa_vulkan_use_buffers(&this->state, flags, n_buffers, buffers); + spa_vulkan_use_buffers(&this->state, &this->state.streams[0], flags, n_buffers, buffers); port->n_buffers = n_buffers; return 0; @@ -958,6 +957,9 @@ impl_init(const struct spa_handle_factory *factory, spa_list_init(&port->ready); this->state.log = this->log; + spa_vulkan_init_stream(&this->state, &this->state.streams[0], + SPA_DIRECTION_OUTPUT, NULL); + this->state.n_streams = 1; return 0; } diff --git a/spa/plugins/vulkan/vulkan-utils.c b/spa/plugins/vulkan/vulkan-utils.c index 3552af080..d6c87a82f 100644 --- a/spa/plugins/vulkan/vulkan-utils.c +++ b/spa/plugins/vulkan/vulkan-utils.c @@ -217,31 +217,36 @@ static uint32_t findMemoryType(struct vulkan_state *s, static int createDescriptors(struct vulkan_state *s) { - static const VkDescriptorPoolSize descriptorPoolSize = { + uint32_t i; + + VkDescriptorPoolSize descriptorPoolSize = { .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .descriptorCount = 1 + .descriptorCount = s->n_streams, }; - static const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { + const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .maxSets = 1, .poolSizeCount = 1, .pPoolSizes = &descriptorPoolSize, }; + VkDescriptorSetLayoutBinding descriptorSetLayoutBinding[s->n_streams]; VK_CHECK_RESULT(vkCreateDescriptorPool(s->device, &descriptorPoolCreateInfo, NULL, &s->descriptorPool)); - static const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT + for (i = 0; i < s->n_streams; i++) { + descriptorSetLayoutBinding[i] = (VkDescriptorSetLayoutBinding) { + .binding = i, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT + }; }; - static const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = { + const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = 1, - .pBindings = &descriptorSetLayoutBinding + .bindingCount = s->n_streams, + .pBindings = descriptorSetLayoutBinding }; VK_CHECK_RESULT(vkCreateDescriptorSetLayout(s->device, &descriptorSetLayoutCreateInfo, NULL, @@ -256,63 +261,42 @@ static int createDescriptors(struct vulkan_state *s) VK_CHECK_RESULT(vkAllocateDescriptorSets(s->device, &descriptorSetAllocateInfo, - &s->descriptorSet)); + s->descriptorSet)); return 0; } -static int createBuffer(struct vulkan_state *s, uint32_t id) +static int updateDescriptors(struct vulkan_state *s) { - const VkBufferCreateInfo bufferCreateInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = s->bufferSize, - .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - VkMemoryRequirements memoryRequirements; + uint32_t i; + VkDescriptorBufferInfo descriptorBufferInfo[s->n_streams]; + VkWriteDescriptorSet writeDescriptorSet[s->n_streams]; - VK_CHECK_RESULT(vkCreateBuffer(s->device, - &bufferCreateInfo, NULL, &s->buffers[id].buffer)); + for (i = 0; i < s->n_streams; i++) { + struct vulkan_stream *p = &s->streams[i]; - vkGetBufferMemoryRequirements(s->device, - s->buffers[id].buffer, &memoryRequirements); + if (p->current_buffer_id == p->pending_buffer_id || + p->pending_buffer_id == SPA_ID_INVALID) + continue; - const VkMemoryAllocateInfo allocateInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = memoryRequirements.size, - .memoryTypeIndex = findMemoryType(s, - memoryRequirements.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), - }; + p->current_buffer_id = p->pending_buffer_id; + p->busy_buffer_id = p->current_buffer_id; + p->pending_buffer_id = SPA_ID_INVALID; - VK_CHECK_RESULT(vkAllocateMemory(s->device, - &allocateInfo, NULL, &s->buffers[id].memory)); - VK_CHECK_RESULT(vkBindBufferMemory(s->device, - s->buffers[id].buffer, s->buffers[id].memory, 0)); - - return 0; -} - -static int updateDescriptors(struct vulkan_state *s, uint32_t buffer_id) -{ - if (s->current_buffer_id == buffer_id) - return 0; - - const VkDescriptorBufferInfo descriptorBufferInfo = { - .buffer = s->buffers[buffer_id].buffer, - .offset = 0, - .range = s->bufferSize, - }; - const VkWriteDescriptorSet writeDescriptorSet = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = s->descriptorSet, - .dstBinding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .pBufferInfo = &descriptorBufferInfo, - }; - vkUpdateDescriptorSets(s->device, 1, &writeDescriptorSet, 0, NULL); - s->current_buffer_id = buffer_id; + descriptorBufferInfo[i] = (VkDescriptorBufferInfo) { + .buffer = p->buffers[p->current_buffer_id].buffer, + .offset = 0, + .range = p->bufferSize, + }; + writeDescriptorSet[i] = (VkWriteDescriptorSet) { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = s->descriptorSet[i], + .dstBinding = i, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = &descriptorBufferInfo[i], + }; + } + vkUpdateDescriptorSets(s->device, s->n_streams, writeDescriptorSet, 0, NULL); return 0; } @@ -432,7 +416,7 @@ static int runCommandBuffer(struct vulkan_state *s) s->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(struct push_constants), (const void *) &s->constants); vkCmdBindDescriptorSets(s->commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, - s->pipelineLayout, 0, 1, &s->descriptorSet, 0, NULL); + s->pipelineLayout, 0, s->n_streams, s->descriptorSet, 0, NULL); vkCmdDispatch(s->commandBuffer, (uint32_t)ceil(s->constants.width / (float)WORKGROUP_SIZE), @@ -448,58 +432,117 @@ static int runCommandBuffer(struct vulkan_state *s) .pCommandBuffers = &s->commandBuffer, }; VK_CHECK_RESULT(vkQueueSubmit(s->queue, 1, &submitInfo, s->fence)); - s->busy_buffer_id = s->current_buffer_id; + s->started = true; return 0; } -static void clear_buffers(struct vulkan_state *s) +static void clear_buffers(struct vulkan_state *s, struct vulkan_stream *p) { uint32_t i; - for (i = 0; i < s->n_buffers; i++) { - close(s->buffers[i].buf->datas[0].fd); - vkFreeMemory(s->device, s->buffers[i].memory, NULL); - vkDestroyBuffer(s->device, s->buffers[i].buffer, NULL); + for (i = 0; i < p->n_buffers; i++) { + if (p->buffers[i].fd != -1) + close(p->buffers[i].fd); + vkFreeMemory(s->device, p->buffers[i].memory, NULL); + vkDestroyBuffer(s->device, p->buffers[i].buffer, NULL); } - s->n_buffers = 0; + p->n_buffers = 0; } -int spa_vulkan_use_buffers(struct vulkan_state *s, uint32_t flags, +static void clear_streams(struct vulkan_state *s) +{ + uint32_t i; + for (i = 0; i < s->n_streams; i++) { + struct vulkan_stream *p = &s->streams[i]; + clear_buffers(s, p); + } +} + +int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *p, uint32_t flags, uint32_t n_buffers, struct spa_buffer **buffers) { uint32_t i; VULKAN_INSTANCE_FUNCTION(vkGetMemoryFdKHR); - clear_buffers(s); + clear_buffers(s, p); - s->bufferSize = s->constants.width * s->constants.height * sizeof(struct pixel); + p->bufferSize = s->constants.width * s->constants.height * sizeof(struct pixel); for (i = 0; i < n_buffers; i++) { - createBuffer(s, i); - - const VkMemoryGetFdInfoKHR getFdInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, - .memory = s->buffers[i].memory, - .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT + const VkBufferCreateInfo bufferCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = p->bufferSize, + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }; - int fd; + VK_CHECK_RESULT(vkCreateBuffer(s->device, + &bufferCreateInfo, NULL, &p->buffers[i].buffer)); - s->buffers[i].buf = buffers[i]; + VkMemoryRequirements memoryRequirements; + vkGetBufferMemoryRequirements(s->device, + p->buffers[i].buffer, &memoryRequirements); - VK_CHECK_RESULT(vkGetMemoryFdKHR(s->device, &getFdInfo, &fd)); + VkMemoryAllocateInfo allocateInfo = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memoryRequirements.size, + .memoryTypeIndex = findMemoryType(s, + memoryRequirements.memoryTypeBits, + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), + }; - buffers[i]->datas[0].type = SPA_DATA_DmaBuf; - buffers[i]->datas[0].flags = SPA_DATA_FLAG_READABLE; - buffers[i]->datas[0].fd = fd; - buffers[i]->datas[0].mapoffset = 0; - buffers[i]->datas[0].maxsize = s->bufferSize; + if (flags & SPA_NODE_BUFFERS_FLAG_ALLOC) { + VK_CHECK_RESULT(vkAllocateMemory(s->device, + &allocateInfo, NULL, &p->buffers[i].memory)); + + const VkMemoryGetFdInfoKHR getFdInfo = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, + .memory = p->buffers[i].memory, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT + }; + int fd; + + VK_CHECK_RESULT(vkGetMemoryFdKHR(s->device, &getFdInfo, &fd)); + +// buffers[i]->datas[0].type = SPA_DATA_DmaBuf; + buffers[i]->datas[0].type = SPA_DATA_MemFd; + buffers[i]->datas[0].fd = fd; + buffers[i]->datas[0].flags = SPA_DATA_FLAG_READABLE; + buffers[i]->datas[0].mapoffset = 0; + buffers[i]->datas[0].maxsize = p->bufferSize; + p->buffers[i].fd = fd; + } else { + VkImportMemoryFdInfoKHR importInfo = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + .fd = fcntl(buffers[i]->datas[0].fd, F_DUPFD_CLOEXEC, 0), + }; + allocateInfo.pNext = &importInfo; + p->buffers[i].fd = -1; + + VK_CHECK_RESULT(vkAllocateMemory(s->device, + &allocateInfo, NULL, &p->buffers[i].memory)); + } + VK_CHECK_RESULT(vkBindBufferMemory(s->device, + p->buffers[i].buffer, p->buffers[i].memory, 0)); } - s->n_buffers = n_buffers; + p->n_buffers = n_buffers; return 0; } +int spa_vulkan_init_stream(struct vulkan_state *s, struct vulkan_stream *stream, + enum spa_direction direction, struct spa_dict *props) +{ + spa_zero(*stream); + stream->direction = direction; + stream->current_buffer_id = SPA_ID_INVALID; + stream->busy_buffer_id = SPA_ID_INVALID; + stream->ready_buffer_id = SPA_ID_INVALID; + return 0; +} + int spa_vulkan_prepare(struct vulkan_state *s) { if (!s->prepared) { @@ -532,23 +575,31 @@ int spa_vulkan_unprepare(struct vulkan_state *s) int spa_vulkan_start(struct vulkan_state *s) { - s->current_buffer_id = SPA_ID_INVALID; - s->busy_buffer_id = SPA_ID_INVALID; - s->ready_buffer_id = SPA_ID_INVALID; + uint32_t i; + + for (i = 0; i < s->n_streams; i++) { + struct vulkan_stream *p = &s->streams[i]; + p->current_buffer_id = SPA_ID_INVALID; + p->busy_buffer_id = SPA_ID_INVALID; + p->ready_buffer_id = SPA_ID_INVALID; + } return 0; } int spa_vulkan_stop(struct vulkan_state *s) { VK_CHECK_RESULT(vkDeviceWaitIdle(s->device)); + clear_streams(s); + s->started = false; return 0; } int spa_vulkan_ready(struct vulkan_state *s) { + uint32_t i; VkResult result; - if (s->busy_buffer_id == SPA_ID_INVALID) + if (!s->started) return 0; result = vkGetFenceStatus(s->device, s->fence); @@ -556,15 +607,19 @@ int spa_vulkan_ready(struct vulkan_state *s) return -EBUSY; VK_CHECK_RESULT(result); - s->ready_buffer_id = s->busy_buffer_id; - s->busy_buffer_id = SPA_ID_INVALID; + s->started = false; + for (i = 0; i < s->n_streams; i++) { + struct vulkan_stream *p = &s->streams[i]; + p->ready_buffer_id = p->busy_buffer_id; + p->busy_buffer_id = SPA_ID_INVALID; + } return 0; } -int spa_vulkan_process(struct vulkan_state *s, uint32_t buffer_id) +int spa_vulkan_process(struct vulkan_state *s) { - updateDescriptors(s, buffer_id); + updateDescriptors(s); runCommandBuffer(s); return 0; diff --git a/spa/plugins/vulkan/vulkan-utils.h b/spa/plugins/vulkan/vulkan-utils.h index 7ffe58197..0adfa5601 100644 --- a/spa/plugins/vulkan/vulkan-utils.h +++ b/spa/plugins/vulkan/vulkan-utils.h @@ -1,7 +1,9 @@ #include #include +#include +#define MAX_STREAMS 2 #define MAX_BUFFERS 16 #define WORKGROUP_SIZE 32 @@ -17,11 +19,24 @@ struct push_constants { }; struct vulkan_buffer { - struct spa_buffer *buf; + int fd; VkBuffer buffer; VkDeviceMemory memory; }; +struct vulkan_stream { + enum spa_direction direction; + + uint32_t pending_buffer_id; + uint32_t current_buffer_id; + uint32_t busy_buffer_id; + uint32_t ready_buffer_id; + + uint32_t bufferSize; + struct vulkan_buffer buffers[MAX_BUFFERS]; + uint32_t n_buffers; +}; + struct vulkan_state { struct spa_log *log; @@ -43,27 +58,26 @@ struct vulkan_state { uint32_t queueFamilyIndex; VkFence fence; unsigned int prepared:1; - uint32_t busy_buffer_id; - uint32_t ready_buffer_id; + unsigned int started:1; VkDescriptorPool descriptorPool; - VkDescriptorSet descriptorSet; VkDescriptorSetLayout descriptorSetLayout; - uint32_t current_buffer_id; - - uint32_t bufferSize; - struct vulkan_buffer buffers[MAX_BUFFERS]; - uint32_t n_buffers; + uint32_t n_streams; + VkDescriptorSet descriptorSet[MAX_STREAMS]; + struct vulkan_stream streams[MAX_STREAMS]; }; +int spa_vulkan_init_stream(struct vulkan_state *s, struct vulkan_stream *stream, enum spa_direction, + struct spa_dict *props); + int spa_vulkan_prepare(struct vulkan_state *s); -int spa_vulkan_use_buffers(struct vulkan_state *s, uint32_t flags, +int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *stream, uint32_t flags, uint32_t n_buffers, struct spa_buffer **buffers); int spa_vulkan_unprepare(struct vulkan_state *s); int spa_vulkan_start(struct vulkan_state *s); int spa_vulkan_stop(struct vulkan_state *s); int spa_vulkan_ready(struct vulkan_state *s); -int spa_vulkan_process(struct vulkan_state *s, uint32_t buffer_id); +int spa_vulkan_process(struct vulkan_state *s); int spa_vulkan_cleanup(struct vulkan_state *s);