* [FFmpeg-devel] [PATCH] vulkan: hardware decoding fixes and improvements (PR #20862)
@ 2025-11-08 12:45 Lynne via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: Lynne via ffmpeg-devel @ 2025-11-08 12:45 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Lynne
PR #20862 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20862
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20862.patch
This commit adds a few utilities, and fixes decoding of streams where the frame size changes.
>From a09e8c5ac07c68b6cc8f8a85a2a7063909e7ec8b Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 5 Nov 2025 20:25:31 +0100
Subject: [PATCH 1/7] prores: call ff_get_format if width and height change
The issue is that hardware decoders may have some state they depend on,
which would get broken if the dimensions change.
---
libavcodec/proresdec.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c
index 40c15a0c85..5c6b505527 100644
--- a/libavcodec/proresdec.c
+++ b/libavcodec/proresdec.c
@@ -185,7 +185,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
const int data_size, AVCodecContext *avctx)
{
- int hdr_size, width, height, flags;
+ int hdr_size, width, height, flags, dimensions_changed = 0;
int version;
const uint8_t *ptr;
enum AVPixelFormat pix_fmt;
@@ -214,6 +214,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
avctx->width, avctx->height, width, height);
if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
return ret;
+ dimensions_changed = 1;
}
ctx->frame_type = (buf[12] >> 2) & 3;
@@ -250,7 +251,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
}
}
- if (pix_fmt != ctx->pix_fmt) {
+ if (pix_fmt != ctx->pix_fmt || dimensions_changed) {
#define HWACCEL_MAX (CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL + CONFIG_PRORES_VULKAN_HWACCEL)
#if HWACCEL_MAX
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts;
--
2.49.1
>From e6e8d894f8e47d862cf8d94d17cce410f1c19d6f Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 5 Nov 2025 20:29:33 +0100
Subject: [PATCH 2/7] prores_raw: call ff_get_format if width and height change
---
libavcodec/prores_raw.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c
index 0298956efd..65e0576619 100644
--- a/libavcodec/prores_raw.c
+++ b/libavcodec/prores_raw.c
@@ -329,7 +329,7 @@ static int decode_frame(AVCodecContext *avctx,
AVFrame *frame, int *got_frame_ptr,
AVPacket *avpkt)
{
- int ret;
+ int ret, dimensions_changed = 0;
ProResRAWContext *s = avctx->priv_data;
DECLARE_ALIGNED(32, uint8_t, qmat)[64];
memset(qmat, 1, 64);
@@ -390,13 +390,14 @@ static int decode_frame(AVCodecContext *avctx,
avctx->width, avctx->height, w, h);
if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
return ret;
+ dimensions_changed = 1;
}
avctx->coded_width = FFALIGN(w, 16);
avctx->coded_height = FFALIGN(h, 16);
enum AVPixelFormat pix_fmt = AV_PIX_FMT_BAYER_RGGB16;
- if (pix_fmt != s->pix_fmt) {
+ if (pix_fmt != s->pix_fmt || dimensions_changed) {
s->pix_fmt = pix_fmt;
ret = get_pixel_format(avctx, pix_fmt);
--
2.49.1
>From e36c7d4bc52c2ca9c180d92854e851e5bacf46bc Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 5 Nov 2025 20:31:23 +0100
Subject: [PATCH 3/7] ffv1dec: call ff_get_format if width and height change
---
libavcodec/ffv1.h | 1 +
libavcodec/ffv1dec.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index d6f25737f5..adf76b0644 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -139,6 +139,7 @@ typedef struct FFV1Context {
uint32_t crcref;
enum AVPixelFormat pix_fmt;
enum AVPixelFormat configured_pix_fmt;
+ int configured_width, configured_height;
const AVFrame *cur_enc_frame;
int plane_count;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 3d67798961..a70cd74af4 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -507,11 +507,15 @@ static int read_header(FFV1Context *f, RangeCoder *c)
if (ret < 0)
return ret;
- if (f->configured_pix_fmt != f->pix_fmt) {
+ if (f->configured_pix_fmt != f->pix_fmt ||
+ f->configured_width != f->avctx->width ||
+ f->configured_height != f->avctx->height) {
f->avctx->pix_fmt = get_pixel_format(f);
if (f->avctx->pix_fmt < 0)
return AVERROR(EINVAL);
f->configured_pix_fmt = f->pix_fmt;
+ f->configured_width = f->avctx->width;
+ f->configured_height = f->avctx->height;
}
ff_dlog(f->avctx, "%d %d %d\n",
--
2.49.1
>From bf599bd2b37fb11e3ea99951d8afc076c9c18645 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Tue, 4 Nov 2025 11:40:07 +0100
Subject: [PATCH 4/7] vulkan/ffv1: use u32vec2 for slice offsets
Simplifies calculations slightly.
---
libavcodec/vulkan/ffv1_dec_setup.comp | 4 ++--
libavcodec/vulkan_ffv1.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libavcodec/vulkan/ffv1_dec_setup.comp b/libavcodec/vulkan/ffv1_dec_setup.comp
index 5da09df21c..fd297cb70a 100644
--- a/libavcodec/vulkan/ffv1_dec_setup.comp
+++ b/libavcodec/vulkan/ffv1_dec_setup.comp
@@ -114,8 +114,8 @@ void main(void)
{
const uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
- u8buf bs = u8buf(slice_data + slice_offsets[2*slice_idx + 0]);
- uint32_t slice_size = slice_offsets[2*slice_idx + 1];
+ u8buf bs = u8buf(slice_data + slice_offsets[slice_idx].x);
+ uint32_t slice_size = slice_offsets[slice_idx].y;
rac_init_dec(slice_ctx[slice_idx].c,
bs, slice_size);
diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
index b02bc71683..1ed9d7dd6c 100644
--- a/libavcodec/vulkan_ffv1.c
+++ b/libavcodec/vulkan_ffv1.c
@@ -697,7 +697,7 @@ static int init_setup_shader(FFV1Context *f, FFVulkanContext *s,
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.stages = VK_SHADER_STAGE_COMPUTE_BIT,
.mem_quali = "readonly",
- .buf_content = "uint32_t slice_offsets",
+ .buf_content = "u32vec2 slice_offsets",
.buf_elems = 2*f->max_slice_count,
},
{
--
2.49.1
>From 9ac4f6562f790636a23f08004f0f10a306219096 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 6 Nov 2025 23:30:13 +0100
Subject: [PATCH 5/7] ffv1enc_vulkan: only use native image representation
This was done for an unknown reason, and for whatever reason,
non-rgb 8+ bit formats were broken by this.
---
libavcodec/ffv1enc_vulkan.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/libavcodec/ffv1enc_vulkan.c b/libavcodec/ffv1enc_vulkan.c
index d2908a09a9..86521af6c5 100644
--- a/libavcodec/ffv1enc_vulkan.c
+++ b/libavcodec/ffv1enc_vulkan.c
@@ -96,9 +96,6 @@ typedef struct VulkanEncodeFFv1Context {
/* Intermediate frame pool */
AVBufferRef *intermediate_frames_ref;
- /* Representation mode */
- enum FFVkShaderRepFormat rep_fmt;
-
int num_h_slices;
int num_v_slices;
int force_pcm;
@@ -380,7 +377,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(&fv->s, exec, src_views, src,
- fv->rep_fmt));
+ FF_VK_REP_NATIVE));
ff_vk_frame_barrier(&fv->s, exec, src, img_bar, &nb_img_bar,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
@@ -402,7 +399,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
RET(ff_vk_create_imageviews(&fv->s, exec, tmp_views,
tmp,
- fv->rep_fmt));
+ FF_VK_REP_NATIVE));
}
/* Setup shader */
@@ -1084,7 +1081,7 @@ static int init_rct_search_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.dimensions = 2,
.mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
- fv->rep_fmt),
+ FF_VK_REP_NATIVE),
.elems = av_pix_fmt_count_planes(fv->s.frames->sw_format),
.mem_quali = "readonly",
.stages = VK_SHADER_STAGE_COMPUTE_BIT,
@@ -1169,7 +1166,7 @@ static int init_setup_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.dimensions = 2,
.mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
- fv->rep_fmt),
+ FF_VK_REP_NATIVE),
.elems = av_pix_fmt_count_planes(fv->s.frames->sw_format),
.mem_quali = "readonly",
.stages = VK_SHADER_STAGE_COMPUTE_BIT,
@@ -1355,7 +1352,7 @@ static int init_encode_shader(AVCodecContext *avctx, FFVkSPIRVCompiler *spv)
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.dimensions = 2,
.mem_layout = ff_vk_shader_rep_fmt(fv->s.frames->sw_format,
- fv->rep_fmt),
+ FF_VK_REP_NATIVE),
.elems = av_pix_fmt_count_planes(fv->s.frames->sw_format),
.mem_quali = "readonly",
.stages = VK_SHADER_STAGE_COMPUTE_BIT,
@@ -1610,12 +1607,6 @@ static av_cold int vulkan_encode_ffv1_init(AVCodecContext *avctx)
fv->is_rgb = !(f->colorspace == 0 && avctx->sw_pix_fmt != AV_PIX_FMT_YA8) &&
!(avctx->sw_pix_fmt == AV_PIX_FMT_YA8);
- /* bits_per_raw_sample use regular unsigned representation,
- * but in higher bit depths, the data is casted to int16_t */
- fv->rep_fmt = FF_VK_REP_UINT;
- if (!fv->is_rgb && f->bits_per_raw_sample > 8)
- fv->rep_fmt = FF_VK_REP_INT;
-
/* Init rct search shader */
fv->optimize_rct = fv->is_rgb && f->version >= 4 &&
!fv->force_pcm && fv->optimize_rct;
--
2.49.1
>From 16d8cb3b5e73a008582b1a0e523dfd5166c284d5 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 5 Nov 2025 10:31:18 +0100
Subject: [PATCH 6/7] vulkan: add a function to flush or invalidate a buffer
Just for convenience.
---
libavutil/vulkan.c | 32 ++++++++++++++++++++++++++++++++
libavutil/vulkan.h | 7 +++++++
2 files changed, 39 insertions(+)
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index ef755ad6f7..5e23d78e1f 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -1167,6 +1167,37 @@ int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
return 0;
}
+int ff_vk_flush_buffer(FFVulkanContext *s, FFVkBuffer *buf,
+ size_t offset, size_t mem_size,
+ int flush)
+{
+ VkResult ret;
+ FFVulkanFunctions *vk = &s->vkfn;
+
+ if (buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+ return 0;
+
+ const VkMappedMemoryRange flush_data = {
+ .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
+ .memory = buf->mem,
+ .offset = buf->virtual_offset + offset,
+ .size = mem_size,
+ };
+
+ if (flush)
+ ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, 1, &flush_data);
+ else
+ ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, 1, &flush_data);
+
+ if (ret != VK_SUCCESS) {
+ av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
+ ff_vk_ret2str(ret));
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+}
+
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
int flush)
{
@@ -1181,6 +1212,7 @@ int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
const VkMappedMemoryRange flush_buf = {
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.memory = buf[i]->mem,
+ .offset = buf[i]->virtual_offset,
.size = VK_WHOLE_SIZE,
};
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index e1c9a5792f..bdc20e4645 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -523,6 +523,13 @@ int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size,
void *pNext, void *alloc_pNext,
VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags);
+/**
+ * Flush or invalidate a single buffer, with a given size and offset.
+ */
+int ff_vk_flush_buffer(FFVulkanContext *s, FFVkBuffer *buf,
+ size_t offset, size_t mem_size,
+ int flush);
+
/**
* Buffer management code.
*/
--
2.49.1
>From ee00bfe9d34769a0784b21295ab5ee4a3dd80307 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 5 Nov 2025 15:29:57 +0100
Subject: [PATCH 7/7] vulkan: allow arrays of buffers
Could be useful.
---
libavutil/vulkan.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index 5e23d78e1f..3633cb5516 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -2580,10 +2580,11 @@ print:
GLSLA("%s", desc[i].buf_content);
}
GLSLA("\n}");
- } else if (desc[i].elems > 0) {
- GLSLA("[%i]", desc[i].elems);
}
+ if (desc[i].elems > 0)
+ GLSLA("[%i]", desc[i].elems);
+
GLSLA(";");
GLSLA("\n");
}
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-11-08 12:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-08 12:45 [FFmpeg-devel] [PATCH] vulkan: hardware decoding fixes and improvements (PR #20862) Lynne via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git