Repository navigation
Releases
Native 0.2.0
Native 0.2.0 adds a GPU C API for host-owned Metal, Vulkan and DX12 buffers, C++17 wrappers, and an optional Windows CUDA/DX12 adapter.
Breaking changes
- C ABI 3.0.0 replaces 1.0.0. Rebuild C/C++ consumers against the new headers. Remove
oidnw_filter_desc.size, initialize descriptors with their default functions, and keepnextextension pointers NULL. CPU input scales must be positive and finite; unknown filter flag bits are rejected. - Rust execution parameters, information structs and several enums are now non-exhaustive. Replace parameter literals with
DenoiseParams::default().with_input_scale(scale)and add wildcard match arms where required. Rust hosts must continue to use wgpu=30.0.1.
Highlights
- GPU C submissions wait on and signal host timeline objects, with bounded pending work and explicit completion handling.
- C++17 wrappers provide move-only owners and platform import helpers. Vulkan helpers merge device requirements before device creation.
- The optional Windows CUDA adapter accepts ordinary CUDA device pointers or adapter-allocated shared images, orders work on CUDA streams, and supports workspace resizing.
- Rust and GPU C APIs can warm up pipelines before image allocation. CPU filters can update input exposure without rebuilding their workspace.
- Experimental kernel and quality options expose explicit execution paths; FAST quality opts into lower-precision accumulation.
- Packages and the Rust crate include GPU integration example sources and the integration walkthrough.
Get the library
Download the C/C++ package matching your platform: Windows x86_64 MSVC, Linux x86_64 GNU, macOS x86_64 or macOS ARM64. SHA256SUMS covers the release assets.
For Rust:
[dependencies]
oidn-webgpu = { package = "oidn-webgpu-native", version = "0.2.0" }The crate bundles all four platform cores; consumers need Rust and a platform linker, without Node, Zig or build-time GitHub downloads. Model weights are separate.
See the native guide for usage, defaults and hardware limitations, and the full changelog and migration notes.
0.6.0
oidn-webgpu 0.6.0 is the first release under the new package name. It adds experimental native Rust and C APIs, sanitizes inputs and outputs like OIDN, and lowers default FP16 latency in Chrome by up to 19% on the measured GPUs. The package name is the only breaking change.
Breaking changes
- The package is renamed from
oidn-webtooidn-webgpu. Replace the dependency and imports (import { initUNetFromURL } from 'oidn-webgpu'); the API is unchanged.
Added
- Experimental native denoising through Rust and C APIs on Metal, Vulkan or Direct3D 12. Rust hosts can share GPU buffers; the C API accepts CPU images. See the native guide.
- Native releases provide precompiled C packages and a Rust crate with SHA-256 verified cores for Windows x86_64 MSVC, Linux x86_64 GNU, macOS x86_64 and macOS ARM64. The bundled crate builds without Node, npm, Zig or build-time downloads from GitHub.
- Native packages include standalone Rust and Windows MSVC applications for output validation and timing. The Rust application's Git dependency is pinned to the package source revision.
- Experimental
kernel: 'subgroup-matrix'andsubgroupMatrixtuning options. Browsers needchromium-experimental-subgroup-matrix; native hosts need wgpu cooperative-matrix support.
Changed
- Default FP16 denoising in Chrome has 11–19% lower latency on Apple M4 Max and 0–16% on NVIDIA RTX 4060 Laptop than 0.5.0 (Performance); first initialization takes longer. Output differs slightly from 0.5.0;
gemm: { decoderSubPixel: false }restores the 0.5.0 decoder calculation. FP32 is unchanged. getLastExecutionProfile()sums network time over all tiles of an image instead of reporting only the first tile. Preprocessing and output conversion are excluded.
Fixed
- Browser CPU input preserves normalized
Float32Arrayalbedo and normal values instead of dividing them by 255.tileExecutenow accepts floating-point auxiliary images in its TypeScript API; 8-bit auxiliary images still use [0, 255]. - Windows native packages build and link with MSVC. C consumers use the DLL CRT (
/MD). - Native cooperative-matrix denoising produces finite, repeatable output with shader runtime checks disabled on the tested NVIDIA Vulkan device.
- Native distributions include the required runtime license notices, and the crate declares the bundled components' licenses alongside MIT.
- Inputs and network outputs are sanitized like OIDN: NaN becomes 0, and color, albedo and normals are clamped to their valid ranges. Previously NaN or out-of-range input could spread across the image, HDR output could be negative and GPU LDR output could exceed 1.
examples/aux.*are renamed toexamples/auxiliary.*so the repository can be checked out on Windows, whereAUXis a reserved file name.
Install
The browser package is available on npm.
npm i oidn-webgpuThe archive contains the browser library, type declarations and bundled scripts. Weights are separate: choose a TZA file from the weights table.
Rust and C downloads are in Native 0.1.0. Native APIs remain experimental; Rust hosts must share the exact wgpu 30.0.1 crate and source.
Validation
- 64 JavaScript tests, 5 native unit tests and 4 native GPU tests passed on Apple M4 Max / macOS Metal.
- 27 external C/Rust application cases passed. All 15 output comparisons were byte-identical; the real 1024×1024 HDR example also matched between C and the browser with implicit GEMM / FP16.
- The browser archive installed into a separate application, built with Vite and completed WebGPU inference.
- Four-platform CI builds packages and verifies the standalone crate without a GPU. This local validation did not exercise Windows/Linux GPU execution or Intel Mac GPUs.
Full changelog and performance measurements.
Source: 1d7dd4a. Four-platform CI.
Native 0.1.1
Native 0.1.1 adds CMake integration for the precompiled C packages. The C ABI and denoising kernels are unchanged from Native 0.1.0.
CMake integration
Set CMAKE_PREFIX_PATH to the extracted package root. With CMake 3.20 or newer:
find_package(oidn_webgpu CONFIG REQUIRED)
add_executable(my_app main.c)
target_link_libraries(my_app PRIVATE oidn_webgpu::oidn_webgpu)oidn_webgpu::oidn_webgpu: shared C filter library and public headers.oidn_webgpu::oidn_webgpu_core: static planner library, public headers and required system libraries.- The config and version files remain usable when the package is moved. Version checks use the native crate version.
examples/CMakeLists.txtbuilds and installsdenoise,planand the Windows validation application. Windows examples copy the DLL beside the executable; installed examples can be deployed as one directory.
Weights are separate from these packages. Choose the package for your target OS and CPU architecture.
Downloads
C packages now use stable, versioned names such as oidn-webgpu-native-0.1.1-aarch64-apple-darwin.tar.gz. The source commit remains in manifest.json.
Packages cover macOS ARM64, macOS x86_64, Windows x86_64 MSVC and Linux x86_64 GNU. The release also includes the four planner cores, their manifest, a Rust crate with bundled cores, license notices and SHA-256 checksums.
The Rust crate is available on crates.io:
[dependencies]
oidn-webgpu = { package = "oidn-webgpu-native", version = "0.1.1" }Rust hosts must share the exact wgpu 30.0.1 crate and source. The browser npm package remains at 0.6.0.
Validation
Four-platform CI builds the C packages, checks the CMake targets, relocated packages and installed applications, then validates the assembled crate in isolation without Node/scriptc. Hosted CI does not run GPU inference.
Local validation on Apple M4 Max / Metal includes CMake-built applications after SDK relocation and a real 1024×1024 HDR image whose implicit-GEMM / FP16 output matches the browser byte-for-byte. JavaScript tests: 69 passed; native unit tests: 5 passed. Windows/Linux and Intel Mac GPU execution are not exercised by this release validation.
Native integration guide · Source 26a4eb1 · Release validation
Native 0.1.0
Experimental Rust and C GPU denoising on Metal, Vulkan and Direct3D 12, using the same WGSL kernels as the browser package.
Downloads
- Four precompiled C packages: macOS ARM64, macOS x86_64, Windows x86_64 MSVC and Linux x86_64 GNU. Each contains the shared library, headers, planner core and application examples.
- A Rust
.cratecontaining all four verified planner cores. Extract it and use a local Cargo path dependency to build without Node, npm, Zig or a build-time GitHub download. Cargo dependencies still need to be available. - Raw planner cores, their target manifest, license notices and SHA-256 checksums.
The Rust package is available on crates.io:
[dependencies]
oidn-webgpu = { package = "oidn-webgpu-native", version = "0.1.0" }The native guide also describes Git dependencies and precompiled core overrides.
Rust hosts use their own wgpu buffers and encoder and must resolve the same wgpu 30.0.1 crate and source. The C API accepts packed CPU RGBA32F images, creates its own device and blocks through readback. Weights are separate from these downloads.
Validation
Four-platform CI verifies package hashes and C/Rust interfaces, then unpacks the assembled crate outside the checkout and runs publish dry-runs and Rust examples without Node/scriptc. Hosted CI does not run GPU inference.
On Apple M4 Max / macOS Metal, 27 external C/Rust cases passed, including odd dimensions, tiling, checked/unchecked shaders, cooperative matrices and host-owned buffers. All 15 output comparisons were byte-identical. Four native GPU regression tests also passed. Windows/Linux and Intel Mac GPU execution were not exercised in this local validation.
Native API and integration guide · Browser release 0.6.0
Source: 1d7dd4a. Four-platform CI.
0.5.0
oidn-web 0.5.0 simplifies device setup, makes tiled execution always settle, and switches FP16 convolutions to implicit GEMM. It contains breaking changes for TypeScript callers that pass adapterInfo, for code that constructs UNet directly, and for code that relies on square tiles or per-frame tile pacing.
Performance
Measured with npm run benchmark -- --direct-gemm-only in headless Chrome, using the Clean Aux Large model with FP16. Times are medians. Performance depends on the browser, GPU, model, and tile size. Devices without shader-f16 use FP32, which already used implicit GEMM in 0.4.0, so their gains are expected to be smaller.
| GPU | Input | 0.4.0 | 0.5.0 | Speedup |
|---|---|---|---|---|
| Apple GPU (macOS) | 512 x 512, one tile | 27.2 ms | 19.1 ms | 1.42x |
| Apple GPU (macOS) | 1920 x 1080, 512 px tiles (12 tiles) | 742 ms | 369 ms | 2.01x |
| NVIDIA RTX 4060 Laptop (Windows 11, Chrome 153) | 512 x 512, one tile | 339 ms | 39.7 ms | 8.55x |
| NVIDIA RTX 4060 Laptop (Windows 11, Chrome 153) | 1920 x 1080, 512 px tiles (12 tiles) | 8844 ms | 555 ms | 15.94x |
- Implicit GEMM is now the default for FP16. The 0.4.0 direct FP16 kernel was especially slow on the tested NVIDIA GPU. Network GPU time for a 512 x 512 tile drops from 26.8 ms to 18.5 ms on the Apple GPU, and from 360 ms to 38.5 ms on the RTX 4060.
- Overlap only on shared tile edges reduces the input each tile computes. With the direct kernel alone, the 1920 x 1080 case is about 1.5x faster than 0.4.0 on both GPUs.
Breaking changes
initUNetFromURLandinitUNetFromBuffertake{ device }as the second argument.adapterInfowas only needed by the removed TensorFlow.js backend and is no longer accepted by the type. Extra properties are ignored at runtime, but TypeScript rejects an object literal that still containsadapterInfo.new UNet(tensors, device, options)takes aGPUDeviceinstead of a{ device, adapterInfo }object.tileExecutenow continues on the event loop between tiles by default instead of waiting forrequestAnimationFrame. Passscheduling: 'animation-frame'to keep pacing tiles to display frames.- Tiles are balanced rectangles with overlap only on edges shared with another tile, instead of fixed-size squares. Tile count, position, and size reported to
progressdiffer from 0.4.0. The defaultdynamicTile.initialTileSizeis now 432. UNetExecutionStatsno longer hastileWidthandtileHeight. UsetileColumns,tileRows,tileOverlap,inputPixelCount, andinputShapeCountinstead.- FP16 convolutions use implicit GEMM by default. Output differs slightly from 0.4.0 because accumulation order changed. Set
kernel: 'direct'to reproduce the 0.4.0 FP16 path.
Added
hdrTransfer: 'log'for RTLightmap HDR models, alongside the default PU transfer.errorcallback ontileExecutefor asynchronous failures, WebGPU device loss, and exceptions thrown byprogressordone.progressanddonemay return promises.scheduling: 'event-loop' | 'animation-frame',tileOverlap, andwholeImageoptions ontileExecute.prepareForImage(width, height)to create per-shape GPU resources before the first denoise.planTileGridand itsTilePlan,PlannedTile, andTileRecttypes.- Experimental
gemmtuning options. These are intended for benchmarking and are not covered by semver. hdrTransferandactiveExecutionCountingetRuntimeInfo(), and the active GEMM configuration underkernel.gemm.
Changed
- Implicit GEMM tiles are selected by output alignment and GPU limits, with optimized addressing, weight layout, register tiles, shared-memory layout, and pooling access.
- The final RGB convolution uses an adaptive shared-memory cache.
- Adaptive tile sizing uses the smoothed P75 tile GPU time, excludes the cold first tile, ignores cancelled and single-tile work, and buckets input shapes to at most two sizes.
animation-framescheduling falls back to a 100 ms timer so execution still completes in hidden tabs.
Fixed
- Tiled execution always settles with
doneorerror, or stops silently after abort, including whenrequestAnimationFramenever fires or the device is lost. - Completed executions release their device-loss listeners.
- Edge tiles whose size is not a multiple of 16 replicate edge pixels into the padded model input.
- The npm package no longer includes benchmark results, tests, and scripts.
- Renamed
examples/aux.*toexamples/auxiliary.*so the repository can be checked out on Windows, whereAUXis a reserved file name.
Migration notes
- Replace
{ device, adapterInfo }with{ device }. - Replace
new UNet(tensors, { device, adapterInfo }, options)withnew UNet(tensors, device, options). - Interactive renderers that share the GPU with OIDN should pass
scheduling: 'animation-frame'. - Pass an
errorcallback to handle failures. Without one, failures are logged to the console.
0.4.0
oidn-web 0.4.0 replaces the TensorFlow.js inference stack with a purpose-built, model-driven WebGPU runtime. Existing initUNetFromURL and initUNetFromBuffer integrations remain supported while gaining native FP16, adaptive scheduling, runtime diagnostics, and stronger model validation.
Highlights
- Removed TensorFlow.js and its WebGPU backend from the runtime dependencies.
- Added a custom WGSL U-Net executor with automatic FP16 selection and a deterministic FP32 fallback.
- Added built-in topology descriptors for the current OIDN small and large RT models, including clean auxiliary variants.
- Reduced the reference Vite ESM bundle from approximately 168.8 KB to 32.4 KB gzip compared with 0.3.5, a reduction of about 81%.
- Reached a 27.6 ms median for a 512 x 512 Clean Aux Large inference on the tested Apple GPU, versus 35.0 ms for the TensorFlow.js baseline (1.27x faster). Performance depends on the browser, GPU, model, and tile size.
Added
- Model-driven graph planning and lifetime-aware activation-buffer reuse.
- Versioned
UNetModelSpecdescriptors, topology detection, and validation of tensor names, layouts, data types, byte lengths, kernel shapes, bias shapes, and graph channel flow. modelSpecinitialization option for future or custom OIDN model topologies.npm run model:inspectfor model hashes, tensor signatures, and descriptor compatibility checks.- Dynamic tile sizing with configurable minimum, initial, and maximum tile sizes and a target GPU time.
- GPU queue backpressure between tiles to keep cancellation and rendering interaction responsive.
- Runtime diagnostics through
getRuntimeInfo(), including the selected engine, precision, model, kernel capabilities, tile state, and resource statistics. - Per-layer GPU profiling through
profileNextExecution()andgetLastExecutionProfile()whentimestamp-queryis enabled. - Cross-version browser benchmarks with queue-complete timings, sampled output validation, TFJS baseline comparison, and per-layer GPU profiles.
- Explicit, idempotent resource disposal and resource lifecycle accounting.
- Automated model, graph, scheduler, resource leak, allocation rollback, and late-async-cleanup tests.
Changed
- U-Net inference now runs directly in WGSL. The stable
autoengine selects the native WGSL backend and no longer initializes TensorFlow.js. - FP16-capable devices retain TZA half-float weights and use short FP16 FMA accumulation groups folded into FP32 accumulators. The final output remains FP32.
- Devices without
shader-f16automatically use native FP32 inference. - Convolution tensors and activations use a blocked four-channel layout with channel-specialized shaders.
- Decoder
upsample + concat + convpatterns are fused, and all network passes for a tile are encoded into one command buffer. - Shape-independent pipelines are compiled asynchronously before initialization resolves to avoid first-denoise shader compilation stalls.
maxTileSizeis now a hard upper bound for the adaptive tile controller.- A shared
GPUDeviceuses FP16 only whenshader-f16was requested during device creation; WebGPU features cannot be enabled afterward.
Migration notes
- No changes are required for basic
initUNetFromURLorinitUNetFromBufferusage. - Call
dispose()when a U-Net instance is no longer needed. - When supplying an existing
GPUDevice, requestshader-f16before creating the device if FP16 inference is desired. - Set
dynamicTile: falseto restore fixed-size tiling.
Full Changelog: v0.3.2...v0.4.0oidn-web 0.4.0 replaces the TensorFlow.js inference stack with a purpose-built, model-driven WebGPU runtime. Existing initUNetFromURL and
initUNetFromBuffer integrations remain supported while gaining native FP16,
adaptive scheduling, runtime diagnostics, and stronger model validation.
Highlights
- Removed TensorFlow.js and its WebGPU backend from the runtime dependencies.
- Added a custom WGSL U-Net executor with automatic FP16 selection and a
deterministic FP32 fallback. - Added built-in topology descriptors for the current OIDN small and large RT
models, including clean auxiliary variants. - Reduced the reference Vite ESM bundle from approximately 168.8 KB to 32.4 KB
gzip compared with 0.3.5, a reduction of about 81%. - Reached a 27.6 ms median for a 512 x 512 Clean Aux Large inference on the
tested Apple GPU, versus 35.0 ms for the TensorFlow.js baseline (1.27x
faster). Performance depends on the browser, GPU, model, and tile size.
Added
- Model-driven graph planning and lifetime-aware activation-buffer reuse.
- Versioned
UNetModelSpecdescriptors, topology detection, and validation of
tensor names, layouts, data types, byte lengths, kernel shapes, bias shapes,
and graph channel flow. modelSpecinitialization option for future or custom OIDN model
topologies.npm run model:inspectfor model hashes, tensor signatures, and descriptor
compatibility checks.- Dynamic tile sizing with configurable minimum, initial, and maximum tile
sizes and a target GPU time. - GPU queue backpressure between tiles to keep cancellation and rendering
interaction responsive. - Runtime diagnostics through
getRuntimeInfo(), including the selected
engine, precision, model, kernel capabilities, tile state, and resource
statistics. - Per-layer GPU profiling through
profileNextExecution()and
getLastExecutionProfile()whentimestamp-queryis enabled. - Cross-version browser benchmarks with queue-complete timings, sampled output
validation, TFJS baseline comparison, and per-layer GPU profiles. - Explicit, idempotent resource disposal and resource lifecycle accounting.
- Automated model, graph, scheduler, resource leak, allocation rollback, and
late-async-cleanup tests.
Changed
- U-Net inference now runs directly in WGSL. The stable
autoengine selects
the native WGSL backend and no longer initializes TensorFlow.js. - FP16-capable devices retain TZA half-float weights and use short FP16 FMA
accumulation groups folded into FP32 accumulators. The final output remains
FP32. - Devices without
shader-f16automatically use native FP32 inference. - Convolution tensors and activations use a blocked four-channel layout with
channel-specialized shaders. - Decoder
upsample + concat + convpatterns are fused, and all network passes
for a tile are encoded into one command buffer. - Shape-independent pipelines are compiled asynchronously before initialization
resolves to avoid first-denoise shader compilation stalls. maxTileSizeis now a hard upper bound for the adaptive tile controller.- A shared
GPUDeviceuses FP16 only whenshader-f16was requested during
device creation; WebGPU features cannot be enabled afterward.
Migration notes
- No changes are required for basic
initUNetFromURLor
initUNetFromBufferusage. - Call
dispose()when a U-Net instance is no longer needed. - When supplying an existing
GPUDevice, requestshader-f16before creating
the device if FP16 inference is desired. - Set
dynamicTile: falseto restore fixed-size tiling.