pinterf/FFT3dGPU

FR: Add VapourSynth interface

Opened this issue · 6 comments

A comparable plugin for VapourSynth seems not to exist yet. So a dual interface DLL would surely be interesting for people comparing AviSynth with VapourSynth or writing applications which try to support both simultaneously (like Selur's Hybrid).

Are you sure that this plugin is doing something differently/quicker than the fully rewritten Neo FFT3dFilter?
(Yes, I'm trying to find reasons why not to do that :) )

Alright, Selur is discussing just that in the German Gleitz forum, I will tell him to tell his opinion here, he may agree to abandon this request...

My opinion can be changed when later in this year I have more time than now and after doing my first VS conversion/addition it proves to be a quick and easy one. I think there was already another plugin I was requested to do this task but postponed for similar reasons.

Selur commented

I did some testing:

FFMS2 + NeoFFT3DFilter:

# Imports
import vapoursynth as vs
# getting Vapoursynth core
import ctypes
# Loading Support Files
Dllref = ctypes.windll.LoadLibrary("i:/Hybrid/64bit/vsfilters/Support/libfftw3f-3.dll")
core = vs.core

# Loading Plugins
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/DenoiseFilter/NEO_FFT3DFilter/neo-fft3d.dll")
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")

# source: 'G:\TestClips&Co\files\MPEG-4 H.264\4k\4k_sample_4096x2160.mp4'
# current color space: YUV420P8, bit depth: 8, resolution: 4096x2160, fps: 25, color matrix: 2020ncl, yuv luminance scale: limited, scanorder: progressive
# Loading source using FFMS2
clip = core.ffms2.Source(source="G:/TestClips&Co/files/MPEG-4 H.264/4k/4k_sample_4096x2160.mp4",cachefile="E:/Temp/mp4_b30946f06bbf6d3e0309b51cccf4cf0c_853323747.ffindex",format=vs.YUV420P8,alpha=False)

# Setting color matrix to 2020ncl.
clip = core.std.SetFrameProps(clip, _Matrix=9)
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=9)
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=9)

# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)

# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)

# denoising using Neo-FFT3D
clip = core.neo_fft3d.FFT3D(clip=clip, bw=64, bh=64)

# set output frame rate to 25.000fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)

# Output
clip.set_output()

used 50-65% ​CPU, ~12GB RAM with VSPipe and gives

Output 6262 frames in 1796.79 seconds (3.49 fps)​

using FFMS2 without filtering, speed is way higher

Output 6262 frames in 42.96 seconds (145.75 fps)

usind FFMS2 + Avisynth with FFT3DGPU:

# Imports
import vapoursynth as vs
# getting Vapoursynth core
import ctypes
# Loading Support Files

Dllref = ctypes.windll.LoadLibrary("i:/Hybrid/64bit/vsfilters/Support/libfftw3f-3.dll")
Dllref = ctypes.windll.LoadLibrary("i:/Hybrid/64bit/Avisynth/avisynthPlugins/d3d9.dll")

# getting Vapoursynth core
core = vs.core
# Loading Plugins
core.std.LoadPlugin(path="i:/Hybrid/64bit/vsfilters/SourceFilter/FFMS2/ffms2.dll")
core.std.LoadPlugin(path="I:/Hybrid/64bit/Vapoursynth/Vapoursynth64/coreplugins/AvsCompat.dll")
core.avs.LoadPlugin(path="i:/Hybrid/64bit/Avisynth/avisynthPlugins/FFT3dGPU.dll")

# source: 'G:\TestClips&Co\files\MPEG-4 H.264\4k\4k_sample_4096x2160.mp4'
# current color space: YUV420P8, bit depth: 8, resolution: 4096x2160, fps: 25, color matrix: 2020ncl, yuv luminance scale: limited, scanorder: progressive
# Loading source using FFMS2
clip = core.ffms2.Source(source="G:/TestClips&Co/files/MPEG-4 H.264/4k/4k_sample_4096x2160.mp4",cachefile="E:/Temp/mp4_b30946f06bbf6d3e0309b51cccf4cf0c_853323747.ffindex",format=vs.YUV420P8,alpha=False)
# Setting color matrix to 2020ncl.
clip = core.std.SetFrameProps(clip, _Matrix=9)
clip = clip if not core.text.FrameProps(clip,'_Transfer') else core.std.SetFrameProps(clip, _Transfer=9)
clip = clip if not core.text.FrameProps(clip,'_Primaries') else core.std.SetFrameProps(clip, _Primaries=9)
# Setting color range to TV (limited) range.
clip = core.std.SetFrameProp(clip=clip, prop="_ColorRange", intval=1)
# making sure frame rate is set to 25
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)

# Use FFT3DGPU
clip = core.avs.fft3dGPU(clip, bw=64, bh=64,precision=1)

# set output frame rate to 25.000fps
clip = core.std.AssumeFPS(clip=clip, fpsnum=25, fpsden=1)
# Output
clip.set_output()

I needed to use precision=1.

precision=0 produces artifacts, even when using 64bit Avisynth+ with FFT3DGPU and 4k input.
(as as side note: using Avisynth+ with FFMS2 fft3dGPU(clip, bw=64, bh=64,precision=1) I get an the same speed fps)
This gave me:

Output 6262 frames in 400.78 seconds (15.62 fps)

(precision=2 gives me 15.4fps, so roughly the same)

Since NeoFFT3DFilter also has mt an ncpu, I also tried mt=True and different ncpu values but I couldn't get it faster than 3.5fps

I also tried different source filters (LibavSMASHSource, LWLibavSource with and without hardware accelleration and DGDecNV), with FFT3DGPU and neo_fft3d.FFT3D.
-> speed didn't change.

So yes, FFT3DGPU at least here is a lot faster than 'neo_fft3d.FFT3D(clip=clip, bw=64, bh=64)' and cpu usage is only ~3.5%.

My system is: Windows 11, 32GB RAM, Ryzen 9 3850X, Geforce GTX 1070ti, Vapoursynth R57. (so with newer gpus the speed of FFT3DGPU might even be higher)

Yes, the difference is significant.
(Myrsloik has another fft3dfilter version which - if I remember well - was comparable or better than neo's numbers.)

Selur commented

Tried that one too :) and it's basically the same speed as the neo version, also can't get it faster than 3.5fps.