Skip to content

ppikkuaho/reshade-vulkan-metal-port

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

reshade-vulkan-metal-port

A set of Windows ReShade post-processing effects reimplemented as a portable Vulkan compute pipeline that runs on Apple GPUs via MoltenVK, with a self-validating test harness that cannot pass on a no-op GPU.

What it is

reshade-vulkan-metal-port is a headless host that runs a ReShade-style post-processing chain as Vulkan compute shaders. ReShade and its FX shaders are Windows/Direct3D-OpenGL tools; this project takes three of those effects, ports them to Vulkan GLSL compute, and drives them from a standalone command-line host with no windowing system and no graphics API beyond compute. On macOS the Vulkan path executes on Metal through MoltenVK, so the same shaders run on Apple GPUs unmodified.

The hard part is the bloom. A wide-radius bloom is normally a wide-tap blur whose cost grows with the radius. Here it is built instead as a separable second-order Bessel IIR filter run forward and backward along each axis, so the blur radius is large but the cost is independent of the radius and the forward/backward pairing makes the response zero-phase (no spatial shift). To push bloom energy above 1.0 through 8-bit intermediate textures without clipping, bright values are range-compressed with a pack/unpack scheme that stores an exponent bucket in the alpha channel. That is recursive-filter and numeric-precision engineering on the GPU, sitting on top of the descriptor-set and pipeline-barrier plumbing needed to sequence a multi-pass compute graph through a windowless Vulkan host.

The effects are hand-ports of existing open-source shaders; the original algorithms are preserved and the language, descriptor bindings, and multi-pass dispatch structure were rewritten for Vulkan compute. The upstreams and their licenses are listed in shaders/ATTRIBUTION.md.

The pipeline has two modes. The color mode runs a single pass that combines a perceptual saturation adjustment (Colourfulness) with chroma/luma Sobel edge detection (Comic). The full mode adds the bloom: a soft-knee prefilter, four directional IIR passes (horizontal forward and backward, vertical forward and backward), and an additive composite.

                                    ┌─ H-fwd ─ H-bwd ─ V-fwd ─ V-bwd ─┐
  input ─ prefilter ─(soft knee)────┤        (Bessel IIR blur)        ├─ compose ─ output
        └──────────────────(color)──────────────────────────────────-┘

Technical approach

  • Compute-only Vulkan. The host (src/) creates a headless Vulkan instance and device with a single compute queue. There is no surface, swapchain, or window. Each effect is a compute program; intermediate results live in RGBA8 storage images kept in GENERAL layout so every pass can both sample its input and store its output, with a memory barrier between passes. The four directional Bessel passes are one shader specialized at compile time via -DBESSEL_PASS rather than four copy-pasted files.
  • Bessel-IIR bloom. Rather than a fixed-tap Gaussian, the blur runs a 2nd-order IIR filter forward and backward along each axis, with a 128-tap warm-up overscan that primes the recursive state before the first store. The alpha-channel exponent pack/unpack lets >1.0 bloom energy survive the 8-bit intermediates.
  • MoltenVK on macOS. The host enables the Vulkan portability enumeration so the loader will surface MoltenVK, and requests VK_KHR_portability_subset on the device. No Metal code is written by hand; MoltenVK translates the compute dispatches.

A test that cannot pass trivially

The selftest gate is built so that a no-op GPU cannot fool it. Before the compute passes run, the result image is seeded with a passthrough copy of the input. A real effect overwrites that buffer, so the pixel diff against the original input is non-zero (PASS); a passthrough or a no-op driver leaves the output equal to the input, so the diff is exactly zero (FAIL). The harness also runs the chain twice and gates on a bit-identical FNV-1a digest, so a non-deterministic result fails too.

The gate was then validated against itself: linking the host against a no-op Vulkan shim makes selftest correctly fail, and against a shim that mutates a single pixel makes it correctly pass. That confirms the test actually tests something rather than always passing.

selftest builds the test image procedurally from one of five fixture patterns (gradient, checker, a bright disc on a dark field, a flat dark field, or color bands), so the whole pipeline exercises end to end with no external input.

Status

The host is ~1,900 lines of C++17 and GLSL compute. Verified as far as a host without a GPU allows (2026-05-29):

  • All seven SPIR-V modules (the color/edge pass, the bloom prefilter and compose, and the four Bessel filter specializations) compile with glslangValidator and pass spirv-val.
  • The complete C++ host compiles under -Wall -Wextra with no warnings and links across all translation units.
  • The CLI and the full multi-pass orchestration (SPIR-V loading, pipeline creation, pass sequencing, image I/O, diff statistics, and the pass/fail gate) run end to end, CPU-validated through the Vulkan shim described above.

GPU validation on Apple hardware is the one remaining step: it requires a machine with the Vulkan SDK and MoltenVK (the build instructions below), which this build environment did not have, so the actual GPU pixel output has not yet been observed.

Build

Requires a C++17 compiler, CMake 3.16+, and the Vulkan SDK (which provides the Vulkan loader, glslangValidator, and, on macOS, MoltenVK). Set VULKAN_SDK in the environment first.

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

The build compiles the GLSL in shaders/ to SPIR-V (the Bessel filter is compiled four times, once per directional pass) and links the host.

Run

# Synthetic self-test: run the chain over a generated fixture and report the
# pixel delta against the input.
./build/reshade-vulkan-metal-port selftest --shaders build/shaders \
    --pattern highlight --mode full

# Process an image (binary PPM in, binary PPM out).
./build/reshade-vulkan-metal-port run --shaders build/shaders \
    --in input.ppm --out output.ppm --mode full

Use --mode color for the color/edge pass only, skipping the bloom chain. On a conformant (non-MoltenVK) driver, set RVMP_PORTABILITY=0 to disable the portability path.

Notes

  • Images are read and written as binary PPM (P6) to keep the host free of external image-decoding dependencies.
  • License: the host code and build system are MIT. The shaders are derivative works of third-party ReShade FX shaders under permissive (BSD/MIT) licenses; see shaders/ATTRIBUTION.md and NOTICE. The CC BY-SA tonal pass from the original preset is intentionally omitted so the project is cleanly MIT-distributable.

About

Windows ReShade post-processing effects reimplemented as a portable Vulkan compute pipeline that runs on Metal via MoltenVK, including a multi-pass separable Bessel-IIR bloom.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors