diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 83de4b5cb7ba9b6511ef047bd4bfa731aa2843a9..2f4fe6a797f4292e3cbec0df769da15c64d15b5d 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2466,18 +2466,22 @@ typedef struct ImageBuffer { VkMemoryPropertyFlagBits flags; } ImageBuffer; -static void free_buf(AVHWDeviceContext *ctx, ImageBuffer *buf) +static void free_buf(void *opaque, uint8_t *data) { + AVHWDeviceContext *ctx = opaque; AVVulkanDeviceContext *hwctx = ctx->hwctx; - if (!buf) - return; + ImageBuffer *vkbuf = (ImageBuffer *)data; + + if (vkbuf->buf) + vkDestroyBuffer(hwctx->act_dev, vkbuf->buf, hwctx->alloc); + if (vkbuf->mem) + vkFreeMemory(hwctx->act_dev, vkbuf->mem, hwctx->alloc); - vkDestroyBuffer(hwctx->act_dev, buf->buf, hwctx->alloc); - vkFreeMemory(hwctx->act_dev, buf->mem, hwctx->alloc); + av_free(data); } -static int create_buf(AVHWDeviceContext *ctx, ImageBuffer *buf, int height, - int *stride, VkBufferUsageFlags usage, +static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, + int height, int *stride, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags, void *create_pnext, void *alloc_pnext) { @@ -2494,34 +2498,44 @@ static int create_buf(AVHWDeviceContext *ctx, ImageBuffer *buf, int height, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }; + ImageBuffer *vkbuf = av_mallocz(sizeof(*vkbuf)); + if (!vkbuf) + return AVERROR(ENOMEM); + *stride = FFALIGN(*stride, p->props.limits.optimalBufferCopyRowPitchAlignment); buf_spawn.size = height*(*stride); - ret = vkCreateBuffer(hwctx->act_dev, &buf_spawn, NULL, &buf->buf); + ret = vkCreateBuffer(hwctx->act_dev, &buf_spawn, NULL, &vkbuf->buf); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to create buffer: %s\n", vk_ret2str(ret)); return AVERROR_EXTERNAL; } - vkGetBufferMemoryRequirements(hwctx->act_dev, buf->buf, &req); + vkGetBufferMemoryRequirements(hwctx->act_dev, vkbuf->buf, &req); - err = alloc_mem(ctx, &req, flags, alloc_pnext, &buf->flags, &buf->mem); + err = alloc_mem(ctx, &req, flags, alloc_pnext, &vkbuf->flags, &vkbuf->mem); if (err) return err; - ret = vkBindBufferMemory(hwctx->act_dev, buf->buf, buf->mem, 0); + ret = vkBindBufferMemory(hwctx->act_dev, vkbuf->buf, vkbuf->mem, 0); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", vk_ret2str(ret)); - free_buf(ctx, buf); + free_buf(ctx, (uint8_t *)vkbuf); return AVERROR_EXTERNAL; } + *buf = av_buffer_create((uint8_t *)vkbuf, sizeof(*vkbuf), free_buf, ctx, 0); + if (!(*buf)) { + free_buf(ctx, (uint8_t *)vkbuf); + return AVERROR(ENOMEM); + } + return 0; } -static int map_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, uint8_t *mem[], +static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[], int nb_buffers, int invalidate) { VkResult ret; @@ -2530,7 +2544,8 @@ static int map_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, uint8_t *mem[], int invalidate_count = 0; for (int i = 0; i < nb_buffers; i++) { - ret = vkMapMemory(hwctx->act_dev, buf[i].mem, 0, + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + ret = vkMapMemory(hwctx->act_dev, vkbuf->mem, 0, VK_WHOLE_SIZE, 0, (void **)&mem[i]); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", @@ -2543,12 +2558,13 @@ static int map_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, uint8_t *mem[], return 0; for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; const VkMappedMemoryRange ival_buf = { .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, + .memory = vkbuf->mem, .size = VK_WHOLE_SIZE, }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) continue; invalidate_ctx[invalidate_count++] = ival_buf; } @@ -2564,7 +2580,7 @@ static int map_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, uint8_t *mem[], return 0; } -static int unmap_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, +static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, int nb_buffers, int flush) { int err = 0; @@ -2575,12 +2591,13 @@ static int unmap_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, if (flush) { for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; const VkMappedMemoryRange flush_buf = { .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, + .memory = vkbuf->mem, .size = VK_WHOLE_SIZE, }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) continue; flush_ctx[flush_count++] = flush_buf; } @@ -2595,14 +2612,16 @@ static int unmap_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, } } - for (int i = 0; i < nb_buffers; i++) - vkUnmapMemory(hwctx->act_dev, buf[i].mem); + for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + vkUnmapMemory(hwctx->act_dev, vkbuf->mem); + } return err; } static int transfer_image_buf(AVHWDeviceContext *ctx, AVVkFrame *frame, - ImageBuffer *buffer, const int *buf_stride, int w, + AVBufferRef **bufs, const int *buf_stride, int w, int h, enum AVPixelFormat pix_fmt, int to_buf) { VkResult ret; @@ -2678,6 +2697,7 @@ static int transfer_image_buf(AVHWDeviceContext *ctx, AVVkFrame *frame, /* Schedule a copy for each plane */ for (int i = 0; i < planes; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; const int p_w = i > 0 ? AV_CEIL_RSHIFT(w, desc->log2_chroma_w) : w; const int p_h = i > 0 ? AV_CEIL_RSHIFT(h, desc->log2_chroma_h) : h; VkBufferImageCopy buf_reg = { @@ -2696,9 +2716,9 @@ static int transfer_image_buf(AVHWDeviceContext *ctx, AVVkFrame *frame, if (to_buf) vkCmdCopyImageToBuffer(s->cmd.buf, frame->img[i], frame->layout[i], - buffer[i].buf, 1, &buf_reg); + vkbuf->buf, 1, &buf_reg); else - vkCmdCopyBufferToImage(s->cmd.buf, buffer[i].buf, frame->img[i], + vkCmdCopyBufferToImage(s->cmd.buf, vkbuf->buf, frame->img[i], frame->layout[i], 1, &buf_reg); } @@ -2736,7 +2756,7 @@ static int vulkan_transfer_data_from_mem(AVHWFramesContext *hwfc, AVFrame *dst, AVFrame tmp; AVVkFrame *f = (AVVkFrame *)dst->data[0]; AVHWDeviceContext *dev_ctx = hwfc->device_ctx; - ImageBuffer buf[AV_NUM_DATA_POINTERS] = { { 0 } }; + AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; const int planes = av_pix_fmt_count_planes(src->format); int log2_chroma = av_pix_fmt_desc_get(src->format)->log2_chroma_h; @@ -2771,7 +2791,7 @@ static int vulkan_transfer_data_from_mem(AVHWFramesContext *hwfc, AVFrame *dst, int p_height = i > 0 ? AV_CEIL_RSHIFT(h, log2_chroma) : h; tmp.linesize[i] = FFABS(src->linesize[i]); - err = create_buf(dev_ctx, &buf[i], p_height, + err = create_buf(dev_ctx, &bufs[i], p_height, &tmp.linesize[i], VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, NULL, NULL); if (err) @@ -2779,22 +2799,22 @@ static int vulkan_transfer_data_from_mem(AVHWFramesContext *hwfc, AVFrame *dst, } /* Map, copy image to buffer, unmap */ - if ((err = map_buffers(dev_ctx, buf, tmp.data, planes, 0))) + if ((err = map_buffers(dev_ctx, bufs, tmp.data, planes, 0))) goto end; av_image_copy(tmp.data, tmp.linesize, (const uint8_t **)src->data, src->linesize, src->format, src->width, src->height); - if ((err = unmap_buffers(dev_ctx, buf, planes, 1))) + if ((err = unmap_buffers(dev_ctx, bufs, planes, 1))) goto end; /* Copy buffers to image */ - err = transfer_image_buf(dev_ctx, f, buf, tmp.linesize, + err = transfer_image_buf(dev_ctx, f, bufs, tmp.linesize, src->width, src->height, src->format, 0); end: for (int i = 0; i < planes; i++) - free_buf(dev_ctx, &buf[i]); + av_buffer_unref(&bufs[i]); return err; } @@ -2896,7 +2916,7 @@ static int vulkan_transfer_data_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, AVFrame tmp; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVHWDeviceContext *dev_ctx = hwfc->device_ctx; - ImageBuffer buf[AV_NUM_DATA_POINTERS] = { { 0 } }; + AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; const int planes = av_pix_fmt_count_planes(dst->format); int log2_chroma = av_pix_fmt_desc_get(dst->format)->log2_chroma_h; @@ -2926,28 +2946,28 @@ static int vulkan_transfer_data_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, int p_height = i > 0 ? AV_CEIL_RSHIFT(h, log2_chroma) : h; tmp.linesize[i] = FFABS(dst->linesize[i]); - err = create_buf(dev_ctx, &buf[i], p_height, + err = create_buf(dev_ctx, &bufs[i], p_height, &tmp.linesize[i], VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, NULL, NULL); } /* Copy image to buffer */ - if ((err = transfer_image_buf(dev_ctx, f, buf, tmp.linesize, + if ((err = transfer_image_buf(dev_ctx, f, bufs, tmp.linesize, dst->width, dst->height, dst->format, 1))) goto end; /* Map, copy buffer to frame, unmap */ - if ((err = map_buffers(dev_ctx, buf, tmp.data, planes, 1))) + if ((err = map_buffers(dev_ctx, bufs, tmp.data, planes, 1))) goto end; av_image_copy(dst->data, dst->linesize, (const uint8_t **)tmp.data, tmp.linesize, dst->format, dst->width, dst->height); - err = unmap_buffers(dev_ctx, buf, planes, 0); + err = unmap_buffers(dev_ctx, bufs, planes, 0); end: for (int i = 0; i < planes; i++) - free_buf(dev_ctx, &buf[i]); + av_buffer_unref(&bufs[i]); return err; }