mirror of https://git.ffmpeg.org/ffmpeg.git
hwcontext_vulkan: wrap ImageBufs into AVBufferRefs
Makes it easier to support multiple queues
This commit is contained in:
parent
c6df64035f
commit
cdb949a05c
|
@ -2466,18 +2466,22 @@ typedef struct ImageBuffer {
|
||||||
VkMemoryPropertyFlagBits flags;
|
VkMemoryPropertyFlagBits flags;
|
||||||
} ImageBuffer;
|
} 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;
|
AVVulkanDeviceContext *hwctx = ctx->hwctx;
|
||||||
if (!buf)
|
ImageBuffer *vkbuf = (ImageBuffer *)data;
|
||||||
return;
|
|
||||||
|
|
||||||
vkDestroyBuffer(hwctx->act_dev, buf->buf, hwctx->alloc);
|
if (vkbuf->buf)
|
||||||
vkFreeMemory(hwctx->act_dev, buf->mem, hwctx->alloc);
|
vkDestroyBuffer(hwctx->act_dev, vkbuf->buf, hwctx->alloc);
|
||||||
|
if (vkbuf->mem)
|
||||||
|
vkFreeMemory(hwctx->act_dev, vkbuf->mem, hwctx->alloc);
|
||||||
|
|
||||||
|
av_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_buf(AVHWDeviceContext *ctx, ImageBuffer *buf, int height,
|
static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf,
|
||||||
int *stride, VkBufferUsageFlags usage,
|
int height, int *stride, VkBufferUsageFlags usage,
|
||||||
VkMemoryPropertyFlagBits flags, void *create_pnext,
|
VkMemoryPropertyFlagBits flags, void *create_pnext,
|
||||||
void *alloc_pnext)
|
void *alloc_pnext)
|
||||||
{
|
{
|
||||||
|
@ -2494,34 +2498,44 @@ static int create_buf(AVHWDeviceContext *ctx, ImageBuffer *buf, int height,
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ImageBuffer *vkbuf = av_mallocz(sizeof(*vkbuf));
|
||||||
|
if (!vkbuf)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
*stride = FFALIGN(*stride, p->props.limits.optimalBufferCopyRowPitchAlignment);
|
*stride = FFALIGN(*stride, p->props.limits.optimalBufferCopyRowPitchAlignment);
|
||||||
buf_spawn.size = height*(*stride);
|
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) {
|
if (ret != VK_SUCCESS) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to create buffer: %s\n",
|
av_log(ctx, AV_LOG_ERROR, "Failed to create buffer: %s\n",
|
||||||
vk_ret2str(ret));
|
vk_ret2str(ret));
|
||||||
return AVERROR_EXTERNAL;
|
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)
|
if (err)
|
||||||
return 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) {
|
if (ret != VK_SUCCESS) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
|
av_log(ctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
|
||||||
vk_ret2str(ret));
|
vk_ret2str(ret));
|
||||||
free_buf(ctx, buf);
|
free_buf(ctx, (uint8_t *)vkbuf);
|
||||||
return AVERROR_EXTERNAL;
|
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;
|
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)
|
int nb_buffers, int invalidate)
|
||||||
{
|
{
|
||||||
VkResult ret;
|
VkResult ret;
|
||||||
|
@ -2530,7 +2544,8 @@ static int map_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, uint8_t *mem[],
|
||||||
int invalidate_count = 0;
|
int invalidate_count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < nb_buffers; i++) {
|
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]);
|
VK_WHOLE_SIZE, 0, (void **)&mem[i]);
|
||||||
if (ret != VK_SUCCESS) {
|
if (ret != VK_SUCCESS) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
|
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;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < nb_buffers; i++) {
|
for (int i = 0; i < nb_buffers; i++) {
|
||||||
|
ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data;
|
||||||
const VkMappedMemoryRange ival_buf = {
|
const VkMappedMemoryRange ival_buf = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
.memory = buf[i].mem,
|
.memory = vkbuf->mem,
|
||||||
.size = VK_WHOLE_SIZE,
|
.size = VK_WHOLE_SIZE,
|
||||||
};
|
};
|
||||||
if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||||
continue;
|
continue;
|
||||||
invalidate_ctx[invalidate_count++] = ival_buf;
|
invalidate_ctx[invalidate_count++] = ival_buf;
|
||||||
}
|
}
|
||||||
|
@ -2564,7 +2580,7 @@ static int map_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf, uint8_t *mem[],
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unmap_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf,
|
static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs,
|
||||||
int nb_buffers, int flush)
|
int nb_buffers, int flush)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -2575,12 +2591,13 @@ static int unmap_buffers(AVHWDeviceContext *ctx, ImageBuffer *buf,
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
for (int i = 0; i < nb_buffers; i++) {
|
for (int i = 0; i < nb_buffers; i++) {
|
||||||
|
ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data;
|
||||||
const VkMappedMemoryRange flush_buf = {
|
const VkMappedMemoryRange flush_buf = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
.memory = buf[i].mem,
|
.memory = vkbuf->mem,
|
||||||
.size = VK_WHOLE_SIZE,
|
.size = VK_WHOLE_SIZE,
|
||||||
};
|
};
|
||||||
if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||||
continue;
|
continue;
|
||||||
flush_ctx[flush_count++] = flush_buf;
|
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++)
|
for (int i = 0; i < nb_buffers; i++) {
|
||||||
vkUnmapMemory(hwctx->act_dev, buf[i].mem);
|
ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data;
|
||||||
|
vkUnmapMemory(hwctx->act_dev, vkbuf->mem);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int transfer_image_buf(AVHWDeviceContext *ctx, AVVkFrame *frame,
|
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)
|
int h, enum AVPixelFormat pix_fmt, int to_buf)
|
||||||
{
|
{
|
||||||
VkResult ret;
|
VkResult ret;
|
||||||
|
@ -2678,6 +2697,7 @@ static int transfer_image_buf(AVHWDeviceContext *ctx, AVVkFrame *frame,
|
||||||
|
|
||||||
/* Schedule a copy for each plane */
|
/* Schedule a copy for each plane */
|
||||||
for (int i = 0; i < planes; i++) {
|
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_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;
|
const int p_h = i > 0 ? AV_CEIL_RSHIFT(h, desc->log2_chroma_h) : h;
|
||||||
VkBufferImageCopy buf_reg = {
|
VkBufferImageCopy buf_reg = {
|
||||||
|
@ -2696,9 +2716,9 @@ static int transfer_image_buf(AVHWDeviceContext *ctx, AVVkFrame *frame,
|
||||||
|
|
||||||
if (to_buf)
|
if (to_buf)
|
||||||
vkCmdCopyImageToBuffer(s->cmd.buf, frame->img[i], frame->layout[i],
|
vkCmdCopyImageToBuffer(s->cmd.buf, frame->img[i], frame->layout[i],
|
||||||
buffer[i].buf, 1, &buf_reg);
|
vkbuf->buf, 1, &buf_reg);
|
||||||
else
|
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);
|
frame->layout[i], 1, &buf_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2736,7 +2756,7 @@ static int vulkan_transfer_data_from_mem(AVHWFramesContext *hwfc, AVFrame *dst,
|
||||||
AVFrame tmp;
|
AVFrame tmp;
|
||||||
AVVkFrame *f = (AVVkFrame *)dst->data[0];
|
AVVkFrame *f = (AVVkFrame *)dst->data[0];
|
||||||
AVHWDeviceContext *dev_ctx = hwfc->device_ctx;
|
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);
|
const int planes = av_pix_fmt_count_planes(src->format);
|
||||||
int log2_chroma = av_pix_fmt_desc_get(src->format)->log2_chroma_h;
|
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;
|
int p_height = i > 0 ? AV_CEIL_RSHIFT(h, log2_chroma) : h;
|
||||||
|
|
||||||
tmp.linesize[i] = FFABS(src->linesize[i]);
|
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,
|
&tmp.linesize[i], VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, NULL, NULL);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, NULL, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2779,22 +2799,22 @@ static int vulkan_transfer_data_from_mem(AVHWFramesContext *hwfc, AVFrame *dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map, copy image to buffer, unmap */
|
/* 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;
|
goto end;
|
||||||
|
|
||||||
av_image_copy(tmp.data, tmp.linesize, (const uint8_t **)src->data,
|
av_image_copy(tmp.data, tmp.linesize, (const uint8_t **)src->data,
|
||||||
src->linesize, src->format, src->width, src->height);
|
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;
|
goto end;
|
||||||
|
|
||||||
/* Copy buffers to image */
|
/* 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);
|
src->width, src->height, src->format, 0);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
for (int i = 0; i < planes; i++)
|
for (int i = 0; i < planes; i++)
|
||||||
free_buf(dev_ctx, &buf[i]);
|
av_buffer_unref(&bufs[i]);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2896,7 +2916,7 @@ static int vulkan_transfer_data_to_mem(AVHWFramesContext *hwfc, AVFrame *dst,
|
||||||
AVFrame tmp;
|
AVFrame tmp;
|
||||||
AVVkFrame *f = (AVVkFrame *)src->data[0];
|
AVVkFrame *f = (AVVkFrame *)src->data[0];
|
||||||
AVHWDeviceContext *dev_ctx = hwfc->device_ctx;
|
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);
|
const int planes = av_pix_fmt_count_planes(dst->format);
|
||||||
int log2_chroma = av_pix_fmt_desc_get(dst->format)->log2_chroma_h;
|
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;
|
int p_height = i > 0 ? AV_CEIL_RSHIFT(h, log2_chroma) : h;
|
||||||
|
|
||||||
tmp.linesize[i] = FFABS(dst->linesize[i]);
|
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,
|
&tmp.linesize[i], VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, NULL, NULL);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy image to buffer */
|
/* 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)))
|
dst->width, dst->height, dst->format, 1)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
/* Map, copy buffer to frame, unmap */
|
/* 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;
|
goto end;
|
||||||
|
|
||||||
av_image_copy(dst->data, dst->linesize, (const uint8_t **)tmp.data,
|
av_image_copy(dst->data, dst->linesize, (const uint8_t **)tmp.data,
|
||||||
tmp.linesize, dst->format, dst->width, dst->height);
|
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:
|
end:
|
||||||
for (int i = 0; i < planes; i++)
|
for (int i = 0; i < planes; i++)
|
||||||
free_buf(dev_ctx, &buf[i]);
|
av_buffer_unref(&bufs[i]);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue