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]
