[FFmpeg-devel] [PATCH v4 05/16] hwcontext_vulkan: use the common host map function to map frame data
Lynne
dev at lynne.ee
Thu Mar 13 19:03:37 EET 2025
---
libavutil/hwcontext_vulkan.c | 190 ++++++++++-------------------------
1 file changed, 54 insertions(+), 136 deletions(-)
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index fcff34b5e2..1104e02cfd 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -4033,155 +4033,73 @@ static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst,
return 0;
}
-static int create_mapped_buffer(AVHWFramesContext *hwfc,
- FFVkBuffer *vkb, VkBufferUsageFlags usage,
- size_t size,
- VkExternalMemoryBufferCreateInfo *create_desc,
- VkImportMemoryHostPointerInfoEXT *import_desc,
- VkMemoryHostPointerPropertiesEXT props)
-{
- int err;
- VkResult ret;
- VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
- FFVulkanFunctions *vk = &p->vkctx.vkfn;
- AVVulkanDeviceContext *hwctx = &p->p;
-
- VkBufferCreateInfo buf_spawn = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
- .pNext = create_desc,
- .usage = usage,
- .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
- .size = size,
- };
- VkMemoryRequirements req = {
- .size = size,
- .alignment = p->hprops.minImportedHostPointerAlignment,
- .memoryTypeBits = props.memoryTypeBits,
- };
-
- err = ff_vk_alloc_mem(&p->vkctx, &req,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- import_desc, &vkb->flags, &vkb->mem);
- if (err < 0)
- return err;
-
- ret = vk->CreateBuffer(hwctx->act_dev, &buf_spawn, hwctx->alloc, &vkb->buf);
- if (ret != VK_SUCCESS) {
- vk->FreeMemory(hwctx->act_dev, vkb->mem, hwctx->alloc);
- return AVERROR_EXTERNAL;
- }
-
- ret = vk->BindBufferMemory(hwctx->act_dev, vkb->buf, vkb->mem, 0);
- if (ret != VK_SUCCESS) {
- vk->FreeMemory(hwctx->act_dev, vkb->mem, hwctx->alloc);
- vk->DestroyBuffer(hwctx->act_dev, vkb->buf, hwctx->alloc);
- return AVERROR_EXTERNAL;
- }
-
- return 0;
-}
-
-static void destroy_avvkbuf(void *opaque, uint8_t *data)
-{
- FFVulkanContext *s = opaque;
- FFVkBuffer *buf = (FFVkBuffer *)data;
- ff_vk_free_buf(s, buf);
- av_free(buf);
-}
-
static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,
AVFrame *swf, VkBufferImageCopy *region, int upload)
{
int err;
- VkResult ret;
VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
- FFVulkanFunctions *vk = &p->vkctx.vkfn;
- AVVulkanDeviceContext *hwctx = &p->p;
+ uint32_t p_w, p_h;
+ int nb_src_bufs = 0;
const int planes = av_pix_fmt_count_planes(swf->format);
- VkExternalMemoryBufferCreateInfo create_desc = {
- .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
- .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
- };
- VkImportMemoryHostPointerInfoEXT import_desc = {
- .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
- .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
- };
- VkMemoryHostPointerPropertiesEXT props;
-
- for (int i = 0; i < planes; i++) {
- FFVkBuffer *vkb;
- uint32_t p_w, p_h;
- size_t offs;
- size_t buffer_size;
-
- /* We can't host map images with negative strides */
- if (swf->linesize[i] < 0) {
- err = AVERROR(EINVAL);
- goto fail;
- }
-
- get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
-
- /* Get the previous point at which mapping was possible and use it */
- offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment;
- import_desc.pHostPointer = swf->data[i] - offs;
-
- props = (VkMemoryHostPointerPropertiesEXT) {
- VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
- };
- ret = vk->GetMemoryHostPointerPropertiesEXT(hwctx->act_dev,
- import_desc.handleType,
- import_desc.pHostPointer,
- &props);
- if (!(ret == VK_SUCCESS && props.memoryTypeBits)) {
- err = AVERROR(EINVAL);
- goto fail;
- }
-
- /* Buffer region for this plane */
- region[i] = (VkBufferImageCopy) {
- .bufferOffset = offs,
- .bufferRowLength = swf->linesize[i],
- .bufferImageHeight = p_h,
- .imageSubresource.layerCount = 1,
- .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
- /* Rest of the fields adjusted/filled in later */
- };
+ /* We can't host map images with negative strides */
+ for (int i = 0; i < planes; i++)
+ if (swf->linesize[i] < 0)
+ return AVERROR(EINVAL);
- /* Add the offset at the start, which gets ignored */
- buffer_size = offs + swf->linesize[i]*p_h;
- buffer_size = FFALIGN(buffer_size, p->props.properties.limits.minMemoryMapAlignment);
- buffer_size = FFALIGN(buffer_size, p->hprops.minImportedHostPointerAlignment);
+ /* Count the number of buffers in the software frame */
+ while (swf->buf[nb_src_bufs++]);
- /* Create a buffer */
- vkb = av_mallocz(sizeof(*vkb));
- if (!vkb) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
+ /* Single buffer contains all planes */
+ if (nb_src_bufs == 1) {
+ err = ff_vk_host_map_buffer(&p->vkctx, &dst[0],
+ swf->data[0], swf->buf[0],
+ upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ if (err < 0)
+ return err;
+ (*nb_bufs)++;
- err = create_mapped_buffer(hwfc, vkb,
- upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
- VK_BUFFER_USAGE_TRANSFER_DST_BIT,
- buffer_size, &create_desc, &import_desc,
- props);
- if (err < 0) {
- av_free(vkb);
- goto fail;
+ for (int i = 0; i < planes; i++) {
+ get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
+
+ /* Buffer region for this plane */
+ region[i] = (VkBufferImageCopy) {
+ .bufferOffset = ((FFVkBuffer *)dst[0]->data)->virtual_offset +
+ swf->data[i] - swf->data[0],
+ .bufferRowLength = swf->linesize[i],
+ .bufferImageHeight = p_h,
+ .imageSubresource.layerCount = 1,
+ .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
+ /* Rest of the fields adjusted/filled in later */
+ };
}
-
- /* Create a ref */
- dst[*nb_bufs] = av_buffer_create((uint8_t *)vkb, sizeof(*vkb),
- destroy_avvkbuf, &p->vkctx, 0);
- if (!dst[*nb_bufs]) {
- destroy_avvkbuf(&p->vkctx, (uint8_t *)vkb);
- err = AVERROR(ENOMEM);
- goto fail;
+ } else if (nb_src_bufs == planes) { /* One buffer per plane */
+ for (int i = 0; i < planes; i++) {
+ err = ff_vk_host_map_buffer(&p->vkctx, &dst[i],
+ swf->data[i], swf->buf[i],
+ upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
+ VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ if (err < 0)
+ goto fail;
+ (*nb_bufs)++;
+
+ get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
+
+ /* Buffer region for this plane */
+ region[i] = (VkBufferImageCopy) {
+ .bufferOffset = ((FFVkBuffer *)dst[i]->data)->virtual_offset,
+ .bufferRowLength = swf->linesize[i],
+ .bufferImageHeight = p_h,
+ .imageSubresource.layerCount = 1,
+ .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
+ /* Rest of the fields adjusted/filled in later */
+ };
}
-
- (*nb_bufs)++;
+ } else {
+ /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy */
+ return AVERROR_PATCHWELCOME;
}
return 0;
--
2.47.2
More information about the ffmpeg-devel
mailing list