This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 4d63e3dd4c642a7b5e439d810c0772580ecf74b1
Author:     Lynne <[email protected]>
AuthorDate: Fri May 29 04:11:45 2026 +0900
Commit:     Lynne <[email protected]>
CommitDate: Wed Jun 3 14:12:50 2026 +0900

    vulkan_ffv1: add Bayer encoder
    
    Sponsored-by: Sovereign Tech Fund
---
 libavcodec/ffv1enc_vulkan.c                        |  28 +++--
 libavcodec/vulkan/Makefile                         |   4 +-
 libavcodec/vulkan/ffv1_enc.comp.glsl               | 118 +++++++++++++++++----
 ..._enc_rgb.comp.glsl => ffv1_enc_bayer.comp.glsl} |   1 +
 ...t.comp.glsl => ffv1_enc_bayer_golomb.comp.glsl} |   3 +-
 libavcodec/vulkan/ffv1_enc_setup.comp.glsl         |  14 +--
 6 files changed, 134 insertions(+), 34 deletions(-)

diff --git a/libavcodec/ffv1enc_vulkan.c b/libavcodec/ffv1enc_vulkan.c
index 7c22ced785..83950cc504 100644
--- a/libavcodec/ffv1enc_vulkan.c
+++ b/libavcodec/ffv1enc_vulkan.c
@@ -150,6 +150,12 @@ extern const unsigned int 
ff_ffv1_enc_rgb_float_golomb_comp_spv_len;
 extern const unsigned char ff_ffv1_enc_sort32_comp_spv_data[];
 extern const unsigned int ff_ffv1_enc_sort32_comp_spv_len;
 
