Skip to content

fix(upscaling): guard OpenComposite conflict#79

Merged
alandtse merged 4 commits into
devfrom
fix/upscaling-opencomposite-guard
Jun 3, 2026
Merged

fix(upscaling): guard OpenComposite conflict#79
alandtse merged 4 commits into
devfrom
fix/upscaling-opencomposite-guard

Conversation

@alandtse

@alandtse alandtse commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Ports the OpenComposite upscaling conflict guard from
ParticleTroned/skyrim-community-shaders#1
(by @ColdBomb1) into Open Shaders.

When the OpenComposite VR shim (OpenXR-over-OpenVR) runs its own DLSS/FSR/DLAA
upscaling, our upscaler stacking on top causes double upscaling, double jitter,
and conflicting dynamic-resolution sizing — blur/ghosting/broken AA in the
headset. This detects OpenComposite's upscaling from opencomposite.ini and
makes our Upscaling feature stand down so OpenComposite owns the upscale.

What it does

  • Probes opencomposite.ini / opencomposite_ext.ini (loaded openvr_api.dll
    directory + CWD) for dlssEnabled, fsrEnabled, dlaaEnabled, fsrNativeAA,
    fsr3PostAAEnabled (section-agnostic).
  • When any is enabled (VR only): forces upscaleMethod /
    upscaleMethodNoDLSS to None, locks the Method picker with a warning, and
    short-circuits Load (IAT hook), PostPostLoad (render hooks),
    SetupResources, and LoadUpscalingSDKs (Streamline/FFX init).
  • GetUpscaleMethod() returns None while blocked; Save/Load/Restore
    re-assert None so the override persists.
  • Result is cached; lifecycle entry points force-refresh, per-frame callers read
    the cached bool.

Differences from the source PR (re-authored, not cherry-picked)

  • UI: our method picker is ImGui::Combo + BootSnapshot, not the source's
    SliderInt/UpscaleUiChoice. The lock + warning are re-authored against ours.
  • Foveated ordering: the PostPostLoad early-return is placed before
    foveatedRender.PostPostLoad(), and the GetUpscaleMethod check before the
    PerfMode branch, so our DLSS-foveated divergence stands down too.
  • Dropped the source PR's unused refresh-timestamp field (dead code).
  • Self-contained GetLoadedOpenVRDirectory() rather than reusing
    VRDetection::GatherDLLInfo (which also parses version info / enumerates the
    file — more work than a directory lookup needs). Possible future consolidation.
  • In-menu/log text is brand-neutral ("OpenComposite" / "Upscaling") per our
    naming rules; warning uses Util::Text::WrappedWarning.

Testing

  • Builds clean: BuildRelease.bat ALL (universal SE/AE/VR), exit 0, no warnings
    on Upscaling.cpp.
  • Not yet runtime-tested in a VR + OpenComposite session. The guard is gated
    on globals::game::isVR and only fires when opencomposite.ini actually has
    an upscaler enabled, so SteamVR and flat-screen users are unaffected. In-game
    VR validation recommended before merge.

Attribution

Original work by @ColdBomb1 in ParticleTroned#1.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Detect when an external VR compositor is applying upscaling and automatically lock the app's upscaling to "None", showing a warning.
    • Disable the upscaling method selector while blocked and persist the "None" selection until the external setting is cleared.
    • Prevent upscaling initialization and apply no upscaling during the blocked state to avoid conflicts.

When the OpenComposite VR shim runs its own DLSS/FSR/DLAA upscaling,
our upscaler stacking on top causes double upscaling, double jitter,
and conflicting dynamic-resolution sizing in VR. Detect OpenComposite's
upscaling from opencomposite.ini and stand down: force Method to None,
lock the picker, and skip our D3D11 device hook, render hooks, resource
setup, and Streamline/FidelityFX init while OpenComposite owns it.

VR-only and gated on globals::game::isVR; SteamVR users are unaffected.

Ported from ParticleTroned#1, re-authored
against our ImGui::Combo method picker and ordered ahead of
FoveatedRender setup so the foveated path stands down too. Dropped the
source PR's unused refresh-timestamp field.

