Change log
v1.3 (20261030)
Bug fixes
- RemoveGrain, Repair, VerticalCleaner: crash (memory corruption, also hangs) on planes of 1 row, and VerticalCleaner
mode 2 on planes of 2-3 rows (e.g. the chroma of a 2 or 4 row high 4:2:0 clip). A plane without an inner row is
copied now. Existed since 2013. - RemoveGrain modes 13-16 (field interpolation), all code paths: with an odd plane height one row was not written
(random content): the last row (modes 13, 15) or the last odd row (modes 14, 16), e.g. the 4:2:0 chroma of
720x486. Existed since 2013. - RemoveGrain, Repair (SSE2/SSE4.1/AVX2): wrong left border pixel, depending on memory content, when a plane is
exactly one vector + 1 pixel wide (8 bit: 17 or 33, 10-16 bit: 9 or 17, float: 5 or 9 pixels; e.g. the 4:2:0
chroma of a 34 or 66 pixel wide clip). Existed since 2013. - RemoveGrain, Repair, TemporalRepair modes 1-3 (SSE2/SSE4.1, RemoveGrain also AVX2): with a plane width of a multiple
of the vector size, the last vector of a row read one pixel past the end of the row, in the last row past the end of the frame
(possible access violation). The output was not affected. Existed since 2013. - TemporalRepair modes 1-3 (SSE2/SSE4.1): the right border column was overwritten when the row was a multiple of
16 bytes (e.g. the 4:2:2 chroma of a 64 pixel wide clip). Existed since v0.98. - Repair: wrong output with a reference clip of a different frame pitch (e.g. a cropped reference) on the C code
path (CPUs without SSE2, opt=1, planes narrower than 17 pixels). Existed since 2013. - Repair: the two clips must have the same bit depth and color family also when chroma is not processed (Y clips,
modeU=modeV=-1); was accepted with wrong output and reads past the reference rows. Existed since v0.93. - ForwardClense, BackwardClense, 32 bit float YUV: negative chroma (U, V) was clipped to 0. Existed since the 32 bit
float support. - Clense, ForwardClense, BackwardClense: with grey=true the alpha plane is copied (was random content). Existed
since v0.93. - VerticalCleaner: a mode below -1 is an error (was accepted: undefined behaviour, possible crash). Existed since
2013. - RemoveGrain mode 6, 32 bit float, SSE4.1 (opt=3, or auto on CPUs without AVX2): the costs were not clamped at
1.0 as on the other code paths; the result could differ. Existed since the float support. - RemoveGrain mode 25, 10-14 bit, C code path: the result could differ from SIMD for some pixel patterns.
Existed since the 10-16 bit support.
Changes
- RemoveGrain mode 11 on SSE2/SSE4.1/AVX2 (the x86 default): the exact (1 2 1)/16 kernel as documented and as the C
code, (4c + 2(a2+a4+a5+a7) + a1+a3+a6+a8 + 8) / 16. Before, it ran the mode 12 approximation (difference
at most 1). Mode 12 stays the faster approximation. - RemoveGrain C code path (opt=1, CPUs without SSE2, very narrow planes): modes 12, 15, 16, 19 and 20 give the same
result as SIMD (they differed by up to 1, in float in the last bits). All code paths give the same result now. - YUY2 and packed RGB give an error also with planar=true ("use ConvertToYV16"). Before, planar=true skipped the
format check and a YUY2 clip was processed as one plane. - The "Invalid memory alignment. Unaligned crop?" errors are removed: AviSynth+ frames are always aligned
(classic AviSynth 2.6: use an aligned crop).
New
- aarch64 NEON for all filters and bit depths (Linux, Windows on ARM64), the same result as C. Used when the host
reports NEON (AviSynth+: CPUF_ARM_NEON; SetMaxCPU("none") gives C). opt on aarch64: RemoveGrain, Repair: 1 = C,
any other value NEON; TemporalRepair: 0 = C, any other value NEON. - The AviSynth+ V13 formats: YUV 4:1:1 at all bit depths, 4:4:0, 4:1:0 (with or without alpha) and YA (Y with alpha;
the alpha plane is copied). - Documentation: all filters, modes and parameters in README.md; Expr equivalents of some RemoveGrain modes.
Performance
- The row copies of the plane borders use memcpy instead of the AviSynth BitBlt.
- AVX2 (RemoveGrain): no manual vzeroupper (the compilers insert it; with Clang it caused saving and restoring all
vector registers in every plane function).
Build environment
- Visual Studio 2026 solution (RgTools.slnx: Release with the v145 toolset, Rel_Clang with ClangCL); RgTools.sln
(Visual Studio 2022) only for the v141_xp build (Windows XP and 7). The old separate LLVM configurations are removed. - CMake: rewritten (AviSynth+ style); detects x86 and aarch64 (NEON); a plain C build is possible
(ENABLE_INTEL_SIMD=OFF). GCC, Clang, MSVC: no warnings. - Windows on ARM64 DLL (llvm-mingw cross build, build_arm64_mingw.bat); release pack script (build_release.bat).
- AviSynth headers updated to the V14 interface.
- Core test program (tests/core_test.cpp, CMake option RGTOOLS_BUILD_TESTS): SIMD vs C at all bit depths, also
under AddressSanitizer / UBSan and on aarch64 (qemu).
Source
- The filter cores are separated from the AviSynth interface (*_core.cpp; prepares other front ends, e.g.
VapourSynth). The x86, aarch64 and C code are in separate files. - One 10-16 bit code path instead of separate 10, 12, 14 and 16 bit templates (also usable for 9-15 bit).
Note: the v1.3 work (bug hunt, NEON port, core separation, build, tests, documentation) was done with AI
assistance (Claude Code, Anthropic), reviewed and tested by pinterf.