vapoursynth-vszipcu 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. vapoursynth_vszipcu-1.1.0/.gitignore +24 -0
  2. vapoursynth_vszipcu-1.1.0/LICENSE +21 -0
  3. vapoursynth_vszipcu-1.1.0/PKG-INFO +241 -0
  4. vapoursynth_vszipcu-1.1.0/README.md +231 -0
  5. vapoursynth_vszipcu-1.1.0/build.zig +50 -0
  6. vapoursynth_vszipcu-1.1.0/build.zig.zon +17 -0
  7. vapoursynth_vszipcu-1.1.0/cudaz/LICENSE.md +27 -0
  8. vapoursynth_vszipcu-1.1.0/cudaz/Readme.md +166 -0
  9. vapoursynth_vszipcu-1.1.0/cudaz/build.zig +171 -0
  10. vapoursynth_vszipcu-1.1.0/cudaz/build.zig.zon +35 -0
  11. vapoursynth_vszipcu-1.1.0/cudaz/src/c.zig +9 -0
  12. vapoursynth_vszipcu-1.1.0/cudaz/src/compile.zig +163 -0
  13. vapoursynth_vszipcu-1.1.0/cudaz/src/cufft.zig +264 -0
  14. vapoursynth_vszipcu-1.1.0/cudaz/src/curand.zig +124 -0
  15. vapoursynth_vszipcu-1.1.0/cudaz/src/device.zig +114 -0
  16. vapoursynth_vszipcu-1.1.0/cudaz/src/driver.zig +596 -0
  17. vapoursynth_vszipcu-1.1.0/cudaz/src/dynlib.zig +218 -0
  18. vapoursynth_vszipcu-1.1.0/cudaz/src/error.zig +100 -0
  19. vapoursynth_vszipcu-1.1.0/cudaz/src/launchconfig.zig +15 -0
  20. vapoursynth_vszipcu-1.1.0/cudaz/src/lib.zig +73 -0
  21. vapoursynth_vszipcu-1.1.0/cudaz/src/nvrtc.zig +211 -0
  22. vapoursynth_vszipcu-1.1.0/cudaz/src/path.zig +8 -0
  23. vapoursynth_vszipcu-1.1.0/cudaz/src/rng.zig +46 -0
  24. vapoursynth_vszipcu-1.1.0/cudaz/src/utils.zig +45 -0
  25. vapoursynth_vszipcu-1.1.0/cudaz/src/wrappers.zig +73 -0
  26. vapoursynth_vszipcu-1.1.0/cudaz/test/driver.zig +178 -0
  27. vapoursynth_vszipcu-1.1.0/cudaz/test/general.zig +169 -0
  28. vapoursynth_vszipcu-1.1.0/cudaz/test/rng.zig +12 -0
  29. vapoursynth_vszipcu-1.1.0/cudaz/test/utils.zig +34 -0
  30. vapoursynth_vszipcu-1.1.0/hatch_build.py +199 -0
  31. vapoursynth_vszipcu-1.1.0/pyproject.toml +50 -0
  32. vapoursynth_vszipcu-1.1.0/src/bilateral.zig +653 -0
  33. vapoursynth_vszipcu-1.1.0/src/bm3d.cu +922 -0
  34. vapoursynth_vszipcu-1.1.0/src/bm3d.zig +1501 -0
  35. vapoursynth_vszipcu-1.1.0/src/bm3d_vagg.cu +48 -0
  36. vapoursynth_vszipcu-1.1.0/src/cu.zig +45 -0
  37. vapoursynth_vszipcu-1.1.0/src/deband.cu +199 -0
  38. vapoursynth_vszipcu-1.1.0/src/deband.zig +623 -0
  39. vapoursynth_vszipcu-1.1.0/src/dfttest.cu +2043 -0
  40. vapoursynth_vszipcu-1.1.0/src/dfttest.zig +1221 -0
  41. vapoursynth_vszipcu-1.1.0/src/eedi3.cu +716 -0
  42. vapoursynth_vszipcu-1.1.0/src/eedi3.zig +967 -0
  43. vapoursynth_vszipcu-1.1.0/src/fgrain.cu +169 -0
  44. vapoursynth_vszipcu-1.1.0/src/fgrain.zig +385 -0
  45. vapoursynth_vszipcu-1.1.0/src/framecache.zig +115 -0
  46. vapoursynth_vszipcu-1.1.0/src/gaussblur.cu +167 -0
  47. vapoursynth_vszipcu-1.1.0/src/gaussblur.zig +567 -0
  48. vapoursynth_vszipcu-1.1.0/src/kernel.cu +107 -0
  49. vapoursynth_vszipcu-1.1.0/src/nlmeans.cu +235 -0
  50. vapoursynth_vszipcu-1.1.0/src/nlmeans.zig +893 -0
  51. vapoursynth_vszipcu-1.1.0/src/nnedi3.cu +577 -0
  52. vapoursynth_vszipcu-1.1.0/src/nnedi3.zig +904 -0
  53. vapoursynth_vszipcu-1.1.0/src/nnedi3_weights.bin +0 -0
  54. vapoursynth_vszipcu-1.1.0/src/plugin.zig +128 -0
  55. vapoursynth_vszipcu-1.1.0/src/pool.zig +75 -0
  56. vapoursynth_vszipcu-1.1.0/src/vsutil.zig +60 -0
