This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit cf2f8fc5a2a8dc4a1b490bab99ef0f6019222f2d Author: Lynne <[email protected]> AuthorDate: Sat Nov 7 17:38:00 2026 +0800 Commit: Lynne <[email protected]> CommitDate: Sat Nov 7 22:20:30 2026 +0800 avfilter/vf_bwdif_vulkan: make bwdif's decisions on whole sample values bwdif treats a sample as still when its halved temporal differences, rounded down, are all 0, so a change of one step counts as none. And it interpolates from the current field alone unless abs(c - e) is above temporal_diff0. The shader works on floats, which aren't exact and whose halves aren't rounded down, so both decisions could go the other way: after the previous commit, still 1-row stripes with a step of noise were off by up to 1022, and moving pictures by up to 338. Pass the size of a step to the shader, and put both thresholds halfway between the integer outcomes. Float formats have no steps and keep the plain comparisons. On moving, edge and still striped pictures in yuv420p, yuv422p10, yuv444p12, gbrp10, NV12 and P010, with both field orders and both modes, the output now matches bwdif within a code everywhere, on an RX 6900 XT and on lavapipe. Fixes: #25106 Reported-by: oittaa --- libavfilter/vf_bwdif_vulkan.c | 3 ++- libavfilter/vulkan/bwdif.comp.glsl | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c index 9afd9ae409..0fd0255c4d 100644 --- a/libavfilter/vf_bwdif_vulkan.c +++ b/libavfilter/vf_bwdif_vulkan.c @@ -80,10 +80,11 @@ static av_cold int init_filter(AVFilterContext *ctx) clip_max = ((1 << desc->comp[0].depth) - 1) * unit; } - SPEC_LIST_CREATE(sl, 3, 2*sizeof(int) + sizeof(float)) + SPEC_LIST_CREATE(sl, 4, 2*sizeof(int) + 2*sizeof(float)) SPEC_LIST_ADD(sl, 0, 32, vkctx->output_height); SPEC_LIST_ADD(sl, 1, 32, AV_CEIL_RSHIFT(vkctx->output_height, desc->log2_chroma_h)); SPEC_LIST_ADD(sl, 2, 32, av_float2int(clip_max)); + SPEC_LIST_ADD(sl, 3, 32, av_float2int(unit)); ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, sl, (uint32_t [3]) { 1, 64, planes }, 0); diff --git a/libavfilter/vulkan/bwdif.comp.glsl b/libavfilter/vulkan/bwdif.comp.glsl index 76d330cf9f..b477be63c4 100644 --- a/libavfilter/vulkan/bwdif.comp.glsl +++ b/libavfilter/vulkan/bwdif.comp.glsl @@ -34,6 +34,11 @@ layout (constant_id = 1) const int chroma_height = 0; /* The largest sample value, which bwdif clips to */ layout (constant_id = 2) const float clip_max = 1.0; +/* bwdif decides on whole sample values. These are floats, which aren't + * exact, so the decisions are made on steps of this size, 0 for float + * formats. */ +layout (constant_id = 3) const float unit = 0.0; + layout (set = 0, binding = 0) uniform writeonly image2D dst[]; layout (set = 0, binding = 1) uniform readonly image2D prev[]; layout (set = 0, binding = 2) uniform readonly image2D cur[]; @@ -80,7 +85,9 @@ vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], vec4 next1[2], vec4 temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2; temp_diff[2] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2; vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2])); - bvec4 diff_mask = equal(diff, vec4(0)); + /* bwdif halves with shifts, so a change of one step is no motion: diff + * is then at most half a step, and otherwise at least one */ + bvec4 diff_mask = lessThanEqual(diff, vec4(unit * 0.75)); vec4 fbs = prev2[1] + next2[1]; vec4 ffs = prev2[3] + next2[3]; @@ -97,7 +104,8 @@ vec4 process_line(vec4 prev2[5], vec4 prev1[2], vec4 cur[4], vec4 next1[2], vec4 coef_lf[0]*(fc + fe) - coef_lf[1]*(cur[0] + cur[3])) / (1 << 13); vec4 interpolate_cur = (coef_sp[0]*(fc + fe) - coef_sp[1]*(cur[0] + cur[3])) / (1 << 13); - bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0]); + /* bwdif takes interpolate_cur when the differences are equal */ + bvec4 interpolate_cnd1 = greaterThan(abs(fc - fe), temp_diff[0] + unit * 0.5); vec4 interpol = mix(interpolate_cur, interpolate_all, interpolate_cnd1); interpol = clamp(interpol, fd - diff, fd + diff); return mix(interpol, fd, diff_mask); @@ -117,7 +125,7 @@ vec4 process_edge(vec4 prev2[3], vec4 prev1[2], vec4 cur[2], vec4 next1[2], vec4 temp_diff[1] = (abs(prev1[0] - fc) + abs(prev1[1] - fe)) / 2; temp_diff[2] = (abs(next1[0] - fc) + abs(next1[1] - fe)) / 2; vec4 diff = max(temp_diff[0] / 2, max(temp_diff[1], temp_diff[2])); - bvec4 diff_mask = equal(diff, vec4(0)); + bvec4 diff_mask = lessThanEqual(diff, vec4(unit * 0.75)); if (spat) { vec4 fb = (prev2[0] + next2[0]) / 2 - fc; -- 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]