Co-Authored-By: ColdBomb1 <ColdBomb1@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 2, 2026 05:47
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 748c0c82-52fb-4f6e-9f3a-968b708e04cd

📥 Commits

Reviewing files that changed from the base of the PR and between 0d8604d and 77fe93c.

📒 Files selected for processing (4)
  • src/Features/Upscaling.cpp
  • src/Features/Upscaling.h
  • src/Features/VR/OpenVRDetection.cpp
  • src/Features/VR/OpenVRDetection.h

📝 Walkthrough

Walkthrough

Detects OpenComposite upscaling by parsing nearby INI files, caches the result, and forces the local upscaling pipeline (UI, persistence, SDKs, hooks, resources) to NONE when OpenComposite is active.

Changes

OpenComposite Upscaling Blocker

Layer / File(s) Summary
Header: blocker declarations
src/Features/Upscaling.h
Add OpenVRDetection include, cached OpenCompositeUpscalingState, cache-valid flag, one-time logging flag, and private accessor/apply methods on Upscaling.
OpenComposite INI discovery & detection
src/Features/VR/OpenVRDetection.cpp
Locate opencomposite*.ini near loaded openvr_api.dll and cwd, parse boolean DLAA/DLSS/FSR keys, track which config enabled each, and implement detection helpers.
Detection API surface
src/Features/VR/OpenVRDetection.h
Declare OpenCompositeUpscalingState (active, settingName, configPath) and DetectOpenCompositeUpscaling() API.
Blocker: caching, apply, UI, persistence, lifecycle gates
src/Features/Upscaling.cpp
Cache/refresh blocker state, implement GetOpenCompositeUpscalingBlocker() and ApplyOpenCompositeUpscalingBlocker(), lock UI Method combo to None with tooltip/warning, persist/load forced None, and gate Load/DataLoaded/PostPostLoad/SetupResources/LoadUpscalingSDKs/GetUpscaleMethod to skip upscaling initialization when blocked.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • alandtse/open-shaders#42: Related changes to GetUpscaleMethod() and perf-mode / method-selection routing that interact with the new OpenComposite blocker.

Poem

🐰 In INI fields I softly tread,
I find the flags where upscaling's led,
If OpenComposite takes the stage,
I set our shader ramparts to engage—None on every page. 🎮

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(upscaling): guard OpenComposite conflict' directly matches the main change: adding an OpenComposite upscaling conflict guard that forces upscaling to None when OpenComposite settings are detected in VR. It is concise and clearly summarizes the primary change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/upscaling-opencomposite-guard

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.22.0)

OpenGrep fatal error (exit code 2): [00.14][ERROR]: Error: exception Unix_error: No such file or directory stat src/Features/VR/OpenVRDetection.h
Raised by primitive operation at UTmp.replace_named_pipe_by_regular_file_if_needed in file "libs/commons/UTmp.ml", line 145, characters 8-27
Called from Scan_CLI.replace_target_roots_by_regular_files_where_needed.(fun) in file "src/osemgrep/cli_scan/Scan_CLI.ml", lines 1086-1087, characters 19-65
Called from List_.fast_map in file "libs/commons/List_.ml", line 81, characters 17-20
Called

🔧 Infer (1.2.0)
src/Features/Upscaling.cpp

Usage Error: Failed to execute compilation command:
'/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/clang/install/bin/clang++'
-c src/Features/Upscaling.cpp -o
/tmp/coderabbit-infer/76c824e8ea9ae8b0/file.o

Error message:
clang++: error: no such file or directory: 'src/Features/Upscaling.cpp'

*** Infer needs a working compilation command to run.

src/Features/VR/OpenVRDetection.cpp

Usage Error: Failed to execute compilation command:
'/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/clang/install/bin/clang++'
-c src/Features/VR/OpenVRDetection.cpp -o
/tmp/coderabbit-infer/b9e2bcb2e71809a1/file.o

Error message:
clang++: error: no such file or directory: 'src/Features/VR/OpenVRDetection.cpp'

