mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
vulkan: support multiple streams of buffers
This commit is contained in:
parent
332e8b7029
commit
e6f01563ab
4 changed files with 214 additions and 137 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <spa/buffer/buffer.h>
|
||||
#include <spa/node/node.h>
|
||||
|
||||
#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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue