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

Git pushed a commit to branch master
in repository ffmpeg.

commit a1679b5c850c027fab5930aea25dbd2948297c5f
Author:     Lynne <[email protected]>
AuthorDate: Sun Sep 27 01:20:26 2026 +0900
Commit:     Lynne <[email protected]>
CommitDate: Sat Oct 3 12:15:47 2026 +0900

    ffv1enc_vulkan: code each symbol in code specialised for its exponent
    
    A symbol was coded by loops over its unary prefix and its mantissa,
    reading every state from its invocation just before its decision and
    updating it right after.
    
    Each exponent now has its own straight-line code, reached through a
    small branch tree, which reads all the states the symbol uses from
    their invocations up front, so the chain of decisions never waits on
    them. Once the symbol is coded, all invocations adapt their state at
    once, from masks of the states the symbol used and of the decisions
    that were ones. Escaped symbols adapt the two states they repeat in
    scalar registers. The renormalisation check stays a branch instead of
    being turned into selects.
    
    The output is unchanged. Encoding a 6464x4852 16-bit RGB frame with
    1024 slices on an RX 6900 XT, with the frame in VRAM, goes from
    170.1/144.8 ms to 126.6/101.6 ms with context model 1/0.
---
 libavcodec/vulkan/ffv1_enc.comp.glsl       |  23 +++++-
 libavcodec/vulkan/rangecoder_subgroup.glsl | 115 +++++++++++++++++++++++------
 2 files changed, 112 insertions(+), 26 deletions(-)

diff --git a/libavcodec/vulkan/ffv1_enc.comp.glsl 
b/libavcodec/vulkan/ffv1_enc.comp.glsl
index 050a45efef..3e46a7f838 100644
--- a/libavcodec/vulkan/ffv1_enc.comp.glsl
+++ b/libavcodec/vulkan/ffv1_enc.comp.glsl
@@ -114,11 +114,26 @@ void encode_line(in SliceContext sc, readonly uimage2D 
img, uint state_off,
 
         d[1] = fold(d[1], bits);
 
-        uint rc_off = state_off + CONTEXT_SIZE*d[0] + gl_LocalInvocationID.x;
-
+        uint lane = gl_SubgroupInvocationID;
+        uint rc_off = state_off + CONTEXT_SIZE*d[0] + lane;
         uint st = slice_rc_state[rc_off];
-        put_isymbol(st, d[1]);
-        slice_rc_state[rc_off] = uint8_t(st);
+
+        uint ad = abs(d[1]);
+        int e = findMSB(ad);
+        int ec = clamp(e, 0, 9);
+        int es = 11 + min(e, 10);
+        uint used = d[1] == 0 ? 1u : 1u | ((4u << ec) - 2u) | (((1u << ec) - 
1u) << 22) | (1u << es);
+        uint ones = d[1] == 0 ? 1u : ((2u << ec) - 2u) | ((ad & ((1u << ec) - 
1u)) << 22) |
+                                     (uint(d[1] < 0) << es);
+        uint nst = zero_one_state[(bitfieldExtract(ones, int(lane), 1) << 8) + 
st];
+
+        uint s10, s31;
+        put_isymbol(st, d[1], s10, s31);
+
+        uint adapted = bitfieldExtract(used, int(lane), 1) != 0 ? nst : st;
+        if (ad >= 1024)
+            adapted = lane == 10 ? s10 : lane == 31 ? s31 : adapted;
+        slice_rc_state[rc_off] = uint8_t(adapted);
         linecache_next(cur);
         if (rc_nev > 42)
             rac_emit();
diff --git a/libavcodec/vulkan/rangecoder_subgroup.glsl 
b/libavcodec/vulkan/rangecoder_subgroup.glsl
index 94406bbea9..c9ccaf74ce 100644
--- a/libavcodec/vulkan/rangecoder_subgroup.glsl
+++ b/libavcodec/vulkan/rangecoder_subgroup.glsl
@@ -143,7 +143,7 @@ void put_rac_range1(uint range1, bool bit)
 {
     rc_top = bit ? rc_top : rc_top - range1;
     rc.range = bit ? range1 : rc.range - range1;
-    if (rc.range < 0x100)
+    [[dont_flatten]] if (rc.range < 0x100)
         rac_renorm_enc();
 }
 
@@ -181,43 +181,114 @@ uint rac_terminate(void)
     return rc.bs_off - rc.bs_start;
 }
 
