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

Git pushed a commit to branch master
in repository ffmpeg.

commit a9054d015e107a7f56dbc5e350cd93c0ca91a701
Author:     Lynne <[email protected]>
AuthorDate: Sat Sep 26 15:36:17 2026 +0900
Commit:     Lynne <[email protected]>
CommitDate: Sat Oct 3 12:15:46 2026 +0900

    vulkan_ffv1: overlap the state load of the next sample with the current one
    
    The context of the next sample, and with it the load of its states, are
    issued as soon as the value is known, before the states of the current
    sample are adapted and written back, and the states are forwarded when
    both samples use the same context. The renormalisation left over by the
    sign decision moves behind the load.
    
    The parts of the context and of the predictor that only depend on the
    row above are computed 32 samples at a time, one per invocation, with
    the row of the next chunk loaded during the current one, and decoded
    samples are written once per chunk. The median predictor becomes a
    clamp of the sample above between bounds computed per chunk.
    
    Decoding a 6464x4852 16-bit RGB frame with 1024 slices on an RX 6900
    XT, with the bitstream in VRAM, goes from 99.1/72.4/69.8 ms to
    53.5/45.2/44.7 ms with context model 1/0/2.
---
 libavcodec/vulkan/ffv1_dec.comp.glsl | 99 +++++++++++++++++++++++++-----------
 1 file changed, 70 insertions(+), 29 deletions(-)

diff --git a/libavcodec/vulkan/ffv1_dec.comp.glsl 
b/libavcodec/vulkan/ffv1_dec.comp.glsl
index c5b276b6b8..6ad7f3846b 100644
--- a/libavcodec/vulkan/ffv1_dec.comp.glsl
+++ b/libavcodec/vulkan/ffv1_dec.comp.glsl
@@ -83,44 +83,85 @@ void decode_line(ivec2 sp, int w,
     }
 #endif
 
+    bool ext = extend_lookup[quant_table_idx];
     linecache_load(dec[p], sp, y, 0);
 
-    bool ext = extend_lookup[quant_table_idx];
+    ivec3 top = subgroupBroadcast(get_pred_top(dec[p], sp, ivec2(0, y), 0, w,
+                                               quant_table_idx, ext), 0u);
+    ivec2 pr = get_pred_left(top, quant_table_idx, ext);
+    int c = pr[0];
+    int pred = pr[1];
+    int sgn = c < 0 ? -1 : 1;
+    int tl = top.y;
+    int l = linecache[1];
+    uint ctx = abs(c);
+    uint sbase = state_off + gl_LocalInvocationID.x;
+    uint soff = sbase + CONTEXT_SIZE*ctx;
+    uint ld = slice_rc_state[soff];
+    uint8_t adapted = uint8_t(0);
+    bool same = false;
+    uint row = 0;
     ivec2 qthr = quant_ballot ? 
quant_thresh[quant_table_idx][gl_LocalInvocationID.x] : ivec2(0);
     ivec2 qso = quant_ballot ? quant_scale_off[quant_table_idx] : ivec2(0);
-    uint sbase = state_off + gl_LocalInvocationID.x;
 
