mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
vulkan: implement command buffer reuse
Using a similar design for reference counting as GstBuffer/GstBufferPool.
This commit is contained in:
parent
06d7a5ca3c
commit
82e86573b8
19 changed files with 743 additions and 174 deletions
|
@ -1661,7 +1661,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
GstVulkanImageMemory *out_img_mems[4] = { NULL, };
|
||||
GstVulkanFence *fence = NULL;
|
||||
VkFramebuffer framebuffer;
|
||||
VkCommandBuffer cmd;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
GError *error = NULL;
|
||||
VkResult err;
|
||||
int i;
|
||||
|
@ -1692,7 +1692,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (conv->cmd_pool, &error)))
|
||||
if (!(cmd_buf = gst_vulkan_command_pool_create (conv->cmd_pool, &error)))
|
||||
goto error;
|
||||
|
||||
fence = gst_vulkan_fence_new (render->device, 0, &error);
|
||||
|
@ -1711,7 +1711,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkBeginCommandBuffer") < 0)
|
||||
goto error;
|
||||
}
|
||||
|
@ -1733,7 +1734,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd, in_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
in_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&in_image_memory_barrier);
|
||||
|
||||
|
@ -1785,7 +1787,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
render_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&render_image_memory_barrier);
|
||||
|
@ -1812,11 +1814,14 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
}
|
||||
}
|
||||
|
||||
conv->current_shader->cmd_state_update (conv, cmd, conv->current_shader,
|
||||
in_img_mems, render_img_mems);
|
||||
if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd,
|
||||
framebuffer))
|
||||
return GST_FLOW_ERROR;
|
||||
conv->current_shader->cmd_state_update (conv, cmd_buf->cmd,
|
||||
conv->current_shader, in_img_mems, render_img_mems);
|
||||
if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd_buf->cmd,
|
||||
framebuffer)) {
|
||||
g_set_error (&error, GST_VULKAN_ERROR, GST_VULKAN_FAILED,
|
||||
"Failed to fill framebuffer");
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&render->out_info); i++) {
|
||||
if (render_img_mems[i] != out_img_mems[i]) {
|
||||
|
@ -1875,7 +1880,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
render_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&render_image_memory_barrier);
|
||||
|
@ -1887,7 +1892,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
render_img_mems[i]->barrier.image_layout =
|
||||
render_image_memory_barrier.newLayout;
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
out_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&out_image_memory_barrier);
|
||||
|
@ -1901,7 +1906,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
|
||||
/* XXX: This is mostly right for a downsampling pass however if
|
||||
* anything is more complicated, then we will need a new render pass */
|
||||
vkCmdBlitImage (cmd, render_img_mems[i]->image,
|
||||
vkCmdBlitImage (cmd_buf->cmd, render_img_mems[i]->image,
|
||||
render_img_mems[i]->barrier.image_layout, out_img_mems[i]->image,
|
||||
out_img_mems[i]->barrier.image_layout, 1, &blit, VK_FILTER_LINEAR);
|
||||
|
||||
|
@ -1912,7 +1917,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
}
|
||||
}
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -1920,14 +1926,19 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
gst_vulkan_trash_new_free_framebuffer (gst_vulkan_fence_ref (fence),
|
||||
framebuffer));
|
||||
gst_vulkan_trash_list_add (render->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence),
|
||||
conv->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (fence),
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
|
||||
if (!gst_vulkan_full_screen_render_submit (render, cmd, fence))
|
||||
if (!gst_vulkan_full_screen_render_submit (render, cmd_buf->cmd, fence))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
unlock_error:
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
error:
|
||||
GST_ELEMENT_ERROR (bt, LIBRARY, FAILED, ("%s", error->message), (NULL));
|
||||
g_clear_error (&error);
|
||||
|
|
|
@ -143,7 +143,7 @@ static GstFlowReturn
|
|||
_image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
||||
{
|
||||
struct ImageToRawDownload *raw = impl;
|
||||
VkCommandBuffer cmd;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
GError *error = NULL;
|
||||
GstFlowReturn ret;
|
||||
VkResult err;
|
||||
|
@ -157,7 +157,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (raw->cmd_pool, &error)))
|
||||
if (!(cmd_buf = gst_vulkan_command_pool_create (raw->cmd_pool, &error)))
|
||||
goto error;
|
||||
|
||||
if (!raw->pool) {
|
||||
|
@ -191,9 +191,10 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkBeginCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&raw->out_info); i++) {
|
||||
|
@ -207,7 +208,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
in_mem = gst_buffer_peek_memory (inbuf, i);
|
||||
if (!gst_is_vulkan_image_memory (in_mem)) {
|
||||
GST_WARNING_OBJECT (raw->download, "Input is not a GstVulkanImageMemory");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
img_mem = (GstVulkanImageMemory *) in_mem;
|
||||
|
||||
|
@ -215,7 +216,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
if (!gst_is_vulkan_buffer_memory (out_mem)) {
|
||||
GST_WARNING_OBJECT (raw->download,
|
||||
"Output is not a GstVulkanBufferMemory");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
buf_mem = (GstVulkanBufferMemory *) out_mem;
|
||||
|
||||
|
@ -266,7 +267,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
buf_mem->barrier.parent.pipeline_stages | img_mem->barrier.
|
||||
parent.pipeline_stages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1,
|
||||
&buffer_memory_barrier, 1, &image_memory_barrier);
|
||||
|
@ -278,13 +279,14 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
img_mem->barrier.parent.access_flags = image_memory_barrier.dstAccessMask;
|
||||
img_mem->barrier.image_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
|
||||
vkCmdCopyImageToBuffer (cmd, img_mem->image, img_mem->barrier.image_layout,
|
||||
buf_mem->buffer, 1, ®ion);
|
||||
vkCmdCopyImageToBuffer (cmd_buf->cmd, img_mem->image,
|
||||
img_mem->barrier.image_layout, buf_mem->buffer, 1, ®ion);
|
||||
}
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
goto error;
|
||||
|
||||
{
|
||||
VkSubmitInfo submit_info = { 0, };
|
||||
|
@ -299,7 +301,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
.pWaitSemaphores = NULL,
|
||||
.pWaitDstStageMask = &stages,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.pCommandBuffers = &cmd_buf->cmd,
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL
|
||||
};
|
||||
|
@ -316,7 +318,8 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
goto error;
|
||||
|
||||
gst_vulkan_trash_list_add (raw->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (fence, raw->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (fence,
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
}
|
||||
|
||||
/* XXX: STALL!
|
||||
|
@ -330,16 +333,19 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
out:
|
||||
return ret;
|
||||
|
||||
unlock_error:
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
error:
|
||||
if (error) {
|
||||
GST_WARNING_OBJECT (raw->download, "Error: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
gst_buffer_unref (*outbuf);
|
||||
*outbuf = NULL;
|
||||
gst_clear_buffer (outbuf);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto out;
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -538,7 +538,7 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
GstVulkanFence *fence = NULL;
|
||||
GstMemory *in_mem, *out_mem;
|
||||
VkFramebuffer framebuffer;
|
||||
VkCommandBuffer cmd;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
GError *error = NULL;
|
||||
VkResult err;
|
||||
|
||||
|
@ -565,7 +565,8 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
update_descriptor_set (vk_identity, in_img_mem->view);
|
||||
}
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (vk_identity->cmd_pool, &error)))
|
||||
if (!(cmd_buf =
|
||||
gst_vulkan_command_pool_create (vk_identity->cmd_pool, &error)))
|
||||
goto error;
|
||||
|
||||
if (!(framebuffer = _create_framebuffer (vk_identity, out_img_mem->view))) {
|
||||
|
@ -590,9 +591,10 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkBeginCommandBuffer") < 0)
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -626,7 +628,8 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd, in_img_mem->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
in_img_mem->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&in_image_memory_barrier);
|
||||
|
||||
|
@ -636,7 +639,8 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
in_image_memory_barrier.dstAccessMask;
|
||||
in_img_mem->barrier.image_layout = in_image_memory_barrier.newLayout;
|
||||
|
||||
vkCmdPipelineBarrier (cmd, out_img_mem->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
out_img_mem->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&out_image_memory_barrier);
|
||||
|
||||
|
@ -647,13 +651,14 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
out_img_mem->barrier.image_layout = out_image_memory_barrier.newLayout;
|
||||
}
|
||||
|
||||
vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
vkCmdBindDescriptorSets (cmd_buf->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
render->pipeline_layout, 0, 1, &vk_identity->descriptor_set, 0, NULL);
|
||||
if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd,
|
||||
if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd_buf->cmd,
|
||||
framebuffer))
|
||||
return GST_FLOW_ERROR;
|
||||
goto unlock_error;
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -661,14 +666,19 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
gst_vulkan_trash_new_free_framebuffer (gst_vulkan_fence_ref (fence),
|
||||
framebuffer));
|
||||
gst_vulkan_trash_list_add (render->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence),
|
||||
vk_identity->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (fence),
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
|
||||
if (!gst_vulkan_full_screen_render_submit (render, cmd, fence))
|
||||
if (!gst_vulkan_full_screen_render_submit (render, cmd_buf->cmd, fence))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
unlock_error:
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
error:
|
||||
GST_ELEMENT_ERROR (bt, LIBRARY, FAILED, ("%s", error->message), (NULL));
|
||||
g_clear_error (&error);
|
||||
|
|
|
@ -440,7 +440,7 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
GstFlowReturn ret;
|
||||
GError *error = NULL;
|
||||
VkResult err;
|
||||
VkCommandBuffer cmd;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
guint i;
|
||||
|
||||
if (!raw->cmd_pool) {
|
||||
|
@ -451,7 +451,7 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (raw->cmd_pool, &error)))
|
||||
if (!(cmd_buf = gst_vulkan_command_pool_create (raw->cmd_pool, &error)))
|
||||
goto error;
|
||||
|
||||
if (!raw->pool) {
|
||||
|
@ -485,9 +485,10 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkBeginCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&raw->out_info); i++) {
|
||||
|
@ -501,14 +502,14 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
in_mem = gst_buffer_peek_memory (inbuf, i);
|
||||
if (!gst_is_vulkan_buffer_memory (in_mem)) {
|
||||
GST_WARNING_OBJECT (raw->upload, "Input is not a GstVulkanBufferMemory");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
buf_mem = (GstVulkanBufferMemory *) in_mem;
|
||||
|
||||
out_mem = gst_buffer_peek_memory (*outbuf, i);
|
||||
if (!gst_is_vulkan_image_memory (out_mem)) {
|
||||
GST_WARNING_OBJECT (raw->upload, "Output is not a GstVulkanImageMemory");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
img_mem = (GstVulkanImageMemory *) out_mem;
|
||||
|
||||
|
@ -559,7 +560,7 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
buf_mem->barrier.parent.pipeline_stages | img_mem->barrier.
|
||||
parent.pipeline_stages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1,
|
||||
&buffer_memory_barrier, 1, &image_memory_barrier);
|
||||
|
@ -571,13 +572,14 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
img_mem->barrier.parent.access_flags = image_memory_barrier.dstAccessMask;
|
||||
img_mem->barrier.image_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
vkCmdCopyBufferToImage (cmd, buf_mem->buffer, img_mem->image,
|
||||
vkCmdCopyBufferToImage (cmd_buf->cmd, buf_mem->buffer, img_mem->image,
|
||||
img_mem->barrier.image_layout, 1, ®ion);
|
||||
}
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
goto error;
|
||||
|
||||
{
|
||||
VkSubmitInfo submit_info = { 0, };
|
||||
|
@ -592,7 +594,7 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
.pWaitSemaphores = NULL,
|
||||
.pWaitDstStageMask = &stages,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.pCommandBuffers = &cmd_buf->cmd,
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL
|
||||
};
|
||||
|
@ -609,7 +611,8 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
goto error;
|
||||
|
||||
gst_vulkan_trash_list_add (raw->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (fence, raw->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (fence,
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
}
|
||||
|
||||
gst_vulkan_trash_list_gc (raw->trash_list);
|
||||
|
@ -619,13 +622,17 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
out:
|
||||
return ret;
|
||||
|
||||
unlock_error:
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
error:
|
||||
if (error) {
|
||||
GST_WARNING_OBJECT (raw->upload, "Error: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
gst_buffer_unref (*outbuf);
|
||||
*outbuf = NULL;
|
||||
gst_clear_buffer (outbuf);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
@ -758,9 +765,9 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
struct RawToImageUpload *raw = impl;
|
||||
GstFlowReturn ret;
|
||||
GstBuffer *in_vk_copy = NULL;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
GError *error = NULL;
|
||||
VkResult err;
|
||||
VkCommandBuffer cmd;
|
||||
guint i;
|
||||
|
||||
if (!raw->cmd_pool) {
|
||||
|
@ -771,7 +778,7 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (raw->cmd_pool, &error)))
|
||||
if (!(cmd_buf = gst_vulkan_command_pool_create (raw->cmd_pool, &error)))
|
||||
goto error;
|
||||
|
||||
if (!raw->pool) {
|
||||
|
@ -805,7 +812,8 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkBeginCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -852,26 +860,26 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
if ((ret =
|
||||
gst_buffer_pool_acquire_buffer (raw->in_pool, &in_vk_copy,
|
||||
NULL)) != GST_FLOW_OK) {
|
||||
goto out;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
if (!gst_video_frame_map (&in_frame, &raw->in_info, inbuf, GST_MAP_READ)) {
|
||||
GST_WARNING_OBJECT (raw->upload, "Failed to map input buffer");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
if (!gst_video_frame_map (&out_frame, &raw->in_info, in_vk_copy,
|
||||
GST_MAP_WRITE)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
GST_WARNING_OBJECT (raw->upload, "Failed to map input buffer");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
if (!gst_video_frame_copy (&out_frame, &in_frame)) {
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
gst_video_frame_unmap (&out_frame);
|
||||
GST_WARNING_OBJECT (raw->upload, "Failed to copy input buffer");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
gst_video_frame_unmap (&in_frame);
|
||||
|
@ -884,7 +892,7 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
out_mem = gst_buffer_peek_memory (*outbuf, i);
|
||||
if (!gst_is_vulkan_image_memory (out_mem)) {
|
||||
GST_WARNING_OBJECT (raw->upload, "Output is not a GstVulkanImageMemory");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
img_mem = (GstVulkanImageMemory *) out_mem;
|
||||
|
||||
|
@ -935,7 +943,7 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
buf_mem->barrier.parent.pipeline_stages | img_mem->barrier.
|
||||
parent.pipeline_stages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1,
|
||||
&buffer_memory_barrier, 1, &image_memory_barrier);
|
||||
|
@ -947,11 +955,12 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
img_mem->barrier.parent.access_flags = image_memory_barrier.dstAccessMask;
|
||||
img_mem->barrier.image_layout = image_memory_barrier.newLayout;
|
||||
|
||||
vkCmdCopyBufferToImage (cmd, buf_mem->buffer, img_mem->image,
|
||||
vkCmdCopyBufferToImage (cmd_buf->cmd, buf_mem->buffer, img_mem->image,
|
||||
img_mem->barrier.image_layout, 1, ®ion);
|
||||
}
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -968,7 +977,7 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
.pWaitSemaphores = NULL,
|
||||
.pWaitDstStageMask = NULL,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.pCommandBuffers = &cmd_buf->cmd,
|
||||
.signalSemaphoreCount = 0,
|
||||
.pSignalSemaphores = NULL,
|
||||
};
|
||||
|
@ -985,7 +994,8 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
|
|||
goto error;
|
||||
|
||||
gst_vulkan_trash_list_add (raw->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (fence, raw->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (fence,
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
}
|
||||
|
||||
gst_vulkan_trash_list_gc (raw->trash_list);
|
||||
|
@ -998,13 +1008,17 @@ out:
|
|||
|
||||
return ret;
|
||||
|
||||
unlock_error:
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
error:
|
||||
if (error) {
|
||||
GST_WARNING_OBJECT (raw->upload, "Error: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
gst_buffer_unref (*outbuf);
|
||||
*outbuf = NULL;
|
||||
gst_clear_buffer (outbuf);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -2234,8 +2234,8 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
GstVulkanImageMemory *in_img_mems[GST_VIDEO_MAX_PLANES] = { NULL, };
|
||||
GstVulkanImageMemory *out_img_mems[4] = { NULL, };
|
||||
GstVulkanFence *fence = NULL;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
VkFramebuffer framebuffer;
|
||||
VkCommandBuffer cmd;
|
||||
GError *error = NULL;
|
||||
VkResult err;
|
||||
int i;
|
||||
|
@ -2266,7 +2266,7 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (conv->cmd_pool, &error)))
|
||||
if (!(cmd_buf = gst_vulkan_command_pool_create (conv->cmd_pool, &error)))
|
||||
goto error;
|
||||
|
||||
fence = gst_vulkan_fence_new (render->device, 0, &error);
|
||||
|
@ -2285,9 +2285,10 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkBeginCommandBuffer") < 0)
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&render->in_info); i++) {
|
||||
|
@ -2307,7 +2308,8 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd, in_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
in_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&in_image_memory_barrier);
|
||||
|
||||
|
@ -2337,7 +2339,7 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
out_img_mems[i]->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&out_image_memory_barrier);
|
||||
|
@ -2359,17 +2361,22 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
GST_VIDEO_INFO_N_PLANES (&render->out_info), attachments))) {
|
||||
g_set_error_literal (&error, GST_VULKAN_ERROR, GST_VULKAN_FAILED,
|
||||
"Failed to create framebuffer");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
}
|
||||
|
||||
view_convert_update_command_state (conv, cmd, in_img_mems, out_img_mems);
|
||||
view_convert_update_command_state (conv, cmd_buf->cmd, in_img_mems,
|
||||
out_img_mems);
|
||||
|
||||
if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd,
|
||||
framebuffer))
|
||||
return GST_FLOW_ERROR;
|
||||
if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd_buf->cmd,
|
||||
framebuffer)) {
|
||||
g_set_error (&error, GST_VULKAN_ERROR, GST_VULKAN_FAILED,
|
||||
"Failed to fill framebuffer");
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0)
|
||||
goto error;
|
||||
|
||||
|
@ -2377,14 +2384,19 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf,
|
|||
gst_vulkan_trash_new_free_framebuffer (gst_vulkan_fence_ref (fence),
|
||||
framebuffer));
|
||||
gst_vulkan_trash_list_add (render->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence),
|
||||
conv->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (fence),
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
|
||||
if (!gst_vulkan_full_screen_render_submit (render, cmd, fence))
|
||||
if (!gst_vulkan_full_screen_render_submit (render, cmd_buf->cmd, fence))
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
unlock_error:
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
error:
|
||||
GST_ELEMENT_ERROR (bt, LIBRARY, FAILED, ("%s", error->message), (NULL));
|
||||
g_clear_error (&error);
|
||||
|
|
113
gst-libs/gst/vulkan/gstvkcommandbuffer.c
Normal file
113
gst-libs/gst/vulkan/gstvkcommandbuffer.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:vulkancommandbuffer
|
||||
* @title: vulkancommandbuffer
|
||||
*
|
||||
* vulkancommandbuffer holds information about a command buffer.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstvkcommandbuffer.h"
|
||||
#include "gstvkcommandpool.h"
|
||||
#include "gstvkcommandpool-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_debug_vulkan_command_buffer
|
||||
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
|
||||
|
||||
static void
|
||||
init_debug (void)
|
||||
{
|
||||
static volatile gsize _init = 0;
|
||||
|
||||
if (g_once_init_enter (&_init)) {
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "vulkancommandbuffer", 0,
|
||||
"Vulkan command buffer");
|
||||
g_once_init_leave (&_init, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vulkan_command_buffer_dispose (GstVulkanCommandBuffer * cmd)
|
||||
{
|
||||
GstVulkanCommandPool *pool;
|
||||
|
||||
/* no pool, do free */
|
||||
if ((pool = cmd->pool) == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* keep the buffer alive */
|
||||
gst_vulkan_command_buffer_ref (cmd);
|
||||
/* return the buffer to the pool */
|
||||
gst_vulkan_command_pool_release_buffer (pool, cmd);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vulkan_command_buffer_free (GstVulkanCommandBuffer * cmd)
|
||||
{
|
||||
g_assert (cmd->pool == NULL);
|
||||
|
||||
GST_TRACE ("Freeing %p", cmd);
|
||||
|
||||
g_free (cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vulkan_command_buffer_init (GstVulkanCommandBuffer * cmd,
|
||||
VkCommandBuffer cmd_buf, VkCommandBufferLevel level)
|
||||
{
|
||||
cmd->cmd = cmd_buf;
|
||||
cmd->level = level;
|
||||
|
||||
init_debug ();
|
||||
|
||||
GST_TRACE ("new %p", cmd);
|
||||
|
||||
gst_mini_object_init (&cmd->parent, 0, GST_TYPE_VULKAN_COMMAND_BUFFER,
|
||||
NULL, (GstMiniObjectDisposeFunction) gst_vulkan_command_buffer_dispose,
|
||||
(GstMiniObjectFreeFunction) gst_vulkan_command_buffer_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_buffer_new_wrapped:
|
||||
* @cmd: a VkCommandBuffer
|
||||
* @level: the VkCommandBufferLevel for @cmd
|
||||
*
|
||||
* Returns: (transfer full): a new #GstVulkanCommandBuffer
|
||||
*/
|
||||
GstVulkanCommandBuffer *
|
||||
gst_vulkan_command_buffer_new_wrapped (VkCommandBuffer cmd,
|
||||
VkCommandBufferLevel level)
|
||||
{
|
||||
GstVulkanCommandBuffer *ret;
|
||||
|
||||
ret = g_new0 (GstVulkanCommandBuffer, 1);
|
||||
gst_vulkan_command_buffer_init (ret, cmd, level);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GST_DEFINE_MINI_OBJECT_TYPE (GstVulkanCommandBuffer, gst_vulkan_command_buffer);
|
108
gst-libs/gst/vulkan/gstvkcommandbuffer.h
Normal file
108
gst-libs/gst/vulkan/gstvkcommandbuffer.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_VULKAN_COMMAND_BUFFER_H__
|
||||
#define __GST_VULKAN_COMMAND_BUFFER_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/vulkan/vulkan_fwd.h>
|
||||
#include <gst/vulkan/gstvkapi.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GST_VULKAN_API
|
||||
GType gst_vulkan_command_buffer_get_type (void);
|
||||
#define GST_TYPE_VULKAN_COMMAND_BUFFER (gst_vulkan_command_buffer_get_type ())
|
||||
|
||||
typedef struct _GstVulkanCommandBuffer GstVulkanCommandBuffer;
|
||||
|
||||
struct _GstVulkanCommandBuffer
|
||||
{
|
||||
GstMiniObject parent;
|
||||
|
||||
VkCommandBuffer cmd;
|
||||
|
||||
/* <protected> */
|
||||
GstVulkanCommandPool *pool;
|
||||
VkCommandBufferLevel level;
|
||||
|
||||
GMutex lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_buffer_ref: (skip)
|
||||
* @cmd: a #GstVulkanCommandBuffer.
|
||||
*
|
||||
* Increases the refcount of the given buffer by one.
|
||||
*
|
||||
* Returns: (transfer full): @buf
|
||||
*/
|
||||
static inline GstVulkanCommandBuffer* gst_vulkan_command_buffer_ref(GstVulkanCommandBuffer* cmd);
|
||||
static inline GstVulkanCommandBuffer *
|
||||
gst_vulkan_command_buffer_ref (GstVulkanCommandBuffer * cmd)
|
||||
{
|
||||
return (GstVulkanCommandBuffer *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (cmd));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_buffer_unref: (skip)
|
||||
* @cmd: (transfer full): a #GstVulkanCommandBuffer.
|
||||
*
|
||||
* Decreases the refcount of the buffer. If the refcount reaches 0, the buffer
|
||||
* will be freed.
|
||||
*/
|
||||
static inline void gst_vulkan_command_buffer_unref(GstVulkanCommandBuffer* cmd);
|
||||
static inline void
|
||||
gst_vulkan_command_buffer_unref (GstVulkanCommandBuffer * cmd)
|
||||
{
|
||||
gst_mini_object_unref (GST_MINI_OBJECT_CAST (cmd));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clear_vulkan_command_buffer: (skip)
|
||||
* @cmd_ptr: a pointer to a #GstVulkanCommandBuffer reference
|
||||
*
|
||||
* Clears a reference to a #GstVulkanCommandBuffer.
|
||||
*
|
||||
* @buf_ptr must not be %NULL.
|
||||
*
|
||||
* If the reference is %NULL then this function does nothing. Otherwise, the
|
||||
* reference count of the command buffer is decreased and the pointer is set
|
||||
* to %NULL.
|
||||
*
|
||||
* Since: 1.16
|
||||
*/
|
||||
static inline void
|
||||
gst_clear_vulkan_command_buffer (GstVulkanCommandBuffer ** cmd_ptr)
|
||||
{
|
||||
gst_clear_mini_object ((GstMiniObject **) cmd_ptr);
|
||||
}
|
||||
|
||||
#define gst_vulkan_command_buffer_lock(cmd) (gst_vulkan_command_pool_lock((cmd)->pool))
|
||||
#define gst_vulkan_command_buffer_unlock(cmd) (gst_vulkan_command_pool_unlock((cmd)->pool))
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanCommandBuffer * gst_vulkan_command_buffer_new_wrapped (VkCommandBuffer cmd,
|
||||
VkCommandBufferLevel level);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GST_VULKAN_COMMAND_BUFFER_H_ */
|
33
gst-libs/gst/vulkan/gstvkcommandpool-private.h
Normal file
33
gst-libs/gst/vulkan/gstvkcommandpool-private.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_VULKAN_COMMAND_POOL_PRIVATE_H__
|
||||
#define __GST_VULKAN_COMMAND_POOL_PRIVATE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gst_vulkan_command_pool_release_buffer (GstVulkanCommandPool * pool,
|
||||
GstVulkanCommandBuffer * buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_VULKAN_IMAGE_BUFFER_POOL_H__ */
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
|
||||
#include "gstvkcommandpool.h"
|
||||
#include "gstvkcommandpool-private.h"
|
||||
|
||||
/**
|
||||
* SECTION:vkcommandpool
|
||||
|
@ -31,19 +32,40 @@
|
|||
* @see_also: #GstVulkanDevice
|
||||
*/
|
||||
|
||||
#define GST_VULKAN_COMMAND_POOL_LARGE_OUTSTANDING 1024
|
||||
|
||||
#define GET_PRIV(pool) G_TYPE_INSTANCE_GET_PRIVATE(pool, GST_TYPE_VULKAN_COMMAND_POOL, GstVulkanCommandPoolPrivate)
|
||||
|
||||
#define GST_VULKAN_COMMAND_POOL_LOCK(pool) (g_rec_mutex_lock(&GET_PRIV(pool)->rec_mutex))
|
||||
#define GST_VULKAN_COMMAND_POOL_UNLOCK(pool) (g_rec_mutex_unlock(&GET_PRIV(pool)->rec_mutex))
|
||||
|
||||
#define GST_CAT_DEFAULT gst_vulkan_command_pool_debug
|
||||
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
|
||||
|
||||
struct _GstVulkanCommandPoolPrivate
|
||||
{
|
||||
GQueue *available;
|
||||
|
||||
GRecMutex rec_mutex;
|
||||
|
||||
gsize outstanding;
|
||||
};
|
||||
|
||||
#define parent_class gst_vulkan_command_pool_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstVulkanCommandPool, gst_vulkan_command_pool,
|
||||
GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT,
|
||||
GST_TYPE_OBJECT, G_ADD_PRIVATE (GstVulkanCommandPool);
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT,
|
||||
"vulkancommandpool", 0, "Vulkan Command Pool"));
|
||||
|
||||
static void gst_vulkan_command_pool_dispose (GObject * object);
|
||||
static void gst_vulkan_command_pool_finalize (GObject * object);
|
||||
|
||||
static void
|
||||
gst_vulkan_command_pool_init (GstVulkanCommandPool * device)
|
||||
gst_vulkan_command_pool_init (GstVulkanCommandPool * pool)
|
||||
{
|
||||
GstVulkanCommandPoolPrivate *priv = GET_PRIV (pool);
|
||||
|
||||
g_rec_mutex_init (&priv->rec_mutex);
|
||||
priv->available = g_queue_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -51,23 +73,39 @@ gst_vulkan_command_pool_class_init (GstVulkanCommandPoolClass * device_class)
|
|||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) device_class;
|
||||
|
||||
gobject_class->dispose = gst_vulkan_command_pool_dispose;
|
||||
gobject_class->finalize = gst_vulkan_command_pool_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vulkan_command_pool_dispose (GObject * object)
|
||||
do_free_buffer (GstVulkanCommandBuffer * cmd_buf)
|
||||
{
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vulkan_command_pool_finalize (GObject * object)
|
||||
{
|
||||
GstVulkanCommandPool *pool = GST_VULKAN_COMMAND_POOL (object);
|
||||
GstVulkanCommandPoolPrivate *priv = GET_PRIV (pool);
|
||||
|
||||
GST_VULKAN_COMMAND_POOL_LOCK (pool);
|
||||
g_queue_free_full (priv->available, (GDestroyNotify) do_free_buffer);
|
||||
priv->available = NULL;
|
||||
GST_VULKAN_COMMAND_POOL_UNLOCK (pool);
|
||||
|
||||
if (priv->outstanding > 0)
|
||||
g_critical
|
||||
("Destroying a Vulkan command pool that has outstanding buffers!");
|
||||
|
||||
if (pool->pool)
|
||||
vkDestroyCommandPool (pool->queue->device->device, pool->pool, NULL);
|
||||
pool->pool = VK_NULL_HANDLE;
|
||||
|
||||
if (pool->queue)
|
||||
gst_object_unref (pool->queue);
|
||||
pool->queue = NULL;
|
||||
gst_clear_object (&pool->queue);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
g_rec_mutex_clear (&priv->rec_mutex);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,35 +124,145 @@ gst_vulkan_command_pool_get_queue (GstVulkanCommandPool * pool)
|
|||
return pool->queue ? gst_object_ref (pool->queue) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_pool_create: (skip)
|
||||
* @pool: a #GstVulkanCommandPool
|
||||
* @error: a #GError
|
||||
*
|
||||
* Returns: a new primary VkCommandBuffer
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
VkCommandBuffer
|
||||
gst_vulkan_command_pool_create (GstVulkanCommandPool * pool, GError ** error)
|
||||
static GstVulkanCommandBuffer *
|
||||
command_alloc (GstVulkanCommandPool * pool, GError ** error)
|
||||
{
|
||||
VkResult err;
|
||||
VkCommandBufferAllocateInfo cmd_info = { 0, };
|
||||
GstVulkanCommandBuffer *buf;
|
||||
VkCommandBuffer cmd;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VULKAN_COMMAND_POOL (pool), NULL);
|
||||
|
||||
cmd_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
cmd_info.pNext = NULL;
|
||||
cmd_info.commandPool = pool->pool;
|
||||
cmd_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
cmd_info.commandBufferCount = 1;
|
||||
|
||||
GST_VULKAN_COMMAND_POOL_LOCK (pool);
|
||||
err = vkAllocateCommandBuffers (pool->queue->device->device, &cmd_info, &cmd);
|
||||
GST_VULKAN_COMMAND_POOL_UNLOCK (pool);
|
||||
if (gst_vulkan_error_to_g_error (err, error, "vkCreateCommandBuffer") < 0)
|
||||
return NULL;
|
||||
|
||||
GST_LOG_OBJECT (pool, "created cmd buffer %p", cmd);
|
||||
buf =
|
||||
gst_vulkan_command_buffer_new_wrapped (cmd,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||
GST_LOG_OBJECT (pool, "created cmd buffer %p", buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vulkan_command_pool_can_reset (GstVulkanCommandPool * pool)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_VULKAN_COMMAND_POOL (pool), FALSE);
|
||||
|
||||
/* whether VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT was in flags on
|
||||
* pool creation */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_pool_create:
|
||||
* @pool: a #GstVulkanCommandPool
|
||||
* @error: a #GError
|
||||
*
|
||||
* Returns: a new or recycled primary #GstVulkanCommandBuffer
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
GstVulkanCommandBuffer *
|
||||
gst_vulkan_command_pool_create (GstVulkanCommandPool * pool, GError ** error)
|
||||
{
|
||||
GstVulkanCommandBuffer *cmd = NULL;
|
||||
GstVulkanCommandPoolPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VULKAN_COMMAND_POOL (pool), NULL);
|
||||
|
||||
priv = GET_PRIV (pool);
|
||||
|
||||
if (gst_vulkan_command_pool_can_reset (pool)) {
|
||||
GST_VULKAN_COMMAND_POOL_LOCK (pool);
|
||||
cmd = g_queue_pop_head (priv->available);
|
||||
GST_VULKAN_COMMAND_POOL_UNLOCK (pool);
|
||||
}
|
||||
if (!cmd)
|
||||
cmd = command_alloc (pool, error);
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
|
||||
cmd->pool = gst_object_ref (pool);
|
||||
|
||||
GST_VULKAN_COMMAND_POOL_LOCK (pool);
|
||||
priv->outstanding++;
|
||||
if (priv->outstanding > GST_VULKAN_COMMAND_POOL_LARGE_OUTSTANDING)
|
||||
g_critical ("%s: There are a large number of command buffers outstanding! "
|
||||
"This usually means there is a reference counting issue somewhere.",
|
||||
GST_OBJECT_NAME (pool));
|
||||
GST_VULKAN_COMMAND_POOL_UNLOCK (pool);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void
|
||||
gst_vulkan_command_pool_release_buffer (GstVulkanCommandPool * pool,
|
||||
GstVulkanCommandBuffer * buffer)
|
||||
{
|
||||
GstVulkanCommandPoolPrivate *priv;
|
||||
gboolean can_reset;
|
||||
|
||||
g_return_if_fail (GST_IS_VULKAN_COMMAND_POOL (pool));
|
||||
g_return_if_fail (buffer != NULL);
|
||||
g_return_if_fail (buffer->pool == pool);
|
||||
|
||||
priv = GET_PRIV (pool);
|
||||
can_reset = gst_vulkan_command_pool_can_reset (pool);
|
||||
|
||||
GST_VULKAN_COMMAND_POOL_LOCK (pool);
|
||||
if (can_reset) {
|
||||
vkResetCommandBuffer (buffer->cmd, 0);
|
||||
g_queue_push_tail (priv->available, buffer);
|
||||
GST_TRACE_OBJECT (pool, "reset command buffer %p", buffer);
|
||||
}
|
||||
/* TODO: if this is a secondary command buffer, all primary command buffers
|
||||
* that reference this command buffer will be invalid */
|
||||
priv->outstanding--;
|
||||
GST_VULKAN_COMMAND_POOL_UNLOCK (pool);
|
||||
|
||||
/* decrease the refcount that the buffer had to us */
|
||||
gst_clear_object (&buffer->pool);
|
||||
|
||||
if (!can_reset)
|
||||
gst_vulkan_command_buffer_unref (buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_pool_lock:
|
||||
* @pool: a #GstVulkanCommandPool
|
||||
*
|
||||
* This should be called to ensure no other thread will attempt to access
|
||||
* the pool's internal resources. Any modification of any of the allocated
|
||||
* #GstVulkanCommandBuffer's need to be encapsulated in a
|
||||
* gst_vulkan_command_pool_lock()/gst_vulkan_command_pool_unlock() pair to meet
|
||||
* the Vulkan API requirements that host access to the command pool is
|
||||
* externally synchronised.
|
||||
*/
|
||||
void
|
||||
gst_vulkan_command_pool_lock (GstVulkanCommandPool * pool)
|
||||
{
|
||||
g_return_if_fail (GST_IS_VULKAN_COMMAND_POOL (pool));
|
||||
GST_VULKAN_COMMAND_POOL_LOCK (pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_vulkan_command_pool_unlock:
|
||||
* @pool: a #GstVulkanCommandPool
|
||||
*
|
||||
* See the documentation for gst_vulkan_command_pool_lock() for when you would
|
||||
* need to use this function.
|
||||
*/
|
||||
void
|
||||
gst_vulkan_command_pool_unlock (GstVulkanCommandPool * pool)
|
||||
{
|
||||
g_return_if_fail (GST_IS_VULKAN_COMMAND_POOL (pool));
|
||||
GST_VULKAN_COMMAND_POOL_UNLOCK (pool);
|
||||
}
|
||||
|
|
|
@ -47,10 +47,15 @@ struct _GstVulkanCommandPoolClass
|
|||
};
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanQueue * gst_vulkan_command_pool_get_queue (GstVulkanCommandPool * pool);
|
||||
GstVulkanQueue * gst_vulkan_command_pool_get_queue (GstVulkanCommandPool * pool);
|
||||
|
||||
GST_VULKAN_API
|
||||
VkCommandBuffer gst_vulkan_command_pool_create (GstVulkanCommandPool * pool,
|
||||
GError ** error);
|
||||
GstVulkanCommandBuffer * gst_vulkan_command_pool_create (GstVulkanCommandPool * pool,
|
||||
GError ** error);
|
||||
|
||||
GST_VULKAN_API
|
||||
void gst_vulkan_command_pool_lock (GstVulkanCommandPool * pool);
|
||||
GST_VULKAN_API
|
||||
void gst_vulkan_command_pool_unlock (GstVulkanCommandPool * pool);
|
||||
|
||||
#endif /* __GST_VULKAN_COMMAND_POOL_H__ */
|
||||
|
|
|
@ -118,7 +118,7 @@ gst_vulkan_queue_create_command_pool (GstVulkanQueue * queue, GError ** error)
|
|||
cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
cmd_pool_info.pNext = NULL;
|
||||
cmd_pool_info.queueFamilyIndex = queue->family;
|
||||
cmd_pool_info.flags = 0;
|
||||
cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
|
||||
GST_OBJECT_LOCK (queue->device);
|
||||
err =
|
||||
|
|
|
@ -963,18 +963,18 @@ gst_vulkan_swapper_set_caps (GstVulkanSwapper * swapper, GstCaps * caps,
|
|||
|
||||
static gboolean
|
||||
_build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
||||
GstBuffer * buffer, VkCommandBuffer * cmd_ret, GError ** error)
|
||||
GstBuffer * buffer, GstVulkanCommandBuffer ** cmd_ret, GError ** error)
|
||||
{
|
||||
GstMemory *in_mem;
|
||||
GstVulkanImageMemory *swap_img;
|
||||
VkCommandBuffer cmd;
|
||||
GstVulkanCommandBuffer *cmd_buf;
|
||||
GstVideoRectangle src, dst, rslt;
|
||||
VkResult err;
|
||||
|
||||
g_return_val_if_fail (swap_idx < swapper->priv->n_swap_chain_images, FALSE);
|
||||
swap_img = swapper->priv->swap_chain_images[swap_idx];
|
||||
|
||||
if (!(cmd = gst_vulkan_command_pool_create (swapper->cmd_pool, error)))
|
||||
if (!(cmd_buf = gst_vulkan_command_pool_create (swapper->cmd_pool, error)))
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
|
@ -987,9 +987,10 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
|
||||
gst_vulkan_command_buffer_lock (cmd_buf);
|
||||
err = vkBeginCommandBuffer (cmd_buf->cmd, &cmd_buf_info);
|
||||
if (gst_vulkan_error_to_g_error (err, error, "vkBeginCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1009,7 +1010,8 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd, swap_img->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
swap_img->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&image_memory_barrier);
|
||||
|
||||
|
@ -1082,7 +1084,7 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd, img_mem->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd, img_mem->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&image_memory_barrier);
|
||||
|
||||
|
@ -1090,9 +1092,9 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
|||
img_mem->barrier.parent.access_flags = image_memory_barrier.dstAccessMask;
|
||||
img_mem->barrier.image_layout = image_memory_barrier.newLayout;
|
||||
|
||||
vkCmdClearColorImage (cmd, swap_img->image, swap_img->barrier.image_layout,
|
||||
&clear, 1, &clear_range);
|
||||
vkCmdBlitImage (cmd, img_mem->image, img_mem->barrier.image_layout,
|
||||
vkCmdClearColorImage (cmd_buf->cmd, swap_img->image,
|
||||
swap_img->barrier.image_layout, &clear, 1, &clear_range);
|
||||
vkCmdBlitImage (cmd_buf->cmd, img_mem->image, img_mem->barrier.image_layout,
|
||||
swap_img->image, swap_img->barrier.image_layout, 1, &blit,
|
||||
VK_FILTER_LINEAR);
|
||||
}
|
||||
|
@ -1113,7 +1115,8 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
|||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
vkCmdPipelineBarrier (cmd, swap_img->barrier.parent.pipeline_stages,
|
||||
vkCmdPipelineBarrier (cmd_buf->cmd,
|
||||
swap_img->barrier.parent.pipeline_stages,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
|
||||
&image_memory_barrier);
|
||||
|
||||
|
@ -1122,13 +1125,18 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
|
|||
swap_img->barrier.image_layout = image_memory_barrier.newLayout;
|
||||
}
|
||||
|
||||
err = vkEndCommandBuffer (cmd);
|
||||
err = vkEndCommandBuffer (cmd_buf->cmd);
|
||||
if (gst_vulkan_error_to_g_error (err, error, "vkEndCommandBuffer") < 0)
|
||||
return FALSE;
|
||||
goto unlock_error;
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
|
||||
*cmd_ret = cmd;
|
||||
*cmd_ret = cmd_buf;
|
||||
|
||||
return TRUE;
|
||||
|
||||
unlock_error:
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1140,7 +1148,7 @@ _render_buffer_unlocked (GstVulkanSwapper * swapper,
|
|||
VkSemaphoreCreateInfo semaphore_info = { 0, };
|
||||
GstVulkanFence *fence = NULL;
|
||||
VkPresentInfoKHR present;
|
||||
VkCommandBuffer cmd = VK_NULL_HANDLE;
|
||||
GstVulkanCommandBuffer *cmd_buf = NULL;
|
||||
guint32 swap_idx;
|
||||
VkResult err, present_err = VK_SUCCESS;
|
||||
|
||||
|
@ -1192,7 +1200,7 @@ reacquire:
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!_build_render_buffer_cmd (swapper, swap_idx, buffer, &cmd, error))
|
||||
if (!_build_render_buffer_cmd (swapper, swap_idx, buffer, &cmd_buf, error))
|
||||
goto error;
|
||||
|
||||
err = vkCreateSemaphore (swapper->device->device, &semaphore_info,
|
||||
|
@ -1212,7 +1220,7 @@ reacquire:
|
|||
.pWaitSemaphores = &acquire_semaphore,
|
||||
.pWaitDstStageMask = &stages,
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &cmd,
|
||||
.pCommandBuffers = &cmd_buf->cmd,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &present_semaphore,
|
||||
};
|
||||
|
@ -1229,13 +1237,14 @@ reacquire:
|
|||
goto error;
|
||||
|
||||
gst_vulkan_trash_list_add (swapper->priv->trash_list,
|
||||
gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence),
|
||||
swapper->cmd_pool, cmd));
|
||||
gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (fence),
|
||||
GST_MINI_OBJECT_CAST (cmd_buf)));
|
||||
gst_vulkan_trash_list_add (swapper->priv->trash_list,
|
||||
gst_vulkan_trash_new_free_semaphore (fence, acquire_semaphore));
|
||||
acquire_semaphore = NULL;
|
||||
|
||||
cmd = VK_NULL_HANDLE;
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
cmd_buf = NULL;
|
||||
fence = NULL;
|
||||
}
|
||||
|
||||
|
@ -1297,9 +1306,10 @@ error:
|
|||
vkDestroySemaphore (swapper->device->device, acquire_semaphore, NULL);
|
||||
if (present_semaphore)
|
||||
vkDestroySemaphore (swapper->device->device, present_semaphore, NULL);
|
||||
if (cmd)
|
||||
vkFreeCommandBuffers (swapper->device->device, swapper->cmd_pool->pool,
|
||||
1, &cmd);
|
||||
if (cmd_buf) {
|
||||
gst_vulkan_command_buffer_unlock (cmd_buf);
|
||||
gst_vulkan_command_buffer_unref (cmd_buf);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,36 +116,6 @@ FREE_DESTROY_FUNC (vkDestroyPipelineLayout, VkPipelineLayout, pipeline_layout);
|
|||
FREE_DESTROY_FUNC (vkDestroyRenderPass, VkRenderPass, render_pass);
|
||||
FREE_DESTROY_FUNC (vkDestroySemaphore, VkSemaphore, semaphore)
|
||||
FREE_DESTROY_FUNC (vkDestroySampler, VkSampler, sampler);
|
||||
#define FREE_WITH_GST_PARENT(func, type, type_name, parent_type, parent_resource) \
|
||||
struct G_PASTE(free_parent_info_,type_name) \
|
||||
{ \
|
||||
parent_type parent; \
|
||||
type resource; \
|
||||
}; \
|
||||
static void \
|
||||
G_PASTE(_free_,type_name) (GstVulkanDevice * device, struct G_PASTE(free_parent_info_,type_name) *info) \
|
||||
{ \
|
||||
GST_TRACE_OBJECT (device, "Freeing vulkan " G_STRINGIFY (type) " %p", info->resource); \
|
||||
func (device->device, info->parent parent_resource, 1, &info->resource); \
|
||||
gst_object_unref (info->parent); \
|
||||
g_free (info); \
|
||||
} \
|
||||
GstVulkanTrash * \
|
||||
G_PASTE(gst_vulkan_trash_new_free_,type_name) (GstVulkanFence * fence, \
|
||||
parent_type parent, type type_name) \
|
||||
{ \
|
||||
struct G_PASTE(free_parent_info_,type_name) *info; \
|
||||
GstVulkanTrash *trash; \
|
||||
g_return_val_if_fail (type_name != NULL, NULL); \
|
||||
info = g_new0 (struct G_PASTE(free_parent_info_,type_name), 1); \
|
||||
info->parent = gst_object_ref (parent); \
|
||||
info->resource = (gpointer) type_name; \
|
||||
trash = gst_vulkan_trash_new (fence, \
|
||||
(GstVulkanTrashNotify) G_PASTE(_free_,type_name), info); \
|
||||
return trash; \
|
||||
}
|
||||
FREE_WITH_GST_PARENT (vkFreeCommandBuffers, VkCommandBuffer, command_buffer,
|
||||
GstVulkanCommandPool *,->pool);
|
||||
#define FREE_WITH_VK_PARENT(func, type, type_name, parent_type) \
|
||||
struct G_PASTE(free_parent_info_,type_name) \
|
||||
{ \
|
||||
|
|
|
@ -105,10 +105,6 @@ GstVulkanTrash * gst_vulkan_trash_new_free_semaphore (GstVulkanFe
|
|||
VkSemaphore semaphore);
|
||||
|
||||
GST_VULKAN_API
|
||||
GstVulkanTrash * gst_vulkan_trash_new_free_command_buffer (GstVulkanFence * fence,
|
||||
GstVulkanCommandPool * parent,
|
||||
VkCommandBuffer command_buffer);
|
||||
GST_VULKAN_API
|
||||
GstVulkanTrash * gst_vulkan_trash_new_free_descriptor_set (GstVulkanFence * fence,
|
||||
VkDescriptorPool parent,
|
||||
VkDescriptorSet descriptor_set);
|
||||
|
|
|
@ -6,6 +6,7 @@ endif
|
|||
vulkan_sources = [
|
||||
'gstvkbuffermemory.c',
|
||||
'gstvkbufferpool.c',
|
||||
'gstvkcommandbuffer.c',
|
||||
'gstvkcommandpool.c',
|
||||
'gstvkdevice.c',
|
||||
'gstvkdebug.c',
|
||||
|
@ -30,6 +31,7 @@ vulkan_headers = [
|
|||
'gstvkbarrier.h',
|
||||
'gstvkbuffermemory.h',
|
||||
'gstvkbufferpool.h',
|
||||
'gstvkcommandbuffer.h',
|
||||
'gstvkcommandpool.h',
|
||||
'gstvkdebug.h',
|
||||
'gstvkdevice.h',
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <gst/vulkan/gstvkbufferpool.h>
|
||||
#include <gst/vulkan/gstvkimagebufferpool.h>
|
||||
#include <gst/vulkan/gstvkutils.h>
|
||||
#include <gst/vulkan/gstvkcommandbuffer.h>
|
||||
#include <gst/vulkan/gstvkcommandpool.h>
|
||||
#include <gst/vulkan/gstvktrash.h>
|
||||
#include <gst/vulkan/gstvkswapper.h>
|
||||
|
|
|
@ -44,6 +44,8 @@ typedef struct _GstVulkanCommandPool GstVulkanCommandPool;
|
|||
typedef struct _GstVulkanCommandPoolClass GstVulkanCommandPoolClass;
|
||||
typedef struct _GstVulkanCommandPoolPrivate GstVulkanCommandPoolPrivate;
|
||||
|
||||
typedef struct _GstVulkanCommandBuffer GstVulkanCommandBuffer;
|
||||
|
||||
typedef struct _GstVulkanDisplay GstVulkanDisplay;
|
||||
typedef struct _GstVulkanDisplayClass GstVulkanDisplayClass;
|
||||
typedef struct _GstVulkanDisplayPrivate GstVulkanDisplayPrivate;
|
||||
|
|
127
tests/check/libs/vkcommandpool.c
Normal file
127
tests/check/libs/vkcommandpool.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/vulkan/vulkan.h>
|
||||
|
||||
static GstVulkanInstance *instance;
|
||||
static GstVulkanDevice *device;
|
||||
static GstVulkanQueue *queue;
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
instance = gst_vulkan_instance_new ();
|
||||
fail_unless (gst_vulkan_instance_open (instance, NULL));
|
||||
device = gst_vulkan_device_new_with_index (instance, 0);
|
||||
fail_unless (gst_vulkan_device_open (device, NULL));
|
||||
/* family and id may be wrong! */
|
||||
queue = gst_vulkan_device_get_queue (device, 0, 0);
|
||||
fail_unless (GST_IS_VULKAN_QUEUE (queue));
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
gst_object_unref (instance);
|
||||
gst_object_unref (device);
|
||||
gst_object_unref (queue);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_new)
|
||||
{
|
||||
GstVulkanCommandPool *pool =
|
||||
gst_vulkan_queue_create_command_pool (queue, NULL);
|
||||
fail_unless (GST_IS_VULKAN_COMMAND_POOL (pool));
|
||||
gst_object_unref (pool);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
buffer_destroy_notify (gpointer ptr)
|
||||
{
|
||||
gint *counter = ptr;
|
||||
|
||||
GST_DEBUG ("buffer destroyed");
|
||||
|
||||
*counter += 1;
|
||||
}
|
||||
|
||||
/* Track when a buffer is destroyed. The counter will be increased if the
|
||||
* buffer is finalized (but not if it was re-surrected in dispose and put
|
||||
* back into the buffer pool. */
|
||||
static void
|
||||
buffer_track_destroy (GstVulkanCommandBuffer * buf, gint * counter)
|
||||
{
|
||||
gst_mini_object_set_qdata (GST_MINI_OBJECT (buf),
|
||||
g_quark_from_static_string ("TestTracker"),
|
||||
counter, buffer_destroy_notify);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_recycle)
|
||||
{
|
||||
GstVulkanCommandPool *pool =
|
||||
gst_vulkan_queue_create_command_pool (queue, NULL);
|
||||
GstVulkanCommandBuffer *cmd;
|
||||
gint dcount = 0;
|
||||
|
||||
fail_unless (GST_IS_VULKAN_COMMAND_POOL (pool));
|
||||
cmd = gst_vulkan_command_pool_create (pool, NULL);
|
||||
fail_unless (cmd != NULL);
|
||||
buffer_track_destroy (cmd, &dcount);
|
||||
|
||||
gst_vulkan_command_buffer_unref (cmd);
|
||||
/* buffer should have been recycled */
|
||||
fail_unless (dcount == 0);
|
||||
|
||||
gst_object_unref (pool);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
vkcommandpool_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("vkcommandpool");
|
||||
TCase *tc_basic = tcase_create ("general");
|
||||
gboolean have_instance;
|
||||
|
||||
suite_add_tcase (s, tc_basic);
|
||||
tcase_add_checked_fixture (tc_basic, setup, teardown);
|
||||
|
||||
/* FIXME: CI doesn't have a software vulkan renderer (and none exists currently) */
|
||||
instance = gst_vulkan_instance_new ();
|
||||
have_instance = gst_vulkan_instance_open (instance, NULL);
|
||||
gst_object_unref (instance);
|
||||
if (have_instance) {
|
||||
tcase_add_test (tc_basic, test_new);
|
||||
tcase_add_test (tc_basic, test_recycle);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (vkcommandpool);
|
|
@ -59,6 +59,7 @@ base_tests = [
|
|||
[['libs/vkwindow.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||
[['libs/vkdevice.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||
[['elements/vkdeviceprovider.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||
[['libs/vkcommandpool.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
|
||||
]
|
||||
|
||||
# FIXME: unistd dependency, unstable or not tested yet on windows
|
||||
|
|
Loading…
Reference in a new issue