-void put_rac_state(inout uint st, uint i, bool bit)
+void put_isymbol_tail(int e, uint st24, uint a, bool neg)
 {
-    uint s = subgroupBroadcast(st, i);
-    put_rac(s << 24, bit);
-    uint ns = uint(zero_one_state[(uint(bit) << 8) + s]);
-    st = gl_SubgroupInvocationID == i ? ns : st;
+    uint s[21];
+    [[unroll]] for (int i = 0; i < 11; i++)
+        if (i <= e + 1)
+            s[i] = subgroupBroadcast(st24, i);
+    [[unroll]] for (int i = 0; i < 9; i++)
+        if (i < e)
+            s[11 + i] = subgroupBroadcast(st24, 22 + i);
+    s[20] = subgroupBroadcast(st24, 11 + e);
+
+    put_rac(s[0], false);
+    [[unroll]] for (int i = 0; i < 9; i++)
+        if (i < e)
+            put_rac(s[1 + i], true);
+    put_rac(s[1 + e], false);
+    [[unroll]] for (int i = 8; i >= 0; i--)
+        if (i < e)
+            put_rac(s[11 + i], bitfieldExtract(a, i, 1) != 0);
+    put_rac(s[20], neg);
 }
 
-void put_isymbol(inout uint st, int v)
+void put_isymbol_esc(int e, uint st, uint a, bool neg, out uint s10, out uint 
s31)
 {
-    put_rac_state(st, 0, v == 0);
-    if (v == 0)
-        return;
-
-    uint a = abs(v);
-    int e = findMSB(a);
+    uint st24 = st << 24;
+    uint s[10];
+    [[unroll]] for (int i = 0; i < 10; i++)
+        s[i] = subgroupBroadcast(st24, i);
+    s10 = subgroupBroadcast(st, 10);
+    s31 = subgroupBroadcast(st, 31);
+    put_rac(s[0], false);
+    [[unroll]] for (int i = 1; i < 10; i++)
+        put_rac(s[i], true);
+    if (rc_nev > 40)
+        rac_emit();
 
-    for (int i = 0; i < min(e, 9); i++)
-        put_rac_state(st, 1 + i, true);
     for (int i = 9; i < e; i++) {
-        put_rac_state(st, 10, true);
+        uint nx = rangecoder_state[256 + s10];
+        put_rac(s10 << 24, true);
         if (rc_nev > 60)
             rac_emit();
+        s10 = nx;
     }
-    put_rac_state(st, 1 + min(e, 9), false);
+    uint nx = rangecoder_state[s10];
+    put_rac(s10 << 24, false);
+    s10 = nx;
 
     for (int i = e - 1; i >= 9; i--) {
-        put_rac_state(st, 31, bitfieldExtract(a, i, 1) != 0);
+        bool b = bitfieldExtract(a, i, 1) != 0;
+        uint n0 = rangecoder_state[s31];
+        uint n1 = rangecoder_state[256 + s31];
+        put_rac(s31 << 24, b);
         if (rc_nev > 60)
             rac_emit();
+        s31 = b ? n1 : n0;
     }
-    if (e > 9 && rc_nev > 50)
+    if (rc_nev > 50)
         rac_emit();
-    for (int i = min(e, 9) - 1; i >= 0; i--)
-        put_rac_state(st, 22 + i, bitfieldExtract(a, i, 1) != 0);
 
-    put_rac_state(st, 11 + min(e, 10), v < 0);
+    [[unroll]] for (int i = 8; i >= 0; i--)
+        s[i] = subgroupBroadcast(st24, 22 + i);
+    uint ss = subgroupBroadcast(st24, 21);
+    [[unroll]] for (int i = 8; i >= 0; i--)
+        put_rac(s[i], bitfieldExtract(a, i, 1) != 0);
+    put_rac(ss, neg);
+}
+
+void put_isymbol(uint st, int v, out uint s10, out uint s31)
+{
+    uint st24 = st << 24;
+    uint a = abs(v);
+    int e = findMSB(a);
+    bool neg = v < 0;
+    s10 = 0;
+    s31 = 0;
+
+    if (v != 0) {
+        if (e < 4) {
+            if (e < 2) {
+                if (e == 1)
+                    put_isymbol_tail(1, st24, a, neg);
+                else
+                    put_isymbol_tail(0, st24, a, neg);
+            } else if (e == 3) {
+                put_isymbol_tail(3, st24, a, neg);
+            } else {
+                put_isymbol_tail(2, st24, a, neg);
+            }
+        } else if (e < 7) {
+            if (e == 4)
+                put_isymbol_tail(4, st24, a, neg);
+            else if (e == 5)
+                put_isymbol_tail(5, st24, a, neg);
+            else
+                put_isymbol_tail(6, st24, a, neg);
+        } else if (e < 10) {
+            if (e == 7)
+                put_isymbol_tail(7, st24, a, neg);
+            else if (e == 8)
+                put_isymbol_tail(8, st24, a, neg);
+            else
+                put_isymbol_tail(9, st24, a, neg);
+        } else {
+            put_isymbol_esc(e, st, a, neg, s10, s31);
+        }
+    } else {
+        put_rac(subgroupBroadcast(st24, 0), true);
+    }
 }
 #endif
 

-- 
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