vulkan: Complete vulkan_pass

vulkan_pass now contains everything required for a single blit pass.
This commit is contained in:
columbarius 2024-04-08 02:51:13 +02:00 committed by Wim Taymans
parent 11ff1471e9
commit c223e02d9b
4 changed files with 76 additions and 50 deletions

View file

@ -479,6 +479,7 @@ static int clear_buffers(struct impl *this, struct port *port)
spa_log_debug(this->log, "%p: clear buffers", this);
lock_renderer(this);
spa_vulkan_blit_use_buffers(&this->state, &this->state.streams[port->stream_id], 0, &port->current_format, 0, NULL);
spa_vulkan_blit_clear_pass(&this->state, &this->pass);
unlock_renderer(this);
port->n_buffers = 0;
spa_list_init(&port->empty);
@ -649,6 +650,8 @@ impl_node_port_use_buffers(void *object,
}
spa_vulkan_blit_use_buffers(&this->state, &this->state.streams[port->stream_id], flags, &port->current_format, n_buffers, buffers);
port->n_buffers = n_buffers;
if (n_buffers > 0)
spa_vulkan_blit_init_pass(&this->state, &this->pass);
unlock_renderer(this);
return 0;
@ -737,8 +740,6 @@ static int impl_node_process(void *object)
return -EBUSY;
}
spa_vulkan_blit_init_pass(&this->state, &this->pass);
b = &inport->buffers[inio->buffer_id];
this->pass.in_stream_id = SPA_DIRECTION_INPUT;
this->pass.in_buffer_id = b->id;
@ -753,8 +754,7 @@ static int impl_node_process(void *object)
spa_log_debug(this->log, "filter into %d", b->id);
spa_vulkan_blit_process(&this->state, &this->pass);
spa_vulkan_blit_clear_pass(&this->state, &this->pass);
spa_vulkan_blit_reset_pass(&this->state, &this->pass);
b->outbuf->datas[0].chunk->offset = 0;
b->outbuf->datas[0].chunk->size = b->outbuf->datas[0].maxsize;

View file

@ -524,6 +524,7 @@ static int clear_buffers(struct impl *this, struct port *port)
spa_log_debug(this->log, "%p: clear buffers", this);
lock_renderer(this);
spa_vulkan_blit_use_buffers(&this->state, &this->state.streams[port->stream_id], 0, &port->current_format, 0, NULL);
spa_vulkan_blit_clear_pass(&this->state, &this->pass);
unlock_renderer(this);
port->n_buffers = 0;
spa_list_init(&port->empty);
@ -746,6 +747,8 @@ impl_node_port_use_buffers(void *object,
}
spa_vulkan_blit_use_buffers(&this->state, &this->state.streams[port->stream_id], flags, &port->current_format, n_buffers, buffers);
port->n_buffers = n_buffers;
if (n_buffers > 0)
spa_vulkan_blit_init_pass(&this->state, &this->pass);
unlock_renderer(this);
return 0;
@ -834,8 +837,6 @@ static int impl_node_process(void *object)
return -EBUSY;
}
spa_vulkan_blit_init_pass(&this->state, &this->pass);
b = &inport->buffers[inio->buffer_id];
this->pass.in_stream_id = SPA_DIRECTION_INPUT;
this->pass.in_buffer_id = b->id;
@ -850,7 +851,7 @@ static int impl_node_process(void *object)
spa_log_debug(this->log, "filter into %d", b->id);
spa_vulkan_blit_process(&this->state, &this->pass);
spa_vulkan_blit_clear_pass(&this->state, &this->pass);
spa_vulkan_blit_reset_pass(&this->state, &this->pass);
b->outbuf->datas[0].chunk->offset = 0;
b->outbuf->datas[0].chunk->size = b->outbuf->datas[0].maxsize;

View file

