ffmpeg | branch: master | Lynne <d...@lynne.ee> | Thu Mar 13 03:08:39 2025 
+0000| [6c9affb3e660d14ddca17d4eaa1c8d7b47b0d8a0] | committer: Lynne

hwcontext_vulkan: fix downloads; use the common host map function to map frame 
data

This commit uses the recently exported code for host mapping images back
where it was exported from.

The function also had broken download code for image downloading since its
recent refactor.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=6c9affb3e660d14ddca17d4eaa1c8d7b47b0d8a0
---

 libavutil/hwcontext_vulkan.c | 237 ++++++++++++++-----------------------------
 1 file changed, 77 insertions(+), 160 deletions(-)

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index fcff34b5e2..46457f8fcb 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -3957,7 +3957,7 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
AVBufferRef *buf,
         .size   = VK_WHOLE_SIZE,
     };
 
-    if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && !upload) {
+    if (!upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
         ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1,
                                                &flush_info);
         if (ret != VK_SUCCESS) {
@@ -3967,15 +3967,25 @@ static int copy_buffer_data(AVHWFramesContext *hwfc, 
AVBufferRef *buf,
         }
     }
 
-    for (int i = 0; i < planes; i++)
-        av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
-                            region[i].bufferRowLength,
-                            swf->data[i],
-                            swf->linesize[i],
-                            swf->linesize[i],
-                            region[i].imageExtent.height);
-
-    if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && upload) {
+    if (upload) {
+        for (int i = 0; i < planes; i++)
+            av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
+                                region[i].bufferRowLength,
+                                swf->data[i],
+                                swf->linesize[i],
+                                swf->linesize[i],
+                                region[i].imageExtent.height);
+    } else {
+        for (int i = 0; i < planes; i++)
+            av_image_copy_plane(swf->data[i],
+                                swf->linesize[i],
+                                vkbuf->mapped_mem + region[i].bufferOffset,
+                                region[i].bufferRowLength,
+                                swf->linesize[i],
+                                region[i].imageExtent.height);
+    }
+
+    if (upload && !(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
         ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1,
                                           &flush_info);
         if (ret != VK_SUCCESS) {
@@ -3992,38 +4002,32 @@ static int get_plane_buf(AVHWFramesContext *hwfc, 
AVBufferRef **dst,
                          AVFrame *swf, VkBufferImageCopy *region, int upload)
 {
     int err;
+    uint32_t p_w, p_h;
     VulkanFramesPriv *fp = hwfc->hwctx;
     VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
     const int planes = av_pix_fmt_count_planes(swf->format);
+    VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
+                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT;
 
     size_t buf_offset = 0;
     for (int i = 0; i < planes; i++) {
-        size_t size;
-        ptrdiff_t linesize = swf->linesize[i];
-
-        uint32_t p_w, p_h;
         get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
 
-        linesize = FFALIGN(linesize,
-                           
p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
-        size = p_h*linesize;
-
         region[i] = (VkBufferImageCopy) {
             .bufferOffset = buf_offset,
-            .bufferRowLength = linesize,
+            .bufferRowLength = FFALIGN(swf->linesize[i],
+                                       
p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
             .bufferImageHeight = p_h,
             .imageSubresource.layerCount = 1,
             .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
             /* Rest of the fields adjusted/filled in later */
         };
 
-        buf_offset = FFALIGN(buf_offset + size,
-                             
p->props.properties.limits.optimalBufferCopyOffsetAlignment);
+        buf_offset += FFALIGN(p_h*region[i].bufferRowLength,
+                              
p->props.properties.limits.optimalBufferCopyOffsetAlignment);
     }
 
-    err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst,
-                                  VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
-                                  VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+    err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
                                   NULL, buf_offset,
                                   VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
                                   VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
@@ -4033,155 +4037,53 @@ 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;
 
+    int nb_src_bufs;
     const int planes = av_pix_fmt_count_planes(swf->format);
+    VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
+                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT;
 
-    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 */
+    nb_src_bufs = 0;
+    while (swf->buf[nb_src_bufs])
+        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],
+                                    buf_usage);
+        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++)
+            region[i].bufferOffset = ((FFVkBuffer 
*)dst[0]->data)->virtual_offset +
+                                     swf->data[i] - swf->data[0];
+    } 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],
+                                        buf_usage);
+            if (err < 0)
+                goto fail;
+            (*nb_bufs)++;
 
-        /* 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;
+            region[i].bufferOffset = ((FFVkBuffer 
*)dst[i]->data)->virtual_offset;
         }
-
-        (*nb_bufs)++;
+    } else {
+        /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy 
*/
+        return AVERROR_PATCHWELCOME;
     }
 
     return 0;
@@ -4228,6 +4130,21 @@ static int vulkan_transfer_frame(AVHWFramesContext *hwfc,
     if (swf->width > hwfc->width || swf->height > hwfc->height)
         return AVERROR(EINVAL);
 
+    for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) {
+        uint32_t p_w, p_h;
+        get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
+
+        /* Buffer region for this plane */
+        region[i] = (VkBufferImageCopy) {
+            .bufferOffset = 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 */
+        };
+    }
+
     /* Setup buffers first */
     if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) {
         err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);

_______________________________________________
ffmpeg-cvslog mailing list
ffmpeg-cvslog@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog

To unsubscribe, visit link above, or email
ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to