Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Lynne via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: Lynne <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PATCH] vulkan: hardware decoding fixes and improvements (PR #20862)
Date: Sat, 08 Nov 2025 12:45:19 -0000
Message-ID: <176260591958.25.4923221013460256295@2cb04c0e5124> (raw)

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

                 reply	other threads:[~2025-11-08 12:46 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=176260591958.25.4923221013460256295@2cb04c0e5124 \
    --to=ffmpeg-devel@ffmpeg.org \
    --cc=code@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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