-    for (int x = 0; x < w; x++) {
-        ivec2 pr;
-        if (quant_ballot) {
-            ivec3 top = get_pred_top(dec[p], sp, ivec2(x, y), 0, w, 
quant_table_idx, ext);
-            TYPE cur = linecache[1];
-            uvec4 q0 = subgroupBallot(int(int8_t(cur - top[0])) >= qthr.x);
-            uvec4 q3 = subgroupBallot(ext && int(int8_t(linecache[0] - cur)) 
>= qthr.y);
-            pr = ivec2(top[2] + qso.y + int(subgroupBallotBitCount(q0)) +
-                       qso.x*int(subgroupBallotBitCount(q3)),
-                       predict(cur, top.xy));
-        } else {
-            pr = get_pred(dec[p], sp, ivec2(x, y), 0, w, quant_table_idx, ext);
-        }
+    ivec4 tr = get_top(dec[p], sp, ivec2(min(1 + int(gl_LocalInvocationID.x), 
w - 1), y),
+                       0, w, ext);
+    for (int x = 0; x < w; x += 32) {
+        ivec3 tn = get_pred_top_quant(tr, quant_table_idx, ext);
+        tn.z += qso.y;
+        tr = get_top(dec[p], sp, ivec2(min(x + 33 + 
int(gl_LocalInvocationID.x), w - 1), y),
+                     0, w, ext);
+        int gmin = min(tn.y - tn.x, 0);
+        int gmax = max(tn.y - tn.x, 0);
+        int n = min(w - x, 32);
 
-        int sgn = pr[0] < 0 ? -1 : 1;
-        uint soff = sbase + CONTEXT_SIZE*abs(pr[0]);
-        uint st = slice_rc_state[soff];
+        int j = 0;
+        do {
+            uint st = same ? uint(adapted) : ld;
+            int base = subgroupBroadcast(tn.z, j);
+            int t = subgroupBroadcast(tn.y, j);
 
-        uint used, used_bits;
-        int v = get_isymbol(st, pr[1], sgn, used, used_bits);
-        rac_renorm();
-        uint vz = zero_extend(v, bits);
-        rac_check_window();
+            uint used, used_bits;
+            int v = get_isymbol(st, pred, sgn, used, used_bits);
+            uint vz = zero_extend(v, bits);
+#ifdef FLOAT
+            v = int(vz);
+#endif
 
-        if (subgroupInverseBallot(uvec4(used, 0, 0, 0)))
-            slice_rc_state[soff] =
-                zero_one_state[st + (subgroupInverseBallot(uvec4(used_bits, 0, 
0, 0)) ? 256 : 0)];
+            if (quant_ballot) {
+                uvec4 q0 = subgroupBallot(int(int8_t(v - tl)) >= qthr.x);
+                uvec4 q3 = subgroupBallot(ext && int(int8_t(l - v)) >= qthr.y);
+                c = base + int(subgroupBallotBitCount(q0)) + 
qso.x*int(subgroupBallotBitCount(q3));
+            } else {
+                c = base + quant_table[quant_table_idx][0][(v - tl) & 
MAX_QUANT_TABLE_MASK];
+                if (ext)
+                    c += quant_table[quant_table_idx][3][(l - v) & 
MAX_QUANT_TABLE_MASK];
+            }
+            uint ctx_prev = ctx;
+            uint soff_prev = soff;
+            ctx = abs(c);
+            soff = sbase + CONTEXT_SIZE*ctx;
+            same = ctx == ctx_prev;
+            if (!same)
+                ld = slice_rc_state[soff];
+            rac_renorm();
+            uint nst = zero_one_state[st + 
(subgroupInverseBallot(uvec4(used_bits, 0, 0, 0)) ? 256 : 0)];
 
-        if (gl_LocalInvocationID.x == 0)
-            imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(vz));
-        linecache_next(TYPE(vz));
+            adapted = uint8_t(subgroupInverseBallot(uvec4(used, 0, 0, 0)) ? 
nst : st);
+            slice_rc_state[soff_prev] = adapted;
+            sgn = c < 0 ? -1 : 1;
+
+            int vm = int(TYPE(vz));
+            pred = subgroupBroadcast(clamp(tn.y, vm + gmin, vm + gmax), j);
+            row = gl_LocalInvocationID.x == j ? vz : row;
+            rac_check_window();
+
+            l = v;
+            tl = t;
+        } while (++j < n);
+
+        if (gl_LocalInvocationID.x < n)
+            imageStore(dec[p], sp + LADDR(ivec2(x + 
int(gl_LocalInvocationID.x), y)), uvec4(row));
     }
 
     memoryBarrierImage();

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to