*** Infer needs a working compilation command to run.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a VR-only guard that detects when the OpenComposite shim is doing its own DLSS/FSR/DLAA upscaling (by probing opencomposite.ini / opencomposite_ext.ini) and forces the Upscaling feature to stand down so the two don't stack. The guard short-circuits lifecycle entry points (Load, PostPostLoad, SetupResources, LoadUpscalingSDKs, DataLoaded), forces upscaleMethod/upscaleMethodNoDLSS to None across Save/Load/Restore, and locks the Method picker in the UI with a warning. Results are cached and refreshed only on lifecycle entry points so per-frame callers (GetUpscaleMethod, DrawSettings) stay cheap.

Changes:

  • New anonymous-namespace helpers in Upscaling.cpp to enumerate OpenComposite config candidates and parse boolean upscaling keys section-agnostically.
  • Upscaling::ApplyOpenCompositeUpscalingBlocker / GetOpenCompositeUpscalingBlocker with a cached OpenCompositeUpscalingBlocker struct; wired into Load/PostPostLoad/SetupResources/LoadUpscalingSDKs/DataLoaded/Save/Load/Restore and GetUpscaleMethod.
  • UI: disables the Method combo and prints a WrappedWarning plus tooltip when the guard fires.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Features/Upscaling.h Declares the OpenCompositeUpscalingBlocker struct, cache fields, and getter/applier members.
src/Features/Upscaling.cpp Implements config probing, the guard apply/get methods, lifecycle short-circuits, and UI lock + warning.

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

No actionable suggestions for changed features.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Features/Upscaling.cpp`:
- Around line 311-326: GetOpenCompositeConfigCandidates currently only adds
opencomposite.ini from the GetLoadedOpenVRDirectory but omits
opencomposite_ext.ini; update the block that checks loadedOpenVRDirectory in
GetOpenCompositeConfigCandidates so that after AddUniquePath(candidates,
loadedOpenVRDirectory / L"opencomposite.ini") you also call
AddUniquePath(candidates, loadedOpenVRDirectory / L"opencomposite_ext.ini") (use
the same pattern as the currentDirectory block and keep using
GetLoadedOpenVRDirectory and AddUniquePath to ensure both files are discovered
next to openvr_api.dll).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d97ab092-0d82-4f85-9b56-643138724dcb

📥 Commits

Reviewing files that changed from the base of the PR and between 629b1d2 and 0d8604d.

📒 Files selected for processing (2)
  • src/Features/Upscaling.cpp
  • src/Features/Upscaling.h

Comment thread src/Features/Upscaling.cpp Outdated
Extract the opencomposite.ini probing/parsing out of Upscaling.cpp into
VRDetection::DetectOpenCompositeUpscaling, where it sits alongside the
existing OpenComposite runtime detection. Upscaling keeps only the
force-to-None policy and the lifecycle/UI gating, dropping ~230 lines
and its parallel blocker struct in favor of the shared VRDetection type.

Consolidate the loaded openvr_api.dll path lookup into one shared helper
(GatherDLLInfo previously had its own copy), and search
opencomposite_ext.ini next to the DLL too, not just in the CWD.

Co-Authored-By: ColdBomb1 <ColdBomb1@gmail.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

✅ A pre-release build is available for this PR:
Download

Address self-review of the OpenComposite guard: condense the verbose
multi-line comments to one-liners (keeping only non-obvious "why"),
drop the redundant re-Apply in DrawSettings (the method combo is
already disabled when blocked, so the value can't change), and
short-circuit the per-frame GetUpscaleMethod blocker check on
globals::game::isVR so non-VR pays zero per-frame cost.

No behavior change: the blocker was already inactive on non-VR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 02:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread src/Features/VR/OpenVRDetection.cpp Outdated
…g enables it

ReadOpenCompositeUpscalingSettings probes multiple candidates (DLL dir +
CWD, opencomposite.ini + opencomposite_ext.ini). UpdateOpenCompositeSettingValue
overwrote unconditionally, so a later file's explicit false clobbered an
earlier file's true and the guard could miss an active upscaler. Only an
explicit true now updates the setting (and records the enabling file's
path), matching the block-if-any-enabled intent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alandtse alandtse merged commit cac323d into dev Jun 3, 2026
21 checks passed
@alandtse alandtse deleted the fix/upscaling-opencomposite-guard branch June 3, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants