Investigate: built-in ReShade-style user shader effects (load .fx effects in our post chain) #186

Closed
opened 2026-09-29 22:17:53 +00:00 by sky_line · 2 comments
Owner

Investigate a built-in, ReShade-style user shader post-processing stack: load community effect files and run them inside our own frame, instead of people injecting ReShade on top of the viewer.

Why built in beats injected ReShade

  • Correct inputs. Injected ReShade has to guess which depth buffer is the scene (often wrong on Vulkan, flips/jitters with TAA, breaks with render scale #181). We can hand effects the real linear scene, unjittered display depth, normals (thin G-buffer), motion vectors -- data ReShade rarely gets reliably.
  • Right place in the frame. Effects run on the world only: before the UI, HUDs, name tags and chat (injected ReShade blurs/colours the UI too). Choice of injection point: linear HDR (pre-tonemap), after tonemap, or after Lightbox grading.
  • Snapshots. Effects apply to Snapshot / 360 / high-res captures, which injected ReShade can't do at custom sizes.
  • No external install, no anti-cheat-style DLL injection questions, works the same on Linux and Windows.

What to investigate

  1. Effect language. Can we compile ReShade FX (.fx) directly? ReShade's effect compiler (reshadefx, BSD-3) emits SPIR-V. Check: license compatibility (LGPL viewer), build it as a 3p lib or vendor it, how much of the FX runtime semantics (techniques, passes, render targets, uniform annotations, source = special values like timer / frame count / mouse) we need to host. Alternative: our own simpler GLSL effect format (less compatible, less work).
  2. Runtime. Per-effect render targets and passes on the VK post chain (dynamic rendering, one pipeline per pass), texture resources from the effect package, hot reload, GPU timer per effect.
  3. Inputs mapping. ReShade's ReShade::BackBuffer / DepthBuffer conventions -> our HDR scene / tonemapped image / display depth (#181 recordDepthUpscale) / normals / motion. HDR vs LDR expectations of existing effects.
  4. UI. Effect list with enable/order, per-uniform controls generated from annotations, presets (save/load, share), probably inside Lightbox.
  5. Safety. User shaders run on the GPU only; guard against effects that hang the GPU (timeouts -> DEVICE_LOST, #135): per-effect disable on crash, safe-mode start.
  6. Compatibility sample. Try a handful of popular effect packs (e.g. qUINT, iMMERSE-free, SweetFX, prod80) and note what breaks.

Output

A short design note + a go/no-go and size estimate, then implementation tickets.

Related: Lightbox (#111, #112), render scale (#181), temporal pipeline (#84), photo later (#118), device-lost handling (#135).

Investigate a built-in, ReShade-style user shader post-processing stack: load community effect files and run them inside our own frame, instead of people injecting ReShade on top of the viewer. ### Why built in beats injected ReShade - **Correct inputs.** Injected ReShade has to guess which depth buffer is the scene (often wrong on Vulkan, flips/jitters with TAA, breaks with render scale #181). We can hand effects the real linear scene, **unjittered display depth, normals (thin G-buffer), motion vectors** -- data ReShade rarely gets reliably. - **Right place in the frame.** Effects run on the world only: before the UI, HUDs, name tags and chat (injected ReShade blurs/colours the UI too). Choice of injection point: linear HDR (pre-tonemap), after tonemap, or after Lightbox grading. - **Snapshots.** Effects apply to Snapshot / 360 / high-res captures, which injected ReShade can't do at custom sizes. - **No external install**, no anti-cheat-style DLL injection questions, works the same on Linux and Windows. ### What to investigate 1. **Effect language.** Can we compile ReShade FX (`.fx`) directly? ReShade's effect compiler (`reshadefx`, BSD-3) emits SPIR-V. Check: license compatibility (LGPL viewer), build it as a 3p lib or vendor it, how much of the FX runtime semantics (techniques, passes, render targets, `uniform` annotations, `source =` special values like timer / frame count / mouse) we need to host. Alternative: our own simpler GLSL effect format (less compatible, less work). 2. **Runtime.** Per-effect render targets and passes on the VK post chain (dynamic rendering, one pipeline per pass), texture resources from the effect package, hot reload, GPU timer per effect. 3. **Inputs mapping.** ReShade's `ReShade::BackBuffer` / `DepthBuffer` conventions -> our HDR scene / tonemapped image / display depth (#181 `recordDepthUpscale`) / normals / motion. HDR vs LDR expectations of existing effects. 4. **UI.** Effect list with enable/order, per-uniform controls generated from annotations, presets (save/load, share), probably inside Lightbox. 5. **Safety.** User shaders run on the GPU only; guard against effects that hang the GPU (timeouts -> DEVICE_LOST, #135): per-effect disable on crash, safe-mode start. 6. **Compatibility sample.** Try a handful of popular effect packs (e.g. qUINT, iMMERSE-free, SweetFX, prod80) and note what breaks. ### Output A short design note + a go/no-go and size estimate, then implementation tickets. Related: Lightbox (#111, #112), render scale (#181), temporal pipeline (#84), photo later (#118), device-lost handling (#135).
sky_line added this to the Slipstream project 2026-10-06 15:04:15 +00:00
Author
Owner

Investigation done. Design note + plan: epic #542.

Go / no-go:

  • Cel shading (first built-in, optional avatars-only): GO now. It's native: toon ramp in the shared lightSurface(), an avatar-id mask from the GPU-driven pre-pass, and a pre-TAA outline compute. It doesn't depend on the ReShade runtime (#549, #550).
  • ReShade FX compatibility: GO, contingent on P0 (#543). Vendor reshadefx (BSD-3; it emits SPIR-V directly, so no glslang/shaderc) and prove ≥ 90% of SweetFX / prod80 / reshade-shaders compile and validate. If it fails, fall back to our own GLSL format for built-ins only.

Key findings:

  • Default injection point: after FXAA/SMAA, before RLVa sphere and Lightbox final (reusing prepareFinal(force)). That keeps it pre-snapshot-capture and pre-HUD/UI.
  • displayDepth() is jittered at render scale 1 under TAA, so FX depth needs the depth-upscale unjitter at 1:1 too.
  • Our depth has no stencil, so FX needs its own stencil attachment.
  • Deferred G-buffer isn't used offscreen, so the avatar mask must come from the pre-pass, not G2.
  • BUFFER_WIDTH/HEIGHT are compile-time, so custom-size snapshots need a recompile + targets.

Licensing:

  • reshadefx is BSD-3 and ReShade.fxh is CC0, so both can ship.
  • ReShadeUI.fxh has no licence, so we write a clean-room copy.
  • qUINT / iMMERSE (no redistribution) and Lilium HDR (GPL-3) are user-installed only.
  • SweetFX / prod80 are MIT, but we bundle nothing in v1.

Leaving this open for the owner's decision.

Investigation done. Design note + plan: **epic #542**. **Go / no-go:** - **Cel shading (first built-in, optional avatars-only): GO now.** It's native: toon ramp in the shared `lightSurface()`, an avatar-id mask from the GPU-driven pre-pass, and a pre-TAA outline compute. It doesn't depend on the ReShade runtime (#549, #550). - **ReShade FX compatibility: GO, contingent on P0** (#543). Vendor reshadefx (BSD-3; it emits SPIR-V directly, so no glslang/shaderc) and prove ≥ 90% of SweetFX / prod80 / reshade-shaders compile and validate. If it fails, fall back to our own GLSL format for built-ins only. **Key findings:** - Default injection point: after FXAA/SMAA, before RLVa sphere and Lightbox final (reusing `prepareFinal(force)`). That keeps it pre-snapshot-capture and pre-HUD/UI. - `displayDepth()` is jittered at render scale 1 under TAA, so FX depth needs the depth-upscale unjitter at 1:1 too. - Our depth has no stencil, so FX needs its own stencil attachment. - Deferred G-buffer isn't used offscreen, so the avatar mask must come from the pre-pass, not G2. - `BUFFER_WIDTH/HEIGHT` are compile-time, so custom-size snapshots need a recompile + targets. **Licensing:** - reshadefx is BSD-3 and `ReShade.fxh` is CC0, so both can ship. - `ReShadeUI.fxh` has no licence, so we write a clean-room copy. - qUINT / iMMERSE (no redistribution) and Lilium HDR (GPL-3) are user-installed only. - SweetFX / prod80 are MIT, but we bundle nothing in v1. Leaving this open for the owner's decision.
Author
Owner

Investigation complete: go/no-go and design plan are written up in epic #542 (cel shading and ReShade FX phases are tracked as #543-#551).

Investigation complete: go/no-go and design plan are written up in epic #542 (cel shading and ReShade FX phases are tracked as #543-#551).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#186
No description provided.