stride3d / stride3d/stride

`PostProcessingEffects` renders a garbage frame when FXAA is enabled over `GraphicsCompositorHelper.CreateDefault` (disabled private range passes leave FXAA reading an unwritten render target)

Open
#3,316 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
7.8k
Forks
1.2k
Avg merge
2d 17h
Merged PRs (30d)
49

Description

Release Type: Official Release
Version: 4.3.0.2507
Platform(s): All backends (verified Vulkan + D3D11); code-only compositor path

Describe the bug
CreateDefault(enablePostEffects: true) calls PostProcessingEffects.DisableAll(), which also
disables the private rangeCompress/rangeDecompress passes — and nothing can re-enable
them (no public accessor). DrawCore then chooses the "anti-alias before bloom" branch based on

bool stableBloom = Bloom != null && Bloom.StableConvolution;   // Bloom.Enabled is NOT consulted

StableConvolution defaults to true, so the branch is taken even with bloom disabled. Inside
it, rangeCompress.Draw() is a no-op (disabled renderers draw nothing, not even a blit), FXAA
reads the unwritten scoped render target, and currentInput = compressed; discards the real
scene. Everything downstream runs on allocator garbage.

To Reproduce

  1. Code-only game, GraphicsCompositorHelper.CreateDefault(enablePostEffects: true).
  2. post.Antialiasing = new FXAAEffect { Enabled = true };
  3. Frame is garbage/black. Measured on a fixed camera: mean frame luma 0.4775 → 0.0755 with
    FXAA as the only change.

Expected behavior
FXAA over the default compositor antialiases the frame.

Additional context / workaround
One-line app-side workaround (verified: luma unchanged 0.4784 → 0.4807; edge-aliasing metrics
−39% to −52%): set post.Bloom.StableConvolution = false before enabling FXAA — that selects
the other DrawCore branch, which doesn't touch the disabled private passes. Upstream fix
shapes (any one suffices): gate the branch on Bloom.Enabled && Bloom.StableConvolution; have
DrawCore enable the range passes it is about to use (they're private plumbing — their
Enabled flag is meaningless as public state); or make DisableAll() leave them alone. A
defensive log/throw on drawing a disabled internal pass would have made this a one-line
diagnosis instead of a silent black frame. Happy to PR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at GraphicsCompositorHelper.CreateDefault and trace PostProcessingEffects.DisableAll into DrawCore, focusing on the private rangeCompress and rangeDecompress passes and the stable-bloom branch. Reproduce with FXAA enabled and bloom left at its default, then verify that the default compositor produces a valid antialiased frame rather than reading an unwritten render target.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
computer-graphics, game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.