@@ -0,0 +1,24 @@
1
+ zig-out/
2
+ .zig-cache/
3
+ .vscode/
4
+ run.bat
5
+ build-help/releases.json
6
+ build-help/zig-*
7
+ build-help/*.zip
8
+ build-help/*.tar.xz
9
+ .vsjet/
10
+ prof/
11
+ *.h
12
+ *.cpp
13
+ *.so
14
+ build/
15
+ zig-pkg/
16
+ dev/
17
+
18
+ # Python packaging (hatchling + ziglang wheel build)
19
+ dist/
20
+ vapoursynth/
21
+ __pycache__/
22
+ *.egg-info/
23
+ *.whl
24
+ *.tar.gz
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Julek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: vapoursynth-vszipcu
3
+ Version: 1.1.0
4
+ Summary: VapourSynth Zig Image Process — CUDA
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.12
8
+ Requires-Dist: vapoursynth>=75
9
+ Description-Content-Type: text/markdown
10
+
11
+ # vszipcu
12
+
13
+ VapourSynth CUDA image processing, written in Zig.
14
+
15
+ ## Requirements
16
+
17
+ - An NVIDIA GPU + driver. (Only NNEDI3 cares about the architecture: its tensor-core
18
+ predictor needs sm_80+, and it falls back to an fp32 path automatically below that.)
19
+ - **No CUDA toolkit at runtime.** Released wheels ship NVRTC (`nvrtc64_130_0` /
20
+ `libnvrtc.so.13` + builtins) next to the plugin. The host only needs the NVIDIA driver
21
+ (`nvcuda` / `libcuda`).
22
+
23
+ ## Install
24
+
25
+ ```sh
26
+ pip install vapoursynth-vszipcu # released wheels (Windows / Linux x86_64)
27
+ ```
28
+
29
+ The wheel drops the plugin (and NVRTC) where VapourSynth autoloads it.
30
+
31
+ ## Build
32
+
33
+ Directly from a clone, via Python (no local Zig needed — pip fetches the `ziglang` wheel;
34
+ the CUDA **toolkit** must be installed and findable via `CUDA_PATH` so the build can
35
+ compile against headers and **copy NVRTC into the install**):
36
+
37
+ ```sh
38
+ git clone https://github.com/dnjulek/vapoursynth-zipcu
39
+ cd vapoursynth-zipcu
40
+ pip install . # build + install into site-packages
41
+ ```
42
+
43
+ The zig path leaves the DLL in `zig-out` — for a manual install, also copy
44
+ `nvrtc64_130_0.dll` + `nvrtc-builtins64_130.dll` (Windows) or `libnvrtc.so*` +
45
+ `libnvrtc-builtins.so*` (Linux) from the toolkit into the same plugin directory.
46
+
47
+ ## Common arguments
48
+
49
+ `device_id=0` selects the GPU. `num_streams` sets how many frames the filter processes
50
+ concurrently — more streams means more VRAM, raising it past 4 rarely helps.
51
+
52
+ ## Filters
53
+
54
+ ```python
55
+ core.vszipcu.Bilateral(clip clip[,
56
+ float[] sigma_spatial=3.0, # per-plane; chroma default = sigma[0]/sqrt((1<<ssw)*(1<<ssh))
57
+ float[] sigma_color=0.02, # per-plane; operates on the [0,1] domain at every depth
58
+ int[] radius, # per-plane; default max(1, round(sigma_spatial*3))
59
+ int device_id=0, int num_streams=4,
60
+ int use_shared_memory=1, # shared-memory tile kernel while the tile fits 48 KiB
61
+ int block_x=32, int block_y=8,
62
+ clip ref]) # joint/cross bilateral: weights from ref, values from clip
63
+ ```
64
+ 8/16-bit integer, 16-bit half, 32-bit float.
65
+
66
+ ```python
67
+ core.vszipcu.BM3Dv2(clip clip[, # and BM3D, same signature
68
+ clip ref, # empirical Wiener (2nd pass); also drives block matching
69
+ float[] sigma=3.0, # per-plane; < FLT_EPSILON => plane not processed
70
+ int[] block_step=8, # per-plane, 1..8
71
+ int[] bm_range=9, # per-plane, > 0
72
+ int radius=0, # temporal radius; 0 = spatial only
73
+ int[] ps_num=2, int[] ps_range=4,
74
+ bint chroma=False, # CBM3D; YUV444PS only, block matching on Y
75
+ int device_id=0, int num_streams=4,
76
+ int extractor_exp=0, # >= 3 => deterministic (order-independent) sums
77
+ data[] bm_error_s="ssd", # ssd | sad | zssd | zsad | ssd/norm
78
+ data[] transform_2d_s="dct", # dct | haar | wht | bior1.5
79
+ data[] transform_1d_s="dct",
80
+ bint zero_init=True, # BM3D, radius>0 only: zero the unprocessed planes of the
81
+ # stacked output instead of leaving them uninitialized
82
+ bint fast_fused=False]) # see below
83
+ core.vszipcu.VAggregate(clip clip, clip src, int[] planes)
84
+ ```
85
+ 32-bit float only. `BM3Dv2` is the one-step interface; `BM3D` alone emits the stacked accumulator
86
+ clip if you want to drive `VAggregate` yourself. Per-plane arrays follow upstream's rule: element
87
+ *i*, when absent, falls back to element *i-1*.
88
+
89
+ **`fast_fused`** (BM3Dv2, `radius > 0`): runs the collaborative filter and the temporal
90
+ aggregation as one kernel chain, keeping the accumulator stack on the GPU. Byte-identical output,
91
+ **+63 % to +169 %** faster — but it costs **1.7x to 7.9x** the VRAM (the accumulator cache grows
92
+ quadratically with `radius` and is independent of `num_streams`). Hence opt-in. If the cache does
93
+ not fit it raises an error telling you what it needed; it never silently falls back.
94
+
95
+ Note `extractor_exp=0` (the default, matching upstream) makes the result *nondeterministic* —
96
+ float `atomicAdd` order is arbitrary. Use `extractor_exp >= 3` if you need reproducibility.
97
+
98
+ ```python
99
+ core.vszipcu.Deband(clip clip[,
100
+ int[] iterations=1, # debanding passes, 0..32; 0 = grain only
101
+ float[] threshold=3.0, # cut-off threshold. Higher debands harder, but
102
+ # progressively destroys image detail
103
+ float[] radius=16.0, # initial sampling radius (grows each iteration).
104
+ # Higher finds more gradients; lower smooths more aggressively
105
+ float[] grain=4.0, # noise added on top, to cover residual
106
+ # quantization; 0 = none
107
+ int[] planes, # which planes to process at all; default: all
108
+ bint dither=True, # 8-bit output only, first processed plane only
109
+ int dither_algo=0, # 0=blue noise | 1=bayer | 2=ordered fixed | 3=white noise
110
+ int device_id=0, int num_streams=1])
111
+ ```
112
+ 8/16-bit integer, 16-bit half, 32-bit float.
113
+
114
+ The four strength parameters are **per-plane arrays**.
115
+ `int[] planes` says *which* planes are touched, the arrays say *how*.
116
+
117
+ ```python
118
+ core.vszipcu.DFTTest(clip clip[,
119
+ int ftype=0, # 0 = Wiener: mult by max((psd-sigma)/psd, 0) ** f0beta
120
+ # 1 = hard threshold: zero the bin when psd < sigma
121
+ # 2 = mult every bin by sigma
122
+ # 3 = mult by sigma inside [pmin,pmax], else by sigma2
123
+ # 4 = mult by sigma*sqrt(psd*pmax / ((psd+pmin)*(psd+pmax)))
124
+ float sigma=8.0, # main strength (scaled by the window; see slocation/ssx/..)
125
+ float sigma2=8.0, # ftype=3 only: strength outside [pmin,pmax]
126
+ float pmin=0.0, # ftype=3/4 only: PSD bounds
127
+ float pmax=500.0,
128
+ int sbsize=16, # spatial block size; must be 16 in this backend
129
+ int sosize=12, # spatial overlap, 0..15; >50% needs (sbsize-sosize) | sbsize
130
+ int tbsize=3, # temporal block size; ODD, 1..7 (1 = spatial only)
131
+ int swin=0, # spatial window: 0=hanning 1=hamming 2=blackman
132
+ int twin=7, # temporal window: 3=4-term b-harris 4=kaiser-bessel
133
+ # 5=7-term b-harris 6=flat top 7=rectangular 8=bartlett
134
+ # 9=bartlett-hann 10=nuttall 11=blackman-nuttall
135
+ float sbeta=2.5, # kaiser-bessel beta (swin=4 / twin=4)
136
+ float tbeta=2.5,
137
+ bint zmean=True, # subtract the windowed mean before filtering
138
+ float f0beta=1.0, # ftype=0 exponent (1.0 = plain Wiener, 0.5 = sqrt)
139
+ float[] slocation, # frequency-dependent sigma: [freq, sigma, freq, sigma, ...]
140
+ float[] ssx, float[] ssy, float[] sst, # per-axis variants of slocation
141
+ int ssystem=0,
142
+ int[] planes, # default: all
143
+ int device_id=0, int num_streams=1])
144
+ ```
145
+ 8-16-bit integer and 32-bit float.
146
+
147
+ ```python
148
+ core.vszipcu.EEDI3(clip clip, int field[, # and EEDI3H, same args, horizontal
149
+ bint dh=False, # double the height (keep every source line)
150
+ int mdis=20, # max connection radius, 1..40; larger connects shallower
151
+ # lines, but costs speed and risks artifacts
152
+ int nrad=2, # radius used for neighborhood similarity, 0..3
153
+ float alpha=0.2, # 0..1 (alpha+beta <= 1): weight given to connecting similar
154
+ # neighborhoods. Larger = more lines/edges connected
155
+ float beta=0.25, # 0..1: weight given to the vertical difference created by
156
+ # the interpolation. Larger = fewer edges connected
157
+ # (1.0 = no edge directedness at all)
158
+ float gamma=20.0, # >= 0: penalizes changes in interpolation direction.
159
+ # Larger = smoother interpolation field
160
+ bint hp=False, # search half-pixel directions too
161
+ int vcheck=2, # 0..3: strength of the vertical-consistency check
162
+ float vthresh0=32.0, # vcheck thresholds; all must be > 0 when vcheck > 0
163
+ float vthresh1=64.0,
164
+ float vthresh2=4.0,
165
+ clip sclip, # source for the vcheck comparison
166
+ int device_id=0, int num_streams=1])
167
+ ```
168
+ 8/16-bit integer, 16-bit half, 32-bit float. `field`: 0/1 pick the field to keep, 2/3 are the
169
+ double-rate variants (not allowed with `dh=True`).
170
+
171
+ ```python
172
+ core.vszipcu.FGrain(clip clip[,
173
+ int num_iterations=800, # Monte-Carlo samples per pixel; quality vs speed
174
+ float grain_radius_mean=0.1, # mean grain radius, in pixels
175
+ float grain_radius_std=0.0, # grain-radius spread; 0 = every grain the same size
176
+ float sigma=0.8, # std dev of the Gaussian in the grain model
177
+ int seed=0,
178
+ int device_id=0, int num_streams=1])
179
+ ```
180
+ 32-bit float. Physically-based film grain synthesis. For temporally-varying grain, set the
181
+ integer frame property `FGRAIN_SEED_OFFSET` on the source frame — it is added to `seed`.
182
+
183
+ ```python
184
+ core.vszipcu.GaussBlur(clip clip[,
185
+ float[] sigma=0.5, # per-plane; chroma default = sigma[0]/sqrt((1<<ssw)*(1<<ssh))
186
+ int device_id=0, int num_streams=1])
187
+ ```
188
+ 8/16-bit integer, 16-bit half, 32-bit float. A plane whose sigma is below `FLT_EPSILON` is copied
189
+ through untouched.
190
+
191
+ ```python
192
+ core.vszipcu.NLMeans(clip clip[,
193
+ int d=1, # temporal radius; 0 = spatial only
194
+ int a=2, # search-window radius, 1..64
195
+ int s=4, # patch radius, 0..8
196
+ float h=1.2, # > 0: filtering strength
197
+ string channels="auto", # auto | Y | UV | YUV | RGB
198
+ int wmode=0, # weighting function of the patch distance x, 0..3:
199
+ # 0 = exp(-x) | 1 = max(1-x, 0)
200
+ # 2 = max(1-x, 0)**2 | 3 = max(1-x, 0)**8
201
+ float wref=1.0, # >= 0: weight of the pixel itself
202
+ clip rclip, # weights computed from rclip, values from clip
203
+ int device_id=0, int num_streams=1])
204
+ ```
205
+ 8/16-bit integer, 16-bit half, 32-bit float. `channels="YUV"` requires 4:4:4 — a joint patch
206
+ distance needs one shared pixel lattice — so on subsampled clips run a `"Y"` pass and a `"UV"`
207
+ pass instead.
208
+
209
+ ```python
210
+ core.vszipcu.NNEDI3(clip clip, int field[,
211
+ bint dh=False, # double the height (keep every source line)
212
+ int[] planes, # default: all
213
+ int nsize=6, # predictor neighborhood, 0..6: 0=8x6 1=16x6 2=32x6
214
+ # 3=48x6 4=8x4 5=16x4 6=32x4
215
+ int nns=1, # predictor neurons, 0..4: 0=16 1=32 2=64 3=128 4=256
216
+ int qual=1, # 1 or 2: number of predictor passes averaged
217
+ int etype=0, # 0 = weights trained on absolute error, 1 = squared error
218
+ int pscrn=2, # prescreener, 0..4: 0=off (predict every pixel)
219
+ # 1=original, 2..4=new levels 0..2 (higher = fewer pixels
220
+ # left to cubic interpolation: slower, slightly better)
221
+ int device_id=0, int num_streams])
222
+ ```
223
+ 8/16-bit integer, 16-bit half, 32-bit float. Weights are embedded in the plugin — no external
224
+ `nnedi3_weights.bin` file needed. On sm_80+ the predictor runs on tensor cores (fp16 inputs,
225
+ fp32 accumulation); older cards fall back to an fp32 path automatically.
226
+
227
+ ## Credits
228
+
229
+ | filter | ported from |
230
+ |---|---|
231
+ | Bilateral | [VapourSynth-BilateralGPU](https://github.com/WolframRhodium/VapourSynth-BilateralGPU) (rtc variant), by WolframRhodium |
232
+ | BM3D / BM3Dv2 / VAggregate | [VapourSynth-BM3DCUDA](https://github.com/WolframRhodium/VapourSynth-BM3DCUDA), by WolframRhodium |
233
+ | DFTTest | [vs-dfttest2](https://github.com/AmusementClub/vs-dfttest2) (NVRTC backend), by AmusementClub |
234
+ | FGrain | [vs-fgrain-cuda](https://github.com/AmusementClub/vs-fgrain-cuda), by AmusementClub |
235
+ | NNEDI3 | [VapourSynth-nnedi3vk](https://github.com/HolyWu/VapourSynth-nnedi3vk), by HolyWu |
236
+ | Deband | [vs-placebo](https://github.com/Lypheo/vs-placebo), by Lypheo (libplacebo's `pl_shader_deband` + `pl_shader_dither`) |
237
+ | NLMeans | [KNLMeansCL](https://github.com/Khanattila/KNLMeansCL), by Khanattila |
238
+ | EEDI3 / EEDI3H | [VapourSynth-EEDI3](https://github.com/HolyWu/VapourSynth-EEDI3) (by HolyWu) and [vapoursynth-zip](https://github.com/dnjulek/vapoursynth-zip) (by dnjulek) — the CPU references |
239
+
240
+ Built on [cudaz](https://github.com/akhildevelops/cudaz) (CUDA driver API + NVRTC bindings,
241
+ vendored in `cudaz/`).
@@ -0,0 +1,231 @@
1
+ # vszipcu
2
+
3
+ VapourSynth CUDA image processing, written in Zig.
4
+
5
+ ## Requirements
6
+
7
+ - An NVIDIA GPU + driver. (Only NNEDI3 cares about the architecture: its tensor-core
8
+ predictor needs sm_80+, and it falls back to an fp32 path automatically below that.)
9
+ - **No CUDA toolkit at runtime.** Released wheels ship NVRTC (`nvrtc64_130_0` /
10
+ `libnvrtc.so.13` + builtins) next to the plugin. The host only needs the NVIDIA driver
11
+ (`nvcuda` / `libcuda`).
12
+
13
+ ## Install
14
+
15
+ ```sh
16
+ pip install vapoursynth-vszipcu # released wheels (Windows / Linux x86_64)
17
+ ```
18
+
19
+ The wheel drops the plugin (and NVRTC) where VapourSynth autoloads it.
20
+
21
+ ## Build
22
+
23
+ Directly from a clone, via Python (no local Zig needed — pip fetches the `ziglang` wheel;
24
+ the CUDA **toolkit** must be installed and findable via `CUDA_PATH` so the build can
25
+ compile against headers and **copy NVRTC into the install**):
26
+
27
+ ```sh
28
+ git clone https://github.com/dnjulek/vapoursynth-zipcu
29
+ cd vapoursynth-zipcu
30
+ pip install . # build + install into site-packages
31
+ ```
32
+
33
+ The zig path leaves the DLL in `zig-out` — for a manual install, also copy
34
+ `nvrtc64_130_0.dll` + `nvrtc-builtins64_130.dll` (Windows) or `libnvrtc.so*` +
35
+ `libnvrtc-builtins.so*` (Linux) from the toolkit into the same plugin directory.
36
+
37
+ ## Common arguments
38
+
39
+ `device_id=0` selects the GPU. `num_streams` sets how many frames the filter processes
40
+ concurrently — more streams means more VRAM, raising it past 4 rarely helps.
41
+
42
+ ## Filters
43
+
44
+ ```python
45
+ core.vszipcu.Bilateral(clip clip[,
46
+ float[] sigma_spatial=3.0, # per-plane; chroma default = sigma[0]/sqrt((1<<ssw)*(1<<ssh))
47
+ float[] sigma_color=0.02, # per-plane; operates on the [0,1] domain at every depth
48
+ int[] radius, # per-plane; default max(1, round(sigma_spatial*3))
49
+ int device_id=0, int num_streams=4,
50
+ int use_shared_memory=1, # shared-memory tile kernel while the tile fits 48 KiB
51
+ int block_x=32, int block_y=8,
52
+ clip ref]) # joint/cross bilateral: weights from ref, values from clip
53
+ ```
54
+ 8/16-bit integer, 16-bit half, 32-bit float.
55
+
56
+ ```python
57
+ core.vszipcu.BM3Dv2(clip clip[, # and BM3D, same signature
58
+ clip ref, # empirical Wiener (2nd pass); also drives block matching
59
+ float[] sigma=3.0, # per-plane; < FLT_EPSILON => plane not processed
60
+ int[] block_step=8, # per-plane, 1..8
61
+ int[] bm_range=9, # per-plane, > 0
62
+ int radius=0, # temporal radius; 0 = spatial only
63
+ int[] ps_num=2, int[] ps_range=4,
64
+ bint chroma=False, # CBM3D; YUV444PS only, block matching on Y
65
+ int device_id=0, int num_streams=4,
66
+ int extractor_exp=0, # >= 3 => deterministic (order-independent) sums
67
+ data[] bm_error_s="ssd", # ssd | sad | zssd | zsad | ssd/norm
68
+ data[] transform_2d_s="dct", # dct | haar | wht | bior1.5
69
+ data[] transform_1d_s="dct",
70
+ bint zero_init=True, # BM3D, radius>0 only: zero the unprocessed planes of the
71
+ # stacked output instead of leaving them uninitialized
72
+ bint fast_fused=False]) # see below
73
+ core.vszipcu.VAggregate(clip clip, clip src, int[] planes)
74
+ ```
75
+ 32-bit float only. `BM3Dv2` is the one-step interface; `BM3D` alone emits the stacked accumulator
76
+ clip if you want to drive `VAggregate` yourself. Per-plane arrays follow upstream's rule: element
77
+ *i*, when absent, falls back to element *i-1*.
78
+
79
+ **`fast_fused`** (BM3Dv2, `radius > 0`): runs the collaborative filter and the temporal
80
+ aggregation as one kernel chain, keeping the accumulator stack on the GPU. Byte-identical output,
81
+ **+63 % to +169 %** faster — but it costs **1.7x to 7.9x** the VRAM (the accumulator cache grows
82
+ quadratically with `radius` and is independent of `num_streams`). Hence opt-in. If the cache does
83
+ not fit it raises an error telling you what it needed; it never silently falls back.
84
+
85
+ Note `extractor_exp=0` (the default, matching upstream) makes the result *nondeterministic* —
86
+ float `atomicAdd` order is arbitrary. Use `extractor_exp >= 3` if you need reproducibility.
87
+
88
+ ```python
89
+ core.vszipcu.Deband(clip clip[,
90
+ int[] iterations=1, # debanding passes, 0..32; 0 = grain only
91
+ float[] threshold=3.0, # cut-off threshold. Higher debands harder, but
92
+ # progressively destroys image detail
93
+ float[] radius=16.0, # initial sampling radius (grows each iteration).
94
+ # Higher finds more gradients; lower smooths more aggressively
95
+ float[] grain=4.0, # noise added on top, to cover residual
96
+ # quantization; 0 = none
97
+ int[] planes, # which planes to process at all; default: all
98
+ bint dither=True, # 8-bit output only, first processed plane only
99
+ int dither_algo=0, # 0=blue noise | 1=bayer | 2=ordered fixed | 3=white noise
100
+ int device_id=0, int num_streams=1])
101
+ ```
102
+ 8/16-bit integer, 16-bit half, 32-bit float.
103
+
104
+ The four strength parameters are **per-plane arrays**.
105
+ `int[] planes` says *which* planes are touched, the arrays say *how*.
106
+
107
+ ```python
108
+ core.vszipcu.DFTTest(clip clip[,
109
+ int ftype=0, # 0 = Wiener: mult by max((psd-sigma)/psd, 0) ** f0beta
110
+ # 1 = hard threshold: zero the bin when psd < sigma
111
+ # 2 = mult every bin by sigma
112
+ # 3 = mult by sigma inside [pmin,pmax], else by sigma2
113
+ # 4 = mult by sigma*sqrt(psd*pmax / ((psd+pmin)*(psd+pmax)))
114
+ float sigma=8.0, # main strength (scaled by the window; see slocation/ssx/..)
115
+ float sigma2=8.0, # ftype=3 only: strength outside [pmin,pmax]
116
+ float pmin=0.0, # ftype=3/4 only: PSD bounds
117
+ float pmax=500.0,
118
+ int sbsize=16, # spatial block size; must be 16 in this backend
119
+ int sosize=12, # spatial overlap, 0..15; >50% needs (sbsize-sosize) | sbsize
120
+ int tbsize=3, # temporal block size; ODD, 1..7 (1 = spatial only)
121
+ int swin=0, # spatial window: 0=hanning 1=hamming 2=blackman
122
+ int twin=7, # temporal window: 3=4-term b-harris 4=kaiser-bessel
123
+ # 5=7-term b-harris 6=flat top 7=rectangular 8=bartlett
124
+ # 9=bartlett-hann 10=nuttall 11=blackman-nuttall
125
+ float sbeta=2.5, # kaiser-bessel beta (swin=4 / twin=4)
126
+ float tbeta=2.5,
127
+ bint zmean=True, # subtract the windowed mean before filtering
128
+ float f0beta=1.0, # ftype=0 exponent (1.0 = plain Wiener, 0.5 = sqrt)
129
+ float[] slocation, # frequency-dependent sigma: [freq, sigma, freq, sigma, ...]
130
+ float[] ssx, float[] ssy, float[] sst, # per-axis variants of slocation
131
+ int ssystem=0,
132
+ int[] planes, # default: all
133
+ int device_id=0, int num_streams=1])
134
+ ```
135
+ 8-16-bit integer and 32-bit float.
136
+
137
+ ```python
138
+ core.vszipcu.EEDI3(clip clip, int field[, # and EEDI3H, same args, horizontal
139
+ bint dh=False, # double the height (keep every source line)
140
+ int mdis=20, # max connection radius, 1..40; larger connects shallower
141
+ # lines, but costs speed and risks artifacts
142
+ int nrad=2, # radius used for neighborhood similarity, 0..3
143
+ float alpha=0.2, # 0..1 (alpha+beta <= 1): weight given to connecting similar
144
+ # neighborhoods. Larger = more lines/edges connected
145
+ float beta=0.25, # 0..1: weight given to the vertical difference created by
146
+ # the interpolation. Larger = fewer edges connected
147
+ # (1.0 = no edge directedness at all)
148
+ float gamma=20.0, # >= 0: penalizes changes in interpolation direction.
149
+ # Larger = smoother interpolation field
150
+ bint hp=False, # search half-pixel directions too
151
+ int vcheck=2, # 0..3: strength of the vertical-consistency check
152
+ float vthresh0=32.0, # vcheck thresholds; all must be > 0 when vcheck > 0
153
+ float vthresh1=64.0,
154
+ float vthresh2=4.0,
155
+ clip sclip, # source for the vcheck comparison
156
+ int device_id=0, int num_streams=1])
157
+ ```
158
+ 8/16-bit integer, 16-bit half, 32-bit float. `field`: 0/1 pick the field to keep, 2/3 are the
159
+ double-rate variants (not allowed with `dh=True`).
160
+
161
+ ```python
162
+ core.vszipcu.FGrain(clip clip[,
163
+ int num_iterations=800, # Monte-Carlo samples per pixel; quality vs speed
164
+ float grain_radius_mean=0.1, # mean grain radius, in pixels
165
+ float grain_radius_std=0.0, # grain-radius spread; 0 = every grain the same size
166
+ float sigma=0.8, # std dev of the Gaussian in the grain model
167
+ int seed=0,
168
+ int device_id=0, int num_streams=1])
169
+ ```
170
+ 32-bit float. Physically-based film grain synthesis. For temporally-varying grain, set the
171
+ integer frame property `FGRAIN_SEED_OFFSET` on the source frame — it is added to `seed`.
172
+
173
+ ```python
174
+ core.vszipcu.GaussBlur(clip clip[,
175
+ float[] sigma=0.5, # per-plane; chroma default = sigma[0]/sqrt((1<<ssw)*(1<<ssh))
176
+ int device_id=0, int num_streams=1])
177
+ ```
178
+ 8/16-bit integer, 16-bit half, 32-bit float. A plane whose sigma is below `FLT_EPSILON` is copied
179
+ through untouched.
180
+
181
+ ```python
182
+ core.vszipcu.NLMeans(clip clip[,
183
+ int d=1, # temporal radius; 0 = spatial only
184
+ int a=2, # search-window radius, 1..64
185
+ int s=4, # patch radius, 0..8
186
+ float h=1.2, # > 0: filtering strength
187
+ string channels="auto", # auto | Y | UV | YUV | RGB
188
+ int wmode=0, # weighting function of the patch distance x, 0..3:
189
+ # 0 = exp(-x) | 1 = max(1-x, 0)
190
+ # 2 = max(1-x, 0)**2 | 3 = max(1-x, 0)**8
191
+ float wref=1.0, # >= 0: weight of the pixel itself
192
+ clip rclip, # weights computed from rclip, values from clip
193
+ int device_id=0, int num_streams=1])
194
+ ```
195
+ 8/16-bit integer, 16-bit half, 32-bit float. `channels="YUV"` requires 4:4:4 — a joint patch
196
+ distance needs one shared pixel lattice — so on subsampled clips run a `"Y"` pass and a `"UV"`
197
+ pass instead.
198
+
199
+ ```python
200
+ core.vszipcu.NNEDI3(clip clip, int field[,
201
+ bint dh=False, # double the height (keep every source line)
202
+ int[] planes, # default: all
203
+ int nsize=6, # predictor neighborhood, 0..6: 0=8x6 1=16x6 2=32x6
204
+ # 3=48x6 4=8x4 5=16x4 6=32x4
205
+ int nns=1, # predictor neurons, 0..4: 0=16 1=32 2=64 3=128 4=256
206
+ int qual=1, # 1 or 2: number of predictor passes averaged
207
+ int etype=0, # 0 = weights trained on absolute error, 1 = squared error
208
+ int pscrn=2, # prescreener, 0..4: 0=off (predict every pixel)
209
+ # 1=original, 2..4=new levels 0..2 (higher = fewer pixels
210
+ # left to cubic interpolation: slower, slightly better)
211
+ int device_id=0, int num_streams])
212
+ ```
213
+ 8/16-bit integer, 16-bit half, 32-bit float. Weights are embedded in the plugin — no external
214
+ `nnedi3_weights.bin` file needed. On sm_80+ the predictor runs on tensor cores (fp16 inputs,
215
+ fp32 accumulation); older cards fall back to an fp32 path automatically.
216
+
217
+ ## Credits
218
+
219
+ | filter | ported from |
220
+ |---|---|
221
+ | Bilateral | [VapourSynth-BilateralGPU](https://github.com/WolframRhodium/VapourSynth-BilateralGPU) (rtc variant), by WolframRhodium |
222
+ | BM3D / BM3Dv2 / VAggregate | [VapourSynth-BM3DCUDA](https://github.com/WolframRhodium/VapourSynth-BM3DCUDA), by WolframRhodium |
223
+ | DFTTest | [vs-dfttest2](https://github.com/AmusementClub/vs-dfttest2) (NVRTC backend), by AmusementClub |
224
+ | FGrain | [vs-fgrain-cuda](https://github.com/AmusementClub/vs-fgrain-cuda), by AmusementClub |
225
+ | NNEDI3 | [VapourSynth-nnedi3vk](https://github.com/HolyWu/VapourSynth-nnedi3vk), by HolyWu |
226
+ | Deband | [vs-placebo](https://github.com/Lypheo/vs-placebo), by Lypheo (libplacebo's `pl_shader_deband` + `pl_shader_dither`) |
227
+ | NLMeans | [KNLMeansCL](https://github.com/Khanattila/KNLMeansCL), by Khanattila |
228
+ | EEDI3 / EEDI3H | [VapourSynth-EEDI3](https://github.com/HolyWu/VapourSynth-EEDI3) (by HolyWu) and [vapoursynth-zip](https://github.com/dnjulek/vapoursynth-zip) (by dnjulek) — the CPU references |
229
+
230
+ Built on [cudaz](https://github.com/akhildevelops/cudaz) (CUDA driver API + NVRTC bindings,
231
+ vendored in `cudaz/`).
@@ -0,0 +1,50 @@
1
+ const std = @import("std");
2
+ const builtin = @import("builtin");
3
+
4
+ pub fn build(b: *std.Build) !void {
5
+ // NVIDIA ships MSVC import libs; gnu ABI cannot link them cleanly on Windows.
6
+ const target = b.standardTargetOptions(.{
7
+ .default_target = if (builtin.os.tag == .windows) .{
8
+ .cpu_arch = .x86_64,
9
+ .os_tag = .windows,
10
+ .abi = .msvc,
11
+ } else .{},
12
+ });
13
+ const optimize = b.standardOptimizeOption(.{});
14
+
15
+ const mod = b.createModule(.{
16
+ .root_source_file = b.path("src/plugin.zig"),
17
+ .target = target,
18
+ .optimize = optimize,
19
+ });
20
+
21
+ const lib = b.addLibrary(.{
22
+ .name = "vszipcu",
23
+ .linkage = .dynamic,
24
+ .root_module = mod,
25
+ });
26
+
27
+ const cudaz_dep = b.dependency("cudaz", .{});
28
+ mod.addImport("cudaz", cudaz_dep.module("cudaz"));
29
+
30
+ const vapoursynth_dep = b.dependency("vapoursynth", .{
31
+ .target = target,
32
+ .optimize = optimize,
33
+ });
34
+ mod.addImport("vapoursynth", vapoursynth_dep.module("vapoursynth"));
35
+
36
+ // cuda.lib is a stub that LoadLibrary()s nvcuda.dll. NVRTC is loaded at runtime
37
+ // (VS plugins do not see PATH, so an import of nvrtc64_*.dll would fail).
38
+ mod.link_libc = true;
39
+ mod.linkSystemLibrary("cuda", .{});
40
+
41
+ if (target.result.os.tag == .linux) {
42
+ mod.linkSystemLibrary("dl", .{}); // dynlib.zig uses dladdr
43
+ }
44
+
45
+ if (optimize == .ReleaseFast) {
46
+ mod.strip = true;
47
+ }
48
+
49
+ b.installArtifact(lib);
50
+ }
@@ -0,0 +1,17 @@
1
+ .{
2
+ .name = .vszipcu,
3
+ .version = "1.1.0",
4
+ .fingerprint = 0x5060d0605c460ab4,
5
+ .minimum_zig_version = "0.16.0",
6
+ .dependencies = .{
7
+ .cudaz = .{
8
+ .path = "./cudaz/",
9
+ },
10
+ .vapoursynth = .{
11
+ // zig fetch --save git+https://github.com/dnjulek/vapoursynth-zig.git
12
+ .url = "git+https://github.com/dnjulek/vapoursynth-zig.git#b87ff61ce680fa5a4cf7d44a9cb4b605c5037432",
13
+ .hash = "vapoursynth-4.0.0-jLYMQ6DjAgDFOODh8tdhWCw0iGHMPKiR4znTJwSyvV36",
14
+ },
15
+ },
16
+ .paths = .{"."},
17
+ }
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Gurramkonda Reddy Akhil Teja
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ ![](./cuda_zig.jpeg)
26
+
27
+ The above image is licensed under CC BY-SA 4.0