+extern const unsigned char ff_ffv1_enc_bayer_comp_spv_data[];
+extern const unsigned int ff_ffv1_enc_bayer_comp_spv_len;
+
+extern const unsigned char ff_ffv1_enc_bayer_golomb_comp_spv_data[];
+extern const unsigned int ff_ffv1_enc_bayer_golomb_comp_spv_len;
+
 static int run_rct_search(AVCodecContext *avctx, FFVkExecContext *exec,
                           AVFrame *enc_in, VkImageView *enc_in_views,
                           FFVkBuffer *slice_data_buf, uint32_t slice_data_size,
@@ -1210,7 +1216,16 @@ static int init_encode_shader(AVCodecContext *avctx, 
VkSpecializationInfo *sl)
     ff_vk_shader_add_descriptor_set(&fv->s, shd, desc_set,
                                     4 + fv->is_rgb + !!f->remap_mode, 0, 0);
 
-    if (f->remap_mode) {
+    if (f->bayer) {
+        if (fv->ctx.ac == AC_GOLOMB_RICE)
+            ff_vk_shader_link(&fv->s, shd,
+                              ff_ffv1_enc_bayer_golomb_comp_spv_data,
+                              ff_ffv1_enc_bayer_golomb_comp_spv_len, "main");
+        else
+            ff_vk_shader_link(&fv->s, shd,
+                              ff_ffv1_enc_bayer_comp_spv_data,
+                              ff_ffv1_enc_bayer_comp_spv_len, "main");
+    } else if (f->remap_mode) {
         if (fv->ctx.ac == AC_GOLOMB_RICE)
             ff_vk_shader_link(&fv->s, shd,
                               ff_ffv1_enc_rgb_float_golomb_comp_spv_data,
@@ -1262,8 +1277,9 @@ static av_cold int vulkan_encode_ffv1_init(AVCodecContext 
*avctx)
     if (err < 0)
         return err;
 
-    /* Target version 3 by default */
-    f->version = 3;
+    /* Target version 3 by default; Bayer is a version 4 feature (the legacy
+     * v3 bits-per-plane increment would mismatch the shaders' c_bits-1). */
+    f->version = f->bayer ? 4 : 3;
 
     err = ff_ffv1_encode_init(avctx);
     if (err < 0)
@@ -1288,9 +1304,9 @@ static av_cold int vulkan_encode_ffv1_init(AVCodecContext 
*avctx)
             return AVERROR_INVALIDDATA;
     }
 
-    /* We target version 4.3 */
+    /* We target version 4.3 by default, remap is 4.9, Bayer is 4.10 */
     if (f->version == 4)
-        f->micro_version = f->remap_mode ? 9 : 3;
+        f->micro_version = f->bayer ? 10 : (f->remap_mode ? 9 : 3);
 
     f->num_h_slices = fv->num_h_slices;
     f->num_v_slices = fv->num_v_slices;
@@ -1437,7 +1453,7 @@ static av_cold int vulkan_encode_ffv1_init(AVCodecContext 
*avctx)
 
     /* Init rct search shader */
     fv->optimize_rct = fv->is_rgb && f->version >= 4 &&
-                       !fv->force_pcm && fv->optimize_rct;
+                       !fv->force_pcm && fv->optimize_rct && !f->bayer;
 
     /* Init shader specialization consts */
     SPEC_LIST_CREATE(sl, 19, 19*sizeof(uint32_t))
diff --git a/libavcodec/vulkan/Makefile b/libavcodec/vulkan/Makefile
index 0425548978..3c47cbd58b 100644
--- a/libavcodec/vulkan/Makefile
+++ b/libavcodec/vulkan/Makefile
@@ -15,7 +15,9 @@ OBJS-$(CONFIG_FFV1_VULKAN_ENCODER) += 
vulkan/ffv1_enc_setup.comp.spv.o \
                                       vulkan/ffv1_enc_remap.comp.spv.o \
                                       vulkan/ffv1_enc_rgb_float.comp.spv.o \
                                       
vulkan/ffv1_enc_rgb_float_golomb.comp.spv.o \
-                                      vulkan/ffv1_enc_sort32.comp.spv.o
+                                      vulkan/ffv1_enc_sort32.comp.spv.o \
+                                      vulkan/ffv1_enc_bayer.comp.spv.o \
+                                      vulkan/ffv1_enc_bayer_golomb.comp.spv.o
 
 OBJS-$(CONFIG_FFV1_VULKAN_HWACCEL) += vulkan/ffv1_dec_setup.comp.spv.o \
                                       vulkan/ffv1_dec_reset.comp.spv.o \
diff --git a/libavcodec/vulkan/ffv1_enc.comp.glsl 
b/libavcodec/vulkan/ffv1_enc.comp.glsl
index 1c30e91828..a4a942782d 100644
--- a/libavcodec/vulkan/ffv1_enc.comp.glsl
+++ b/libavcodec/vulkan/ffv1_enc.comp.glsl
@@ -79,6 +79,9 @@ void encode_line_pcm(in SliceContext sc, readonly uimage2D 
img,
         return;
 
     int w = sc.slice_dim.x;
+#ifdef BAYER
+    w >>= 1;
+#endif
 
 #ifndef RGB
     if (p > 0 && p < 3) {
@@ -100,6 +103,9 @@ void encode_line(in SliceContext sc, readonly uimage2D img, 
uint state_off,
                  uint8_t quant_table_idx, in int run_index)
 {
     int w = sc.slice_dim.x;
+#ifdef BAYER
+    w >>= 1;
+#endif
 
 #ifndef RGB
     if (p > 0 && p < 3) {
@@ -160,6 +166,9 @@ void encode_line(in SliceContext sc, readonly uimage2D img, 
uint state_off,
                  uint8_t quant_table_idx, inout int run_index)
 {
     int w = sc.slice_dim.x;
+#ifdef BAYER
+    w >>= 1;
+#endif
 
 #ifndef RGB
     if (p > 0 && p < 3) {
@@ -301,6 +310,41 @@ void preload_rgb(uint slice_idx, in SliceContext sc, ivec2 
sp, int w, int y,
     memoryBarrierImage();
     barrier();
 }
+
+#ifdef BAYER
+void preload_bayer(in SliceContext sc, ivec2 sp, int w, int y, bool apply_rct)
+{
+    int offset = rct_offset;
+
+    for (uint x = gl_LocalInvocationID.x; x < w; x += gl_WorkGroupSize.x) {
+        ivec2 lpos = sp + LADDR(ivec2(x, y));
+        ivec2 src_pos = sc.slice_pos + ivec2(int(x) << 1, y << 1);
+
+        int r  = int(imageLoad(src[0], src_pos + ivec2(0, 0))[0]);
+        int gr = int(imageLoad(src[0], src_pos + ivec2(1, 0))[0]);
+        int gb = int(imageLoad(src[0], src_pos + ivec2(0, 1))[0]);
+        int b  = int(imageLoad(src[0], src_pos + ivec2(1, 1))[0]);
+
+        if (apply_rct) {
+            int gd = gr - gb;
+            int gm = gb + (gd >> 1);
+            b -= gm;
+            r -= gm;
+            gm += (b*sc.slice_rct_coef.g + r*sc.slice_rct_coef.r) >> 2;
+            b += offset;
+            r += offset;
+            gd += offset;
+            gr = gm;
+            gb = gd;
+        }
+
+        imageStore(tmp, lpos, ivec4(gr, gb, b, r));
+    }
+
+    memoryBarrierImage();
+    barrier();
+}
+#endif
 #endif
 
 void encode_slice(in SliceContext sc, uint slice_idx)
@@ -308,13 +352,39 @@ void encode_slice(in SliceContext sc, uint slice_idx)
     ivec2 sp = sc.slice_pos;
     u16vec4 bits = get_slice_bits(sc);
 
-#ifdef RGB
+#ifdef BAYER
+    int bayer_w = sc.slice_dim.x >> 1;
+    int bayer_h = sc.slice_dim.y >> 1;
+    sp.x >>= 1;
+    sp.y = int(gl_WorkGroupID.y)*rgb_linecache;
+    /* c_bits = bps + 1 for is_rgb pixfmts (Bayer is treated as RGB). gm uses
+     * raw bps; gd/b-gm/r-gm need an extra bit for the RCT difference. PCM
+     * stores raw samples so all planes use bps. */
+    if (sc.slice_coding_mode == 0)
+        bits = u16vec4(c_bits - 1, c_bits, c_bits, c_bits);
+    else
+        bits = u16vec4(c_bits - 1, c_bits - 1, c_bits - 1, c_bits - 1);
+#elif defined(RGB)
     sp.y = int(gl_WorkGroupID.y)*rgb_linecache;
 #endif
 
 #ifndef GOLOMB
     if (force_pcm) {
-#ifndef RGB
+#ifdef BAYER
+        for (int y = 0; y < bayer_h; y++) {
+            preload_bayer(sc, sp, bayer_w, y, false);
+
+            for (uint c = 0; c < 4; c++)
+                encode_line_pcm(sc, tmp, sp, y, 0, c);
+        }
+#elif defined(RGB)
+        for (int y = 0; y < sc.slice_dim.y; y++) {
+            preload_rgb(slice_idx, sc, sp, sc.slice_dim.x, y, false);
+
+            for (uint c = 0; c < color_planes; c++)
+                encode_line_pcm(sc, tmp, sp, y, 0, rgb_plane_order[c]);
+        }
+#else
         for (int c = 0; c < color_planes; c++) {
 
             int h = sc.slice_dim.y;
@@ -328,27 +398,45 @@ void encode_slice(in SliceContext sc, uint slice_idx)
             for (int y = 0; y < h; y++)
                 encode_line_pcm(sc, src[p], sp, y, p, comp);
         }
-#else
-        for (int y = 0; y < sc.slice_dim.y; y++) {
-            preload_rgb(slice_idx, sc, sp, sc.slice_dim.x, y, false);
-
-            for (uint c = 0; c < color_planes; c++)
-                encode_line_pcm(sc, tmp, sp, y, 0, rgb_plane_order[c]);
-        }
 #endif
         return;
     }
 #endif
 
+#ifdef BAYER
+    u32vec4 slice_state_off = (slice_idx*codec_planes +
+                               uvec4(0, 2, 1, 1))*plane_state_size;
+#else
     u32vec4 slice_state_off = (slice_idx*codec_planes +
                                uvec4(0, 1, 1, 2))*plane_state_size;
+#endif
 
 #ifdef GOLOMB
     slice_state_off >>= 3;
     init_golomb();
 #endif
 
-#ifndef RGB
+#ifdef BAYER
+    int run_index = 0;
+    for (int y = 0; y < bayer_h; y++) {
+        preload_bayer(sc, sp, bayer_w, y, true);
+
+        for (uint c = 0; c < 4; c++)
+            encode_line(sc, tmp, slice_state_off[c],
+                        sp, y, 0, c, bits[c],
+                        U8(context_model), run_index);
+    }
+#elif defined(RGB)
+    int run_index = 0;
+    for (int y = 0; y < sc.slice_dim.y; y++) {
+        preload_rgb(slice_idx, sc, sp, sc.slice_dim.x, y, true);
+
+        for (uint c = 0; c < color_planes; c++)
+            encode_line(sc, tmp, slice_state_off[c],
+                        sp, y, 0, rgb_plane_order[c], bits[c],
+                        U8(context_model), run_index);
+    }
+#else
     for (uint c = 0; c < color_planes; c++) {
         int run_index = 0;
 
@@ -363,16 +451,6 @@ void encode_slice(in SliceContext sc, uint slice_idx)
             encode_line(sc, src[p], slice_state_off[c], sp, y, p,
                         comp, bits[c], U8(context_model), run_index);
     }
-#else
-    int run_index = 0;
-    for (int y = 0; y < sc.slice_dim.y; y++) {
-        preload_rgb(slice_idx, sc, sp, sc.slice_dim.x, y, true);
-
-        for (uint c = 0; c < color_planes; c++)
-            encode_line(sc, tmp, slice_state_off[c],
-                        sp, y, 0, rgb_plane_order[c], bits[c],
-                        U8(context_model), run_index);
-    }
 #endif
 }
 
diff --git a/libavcodec/vulkan/ffv1_enc_rgb.comp.glsl 
b/libavcodec/vulkan/ffv1_enc_bayer.comp.glsl
similarity index 98%
copy from libavcodec/vulkan/ffv1_enc_rgb.comp.glsl
copy to libavcodec/vulkan/ffv1_enc_bayer.comp.glsl
index 90d136be1f..fc463795f2 100644
--- a/libavcodec/vulkan/ffv1_enc_rgb.comp.glsl
+++ b/libavcodec/vulkan/ffv1_enc_bayer.comp.glsl
@@ -27,4 +27,5 @@
 layout (set = 1, binding = 4) uniform uimage2D tmp;
 
 #define RGB
+#define BAYER
 #include "ffv1_enc.comp.glsl"
diff --git a/libavcodec/vulkan/ffv1_enc_rgb_float.comp.glsl 
b/libavcodec/vulkan/ffv1_enc_bayer_golomb.comp.glsl
similarity index 97%
copy from libavcodec/vulkan/ffv1_enc_rgb_float.comp.glsl
copy to libavcodec/vulkan/ffv1_enc_bayer_golomb.comp.glsl
index c66440601a..3c49fac3b7 100644
--- a/libavcodec/vulkan/ffv1_enc_rgb_float.comp.glsl
+++ b/libavcodec/vulkan/ffv1_enc_bayer_golomb.comp.glsl
@@ -26,6 +26,7 @@
 
 layout (set = 1, binding = 4) uniform uimage2D tmp;
 
-#define FLOAT
 #define RGB
+#define BAYER
+#define GOLOMB
 #include "ffv1_enc.comp.glsl"
diff --git a/libavcodec/vulkan/ffv1_enc_setup.comp.glsl 
b/libavcodec/vulkan/ffv1_enc_setup.comp.glsl
index f1db2aed8a..8b6b057e1c 100644
--- a/libavcodec/vulkan/ffv1_enc_setup.comp.glsl
+++ b/libavcodec/vulkan/ffv1_enc_setup.comp.glsl
@@ -252,17 +252,19 @@ void write_slice_header(uint slice_idx, inout 
SliceContext sc)
     if (version >= 4) {
         put_rac(rc_state[0], force_pcm);
         put_usymbol(uint(force_pcm), 0);
-        if (!force_pcm && colorspace == 1) {
+        if (!force_pcm && colorspace != 0) {
             put_usymbol(sc.slice_rct_coef.g, 0);
             put_usymbol(sc.slice_rct_coef.r, 0);
         }
 
-        if (remap_mode != 0) {
+        if (micro_version >= 4) {
             put_usymbol(remap_mode, 0);
-            if (c_bits >= 32)
-                encode_float32_remap(slice_idx, sc);
-            else
-                encode_histogram_remap(slice_idx, sc);
+            if (remap_mode != 0) {
+                if (c_bits >= 32)
+                    encode_float32_remap(slice_idx, sc);
+                else
+                    encode_histogram_remap(slice_idx, sc);
+            }
         }
     }
 }

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to