@ -50,7 +50,7 @@ static int runImportSHMBuffers(struct vulkan_blit_state *s, struct vulkan_pass *
.size.height = p->dim.height,
.copies = &pass->in_copy,
};
CHECK(vulkan_write_pixels(&s->base, &writeInfo, &s->staging_buffer));
CHECK(vulkan_write_pixels(&s->base, &writeInfo, &pass->in_staging_buffer));
}
return 0;
@ -122,7 +122,7 @@ static int runCommandBuffer(struct vulkan_blit_state *s, struct vulkan_pass *pas
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
};
VK_CHECK_RESULT(vkBeginCommandBuffer(s->commandBuffer, &beginInfo));
VK_CHECK_RESULT(vkBeginCommandBuffer(pass->commandBuffer, &beginInfo));
uint32_t i;
struct vulkan_stream *stream_input = &s->streams[pass->in_stream_id];
@ -132,7 +132,7 @@ static int runCommandBuffer(struct vulkan_blit_state *s, struct vulkan_pass *pas
VkImage dst_image = stream_output->buffers[pass->out_buffer_id].image;
if (stream_input->buffer_type == SPA_DATA_MemPtr) {
vkCmdCopyBufferToImage(s->commandBuffer, s->staging_buffer.buffer, src_image,
vkCmdCopyBufferToImage(pass->commandBuffer, pass->in_staging_buffer.buffer, src_image,
VK_IMAGE_LAYOUT_GENERAL, 1, &pass->in_copy);
VkImageMemoryBarrier copy_barrier = {
@ -149,7 +149,7 @@ static int runCommandBuffer(struct vulkan_blit_state *s, struct vulkan_pass *pas
.subresourceRange.layerCount = 1,
};
vkCmdPipelineBarrier(s->commandBuffer,
vkCmdPipelineBarrier(pass->commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0, 0, NULL, 0, NULL,
@ -180,7 +180,7 @@ static int runCommandBuffer(struct vulkan_blit_state *s, struct vulkan_pass *pas
spa_log_trace_fp(s->log, "Blitting from (%p, %d, %d) %d,%dx%d,%d to (%p, %d, %d) %d,%dx%d,%d",
stream_input, pass->in_buffer_id, stream_input->direction, 0, 0, stream_input->dim.width, stream_input->dim.height,
stream_output, pass->out_buffer_id, stream_output->direction, 0, 0, stream_output->dim.width, stream_output->dim.height);
vkCmdBlitImage(s->commandBuffer, src_image, VK_IMAGE_LAYOUT_GENERAL,
vkCmdBlitImage(pass->commandBuffer, src_image, VK_IMAGE_LAYOUT_GENERAL,
dst_image, VK_IMAGE_LAYOUT_GENERAL,
1, &imageBlitRegion, VK_FILTER_NEAREST);
@ -244,42 +244,30 @@ static int runCommandBuffer(struct vulkan_blit_state *s, struct vulkan_pass *pas
}
}
vkCmdPipelineBarrier(s->commandBuffer,
vkCmdPipelineBarrier(pass->commandBuffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_2_TRANSFER_BIT,
0, 0, NULL, 0, NULL,
s->n_streams, acquire_barrier);
vkCmdPipelineBarrier(s->commandBuffer,
vkCmdPipelineBarrier(pass->commandBuffer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0, 0, NULL, 0, NULL,
s->n_streams, release_barrier);
VK_CHECK_RESULT(vkEndCommandBuffer(s->commandBuffer));
VK_CHECK_RESULT(vkEndCommandBuffer(pass->commandBuffer));
VK_CHECK_RESULT(vkResetFences(s->base.device, 1, &s->fence));
if (s->pipelineSemaphore == VK_NULL_HANDLE) {
VkExportSemaphoreCreateInfo export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
};
VkSemaphoreCreateInfo semaphore_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = &export_info,
};
VK_CHECK_RESULT(vkCreateSemaphore(s->base.device, &semaphore_info, NULL, &s->pipelineSemaphore));
}
VK_CHECK_RESULT(vkResetFences(s->base.device, 1, &pass->fence));
semaphore_signal_info[semaphore_signal_info_len++] = (VkSemaphoreSubmitInfo) {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
.semaphore = s->pipelineSemaphore,
.semaphore = pass->pipelineSemaphore,
};
VkCommandBufferSubmitInfoKHR commandBufferInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.commandBuffer = s->commandBuffer,
.commandBuffer = pass->commandBuffer,
};
const VkSubmitInfo2KHR submitInfo = {
@ -291,12 +279,12 @@ static int runCommandBuffer(struct vulkan_blit_state *s, struct vulkan_pass *pas
.signalSemaphoreInfoCount = semaphore_signal_info_len,
.pSignalSemaphoreInfos = semaphore_signal_info,
};
VK_CHECK_RESULT(vkQueueSubmit2KHR(s->base.queue, 1, &submitInfo, s->fence));
VK_CHECK_RESULT(vkQueueSubmit2KHR(s->base.queue, 1, &submitInfo, pass->fence));
s->started = true;
VkSemaphoreGetFdInfoKHR get_fence_fd_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
.semaphore = s->pipelineSemaphore,
.semaphore = pass->pipelineSemaphore,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
};
VK_CHECK_RESULT(vkGetSemaphoreFdKHR(s->base.device, &get_fence_fd_info, &pass->sync_fd));
@ -314,10 +302,7 @@ static void clear_buffers(struct vulkan_blit_state *s, struct vulkan_stream *p)
}
p->n_buffers = 0;
p->buffer_type = SPA_DATA_Invalid;
if (p->direction == SPA_DIRECTION_INPUT) {
vulkan_staging_buffer_destroy(&s->base, &s->staging_buffer);
s->staging_buffer.buffer = VK_NULL_HANDLE;
}
p->maxsize = 0;
}
static void clear_streams(struct vulkan_blit_state *s)
@ -406,6 +391,7 @@ int spa_vulkan_blit_use_buffers(struct vulkan_blit_state *s, struct vulkan_strea
return -1;
}
}
p->maxsize = SPA_MAX(p->maxsize, buffers[i]->datas[0].maxsize);
externalBufferInfo.usage = p->direction == SPA_DIRECTION_OUTPUT
? VK_IMAGE_USAGE_TRANSFER_DST_BIT
: VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
@ -442,13 +428,6 @@ int spa_vulkan_blit_use_buffers(struct vulkan_blit_state *s, struct vulkan_strea
p->spa_buffers[i] = buffers[i];
p->n_buffers++;
}
if (p->direction == SPA_DIRECTION_INPUT && p->buffer_type == SPA_DATA_MemPtr) {
ret = vulkan_staging_buffer_create(&s->base, buffers[0]->datas[0].maxsize, &s->staging_buffer);
if (ret < 0) {
spa_log_error(s->log, "Failed to create staging buffer");
return ret;
}
}
return 0;
}
@ -504,6 +483,7 @@ static int vulkan_stream_init(struct vulkan_stream *stream, enum spa_direction d
{
spa_zero(*stream);
stream->direction = direction;
stream->maxsize = 0;
return 0;
}
@ -516,6 +496,42 @@ int spa_vulkan_blit_init_pass(struct vulkan_blit_state *s, struct vulkan_pass *p
pass->sync_fd = -1;
CHECK(vulkan_fence_create(&s->base, &pass->fence));
CHECK(vulkan_commandBuffer_create(&s->base, s->commandPool, &pass->commandBuffer));
VkExportSemaphoreCreateInfo export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
};
VkSemaphoreCreateInfo semaphore_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = &export_info,
};
VK_CHECK_RESULT(vkCreateSemaphore(s->base.device, &semaphore_info, NULL, &pass->pipelineSemaphore));
for (uint32_t i = 0; i < s->n_streams; i++) {
struct vulkan_stream *p = &s->streams[i];
if (p->direction == SPA_DIRECTION_OUTPUT || p->buffer_type != SPA_DATA_MemPtr)
continue;
vulkan_staging_buffer_create(&s->base, p->maxsize, &pass->in_staging_buffer);
}
return 0;
}
int spa_vulkan_blit_reset_pass(struct vulkan_blit_state *s, struct vulkan_pass *pass)
{
pass->in_buffer_id = SPA_ID_INVALID;
pass->in_stream_id = SPA_ID_INVALID;
pass->out_buffer_id = SPA_ID_INVALID;
pass->out_stream_id = SPA_ID_INVALID;
if (pass->sync_fd != -1) {
close(pass->sync_fd);
pass->sync_fd = -1;
}
return 0;
}
@ -531,6 +547,15 @@ int spa_vulkan_blit_clear_pass(struct vulkan_blit_state *s, struct vulkan_pass *
pass->sync_fd = -1;
}
vkDestroyFence(s->base.device, pass->fence, NULL);
pass->fence = VK_NULL_HANDLE;
vkFreeCommandBuffers(s->base.device, s->commandPool, 1, &pass->commandBuffer);
pass->commandBuffer = VK_NULL_HANDLE;
vkDestroySemaphore(s->base.device, pass->pipelineSemaphore, NULL);
pass->pipelineSemaphore = VK_NULL_HANDLE;
vulkan_staging_buffer_destroy(&s->base, &pass->in_staging_buffer);
pass->in_staging_buffer.buffer = VK_NULL_HANDLE;
return 0;
}
@ -543,9 +568,7 @@ int spa_vulkan_blit_init_stream(struct vulkan_blit_state *s, struct vulkan_strea
int spa_vulkan_blit_prepare(struct vulkan_blit_state *s)
{
if (!s->prepared) {
CHECK(vulkan_fence_create(&s->base, &s->fence));
CHECK(vulkan_commandPool_create(&s->base, &s->commandPool));
CHECK(vulkan_commandBuffer_create(&s->base, s->commandPool, &s->commandBuffer));
s->prepared = true;
}
return 0;
@ -555,7 +578,6 @@ int spa_vulkan_blit_unprepare(struct vulkan_blit_state *s)
{
if (s->prepared) {
vkDestroyCommandPool(s->base.device, s->commandPool, NULL);
vkDestroyFence(s->base.device, s->fence, NULL);
s->prepared = false;
}
return 0;

View file

@ -22,6 +22,11 @@ struct vulkan_pass {
uint32_t out_stream_id;
VkBufferImageCopy in_copy;
struct vulkan_staging_buffer in_staging_buffer;
VkCommandBuffer commandBuffer;
VkSemaphore pipelineSemaphore;
VkFence fence;
int sync_fd;
};
@ -32,6 +37,7 @@ struct vulkan_stream {
enum spa_data_type buffer_type;
struct spa_rectangle dim;
uint32_t bpp;
uint32_t maxsize;
struct vulkan_buffer buffers[MAX_BUFFERS];
struct spa_buffer *spa_buffers[MAX_BUFFERS];
@ -47,11 +53,7 @@ struct vulkan_blit_state {
struct vulkan_format_infos formatInfosDSP;
VkCommandPool commandPool;
VkCommandBuffer commandBuffer;
struct vulkan_staging_buffer staging_buffer;
VkFence fence;
VkSemaphore pipelineSemaphore;
unsigned int initialized:1;
unsigned int prepared:1;
unsigned int started:1;
@ -61,6 +63,7 @@ struct vulkan_blit_state {
};
int spa_vulkan_blit_init_pass(struct vulkan_blit_state *s, struct vulkan_pass *pass);
int spa_vulkan_blit_reset_pass(struct vulkan_blit_state *s, struct vulkan_pass *pass);
int spa_vulkan_blit_clear_pass(struct vulkan_blit_state *s, struct vulkan_pass *pass);
int spa_vulkan_blit_init_stream(struct vulkan_blit_state *s, struct vulkan_stream *stream, enum spa_direction,