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]
