Skip to content

feat(VR): DLSSperf — render engine at upscaled resolution#2357

Closed
alandtse wants to merge 5 commits into
community-shaders:devfrom
alandtse:pr2-dlssperf
Closed

feat(VR): DLSSperf — render engine at upscaled resolution#2357
alandtse wants to merge 5 commits into
community-shaders:devfrom
alandtse:pr2-dlssperf

Conversation

@alandtse
Copy link
Copy Markdown
Collaborator

@alandtse alandtse commented May 16, 2026

Summary

VR-only opt-in feature that hooks BSOpenVR::GetRenderTargetSize so the entire engine pipeline allocates render targets at upscaled-render resolution (RenderRes = HMD recommended size / DLSS quality scale) while DLSS writes its upscaled output into a private DisplayRes texture. The legacy "engine renders at DisplayRes, then we upscale down" round-trip disappears.

User-visible benefit: substantial VRAM and bandwidth savings proportional to the quality-mode scale ratio. Makes Ultra Performance preset (0.33×) viable at 6K HMDs on mid-range GPUs, instead of a low-resolution DLAA fallback. Game menus also stop being occluded by the upscaler output.

What changes

Four commits, organized around the integration boundary:

Commit Files What
1 src/Features/DLSSperf.{h,cpp}, features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl The worker class — RT-size hook + Post-chain hybrid (BeginPostIntercept/EndPostIntercept) + bilinear downscale shader
2 src/Globals.{h,cpp} dlssPerf instance + ID3D11DeviceContext::Draw vfunc-13 hook for the scene-fade overlay
3 src/Hooks.cpp BSGraphics::Renderer::UpdateViewPort viewport-correction hook + RT enlargement gate in BSShaderRenderTargets::Create + 6 MaybeEnlargeRT injections + runtime E8 scanner for unhooked CreateRenderTarget call sites
4 src/Features/Upscaling.{h,cpp} Settings::enableDLSSperf field + JSON load/save + UI checkbox (VR + DLSS only, restart required) + jitter branch in ConfigureUpscaling + Main_PostProcessing HandlePostProcessing wrap

Decoupling from the original PR

@YtzyFvra's #2096 routed DLSSperf through DlssEnhancer::Bridge::BootSequence. This PR removes that coupling so DLSSperf can ship without the larger DlssEnhancer framework:

  • Quality mode is read directly from Upscaling::Settings::qualityMode at hook-install time (BSShaderRenderTargets::Create runs after settings load)
  • Scale is computed via ffxFsr3GetUpscaleRatioFromQualityMode — the same helper Upscaling.cpp already uses in ConfigureUpscaling

Bot review fix from #2096 baked in

Copilot flagged that savedVP was uninitialized before RSGetViewports in the Draw vfunc hook. Zero-init D3D11_VIEWPORT savedVP{} and skip the restore when numVP == 0.

What's NOT in this PR (intentionally)

  • The DlssEnhancer framework, subrect/foveated rendering (PR-3 of the decomposition, on my fork)
  • The original PR's unrelated refactors that share its diff: TruePBR instance→pointer migration, ScreenshotFeature removal from features namespace, RefreshTES cleanup, TESObjectLAND_SetupMaterial / BSLightingShader_SetupMaterial hook changes — none of these are DLSSperf-specific

Risks for review

  1. Main_PostProcessing wrap interaction with HDRDisplay: the wrap sits between HDRDisplay::RedirectFramebuffer and RestoreFramebuffer. Order matters; not tested live with both enabled. Worth a VR test session.
  2. Runtime E8 scanner in Hooks::Install writes to the SKSE trampoline. If another PR or feature also patches the same CreateRenderTarget call sites between the named thunks, ordering matters. Currently no known conflict.
  3. enableDLSSperf requires a game restart to take effect (engine RT allocations happen once at init). UI surfaces a "Requires restart" warning.

Test plan

  • Plugin C++ compile passes (MSBuild ClCompile, exit 0, no errors/warnings)
  • CI shader validation (Flatrim + VR)
  • CI build (vs2022 + vs2026)
  • VR validation needed: enable in Skyrim VR, verify DLSS still produces correct output, no menu occlusion regression, no fade-overlay artifacts at scene transitions, no flicker on quality-mode change + restart
  • Verify testTexture + refraTempTex lifecycle when toggling at runtime (load game with on, change setting off, restart, verify clean state)

Credits

Decomposed from @YtzyFvra's #2096 (PR-2 of 4). All DLSSperf design/implementation is theirs; this PR adapts to ship standalone (Bridge decoupled, scoped to just the DLSSperf hunks of the original PR's diff). Co-authored on commits.

See DLSS-PR-PLAN.md for the full decomposition strategy.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added DLSSperf VR mode: enables upscaled rendering with lower VRAM/bandwidth use while preserving post-processing and refraction visuals.
    • Hybrid post-processing flow to maintain UI/tonemap/refraction correctness when using VR upscaling.
  • Configuration

    • New VR-only toggle to enable DLSSperf optimization (requires game restart).

Review Change Stack

alandtse and others added 4 commits May 16, 2026 00:36
…upled from Bridge)

DLSSperf hooks BSOpenVR::GetRenderTargetSize so all engine render
targets allocate at RenderRes while DLSS writes its upscaled output
to a private DisplayRes texture. The legacy UpscaleRT round-trip
disappears, VRAM/bandwidth drop, and game menus stop being occluded
by the upscaler output. The Post chain hybrid (BeginPostIntercept /
EndPostIntercept) swaps in the DisplayRes texture + a fake DSV
around tonemap/refraction so the HDR pyramid builds from anti-
aliased content.

This commit lifts the standalone files only:
- src/Features/DLSSperf.{h,cpp}
- features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl

Decoupling from the original PR's DlssEnhancer::Bridge:
- Quality mode is read directly from Upscaling::Settings at hook-
  install time (BSShaderRenderTargets::Create runs after settings
  load).
- Scale is computed via ffxFsr3GetUpscaleRatioFromQualityMode, the
  same helper Upscaling.cpp uses in ConfigureUpscaling.

Follow-up commits will land the Globals/Hooks/Upscaling integration
hunks and a user-facing enablement toggle.

Decomposed from community-shaders#2096 (PR-2 of 4); see DLSS-PR-PLAN.md.

Co-Authored-By: YtzyFvra <59631290+YtzyFvra@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the dlssPerf instance to globals::features and registers the
ID3D11DeviceContext::Draw vfunc-13 detour. The detour is no-op
unless DLSSperf's RT-size hook is live AND its post chain just
finished, in which case it forces the scene-fade overlay (the
characteristic Draw(30)) to render at displayRes — fixing the
"black stamp" partial-screen artifact where a renderRes VP would
otherwise stamp onto the displayRes kTOTAL.

Decoupled extract from community-shaders#2096 (PR-2 of 4); covers only the DLSSperf-
specific Globals additions, not the unrelated TruePBR/Screenshot/
RefreshTES refactors that share the PR's diff.

Fix vs original PR: zero-init savedVP and skip the restore when
numVP=0 (Copilot review finding — RSGetViewports does not write
savedVP if no viewport was set).

Co-Authored-By: YtzyFvra <59631290+YtzyFvra@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the 3 DLSSperf-specific hook surfaces:

1. BSGraphics::Renderer::UpdateViewPort detour — corrects the engine's
   viewport whenever it disagrees with our enlarged RT dimensions:
   compress displayRes→renderRes for normal world/depth draws, expand
   renderRes→displayRes after the Post chain finishes (UI + submit-prep).
   No-op until DLSSperf::IsHookActive flips on.

2. BSShaderRenderTargets::Create — gates DLSSperf::InstallRenderTarget
   SizeHook on Upscaling::Settings::enableDLSSperf (replacement for the
   PR's DlssEnhancer::Bridge::BootSequence path), enlarges the Color RTs
   in the post-chain whitelist (kIMAGESPACE_TEMP_COPY/kTOTAL/kMENUBG)
   to displayRes via DLSSperf_MaybeEnlargeRT, and calls SetupResources
   manually since DLSSperf isn't a Feature in the registry.

3. Runtime E8 scanner in Hooks::Install that finds every unhooked
   CreateRenderTarget call site within Create() and re-writes them
   through DLSSperf_CreateRT_Thunk so enlargement applies universally,
   not just to the 6 sites with explicit per-target thunks.

Also injects DLSSperf_MaybeEnlargeRT into all 6 existing
CreateRenderTarget thunks (Main, Normals, NormalsSwap, MotionVectors,
RefractionNormals, UnderwaterMask).

The new field Upscaling::Settings::enableDLSSperf (added in the next
commit) provides the user-facing gate; without it set, none of this
code path activates.

Decoupled extract from community-shaders#2096 (PR-2 of 4); skips the unrelated TruePBR/
TESObjectLAND/BSLightingShader refactor hunks that share the PR's diff.

Co-Authored-By: YtzyFvra <59631290+YtzyFvra@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three Upscaling-side changes complete the DLSSperf wiring:

1. ConfigureUpscaling jitter branch — when DLSSperf::IsHookActive,
   RTs are already at RenderRes so the DRS-style scale collapses to
   identity. Jitter is still computed at the real DisplayRes phase
   ratio so DLSS has enough sub-pixel diversity for the upscale.

2. Main_PostProcessing wrap — replaces the bare engine func() call
   with a HandlePostProcessing lambda when DLSSperf::ShouldHandlePost.
   The hybrid Post performs a two-layer struct swap so tonemap +
   refraction read the DisplayRes testTexture instead of small kMAIN.

3. Upscaling::Settings::enableDLSSperf — new opt-in bool with JSON
   load/save (added to NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT)
   and a UI checkbox under Streamline settings, gated on VR + DLSS.
   Restart required (matches the engine init lifecycle of the hook).

DLSSperf.cpp now includes Upscaling.h so the InstallRenderTargetSize
Hook can read settings.qualityMode at install time.

Plugin C++ compile passes (MSBuild ClCompile target, exit 0). Full
link blocked locally by an environmental crash in the FFX shader
permutation generator — unrelated to PR-2 changes; reproduces on
clean upstream/dev.

Decoupled extract from community-shaders#2096 (PR-2 of 4); skips the DlssEnhancer
route and per-eye sharpening branches that share the PR's diff.

Co-Authored-By: YtzyFvra <59631290+YtzyFvra@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b37fe47f-4db2-480f-bac3-79df4f9067b7

📥 Commits

Reviewing files that changed from the base of the PR and between 2fa3233 and cce13c7.

📒 Files selected for processing (1)
  • src/Features/DLSSperf.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Features/DLSSperf.cpp

📝 Walkthrough

Walkthrough

Adds DLSSperf: a VR-only path that captures HMD resolution, overrides engine RT sizes to an upscaled render-eye, allocates D3D11 test/refraction/fake-DS resources, intercepts tonemap/refraction/UI/post passes to render into a test texture, then downsamples it back to the engine main RT.

Changes

DLSSperf VR Render-Target Optimization

Layer / File(s) Summary
DLSSperf interface, state and downscale shader
src/Features/DLSSperf.h, features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl
Defines DLSSperf public API, internal hook/state declarations, D3D11 resource holders, and adds a 3×3 box-filter pixel shader for downscaling.
Render-target size override and resource allocation
src/Features/DLSSperf.cpp (GetRenderTargetSize_Hook, SetupResources)
Captures HMD sizes, computes render-eye dimensions from quality mode, installs the render-target-size hook, and allocates test/refraction textures, fake DSV, shaders, and linear sampler.
Tonemap and refraction interception
src/Features/DLSSperf.cpp (TonemapRender_Hook, RefractionRender_Hook)
Tonemap hook swaps main SRVs/DSVs to read from the test texture; refraction hook replays refraction rendering into the test RTV with save/restore of OM and viewport state.
UI pass and post-chain interception
src/Features/DLSSperf.cpp (UIPassDispatch_Hook, PlayerViewRender_Hook, BeginPostIntercept, EndPostIntercept)
UI hook swaps kMAIN DS views and forces viewport for renderMode==24; player-view hook clears postChainDone; post-chain hooks swap kMAIN_COPY DSV and toggle post-intercept flags.
Downscale draw and post-processing orchestration
src/Features/DLSSperf.cpp (DownscaleToKMain, HandlePostProcessing, DrawSettings)
Performs full-screen downscale from test texture to engine kMAIN RTV with extensive D3D state save/restore; orchestrates copy→downscale and wraps engine post with DS-swap scope.
Upscaling setting, UI and ConfigureUpscaling changes
src/Features/Upscaling.cpp, src/Features/Upscaling.h
Adds enableDLSSperf setting and VR-only checkbox; modifies ConfigureUpscaling to compute jitter/projection from DLSSperf dimensions and routes post-processing through DLSSperf handler when active.
Global feature instance and Draw hook
src/Globals.cpp, src/Globals.h
Adds global dlssPerf instance and installs an ID3D11DeviceContext::Draw hook that temporarily sets a display-resolution viewport for targeted draws during DLSSperf post phases.
Renderer hooks, RT enlargement and call-site patching
src/Hooks.cpp
Adds UpdateViewPort detour to rewrite viewport for DLSSperf; wires RT enlargement into shader render-target create thunks; records original CreateRenderTarget address and patches unhooked call sites via runtime byte scanning to route through DLSSperf thunk.

Sequence Diagram(s)

sequenceDiagram
  participant Engine as Engine
  participant DLSSperf as DLSSperf
  participant TestTex as TestTexture
  participant MainRT as MainRenderTarget

  Engine->>DLSSperf: GetRenderTargetSize() override (HMD size)
  DLSSperf->>DLSSperf: Compute render-eye dimensions
  Engine->>DLSSperf: TonemapRender_Hook call
  DLSSperf->>TestTex: Swap SRV/DSV, render tonemap into TestTexture
  Engine->>DLSSperf: RefractionRender_Hook call
  DLSSperf->>TestTex: Replay refraction -> TestTexture
  Engine->>DLSSperf: UIPassDispatch_Hook (renderMode==24)
  DLSSperf->>DLSSperf: Swap fake DSV, force viewport
  Engine->>DLSSperf: Main PostProcessing entry
  DLSSperf->>DLSSperf: BeginPostIntercept -> copy test→refra, DownscaleToKMain
  DLSSperf->>TestTex: Sample TestTexture (BilinearCopyPS)
  DLSSperf->>MainRT: Draw downscaled result into MainRT
  DLSSperf->>DLSSperf: EndPostIntercept (restore DS/viewport)
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

Suggested Reviewers

  • doodlum
  • SkrubbySkrubInAShrub
  • jiayev

Poem

🐰 A rabbit skips through pixels bright and fair,
Swapping depth and views with nimble care.
It paints a tiny test texture in VR air,
A box-filter hops, then downscales with a flair.
DLSSperf hums—rendered worlds grow light and rare.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.73% 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 clearly summarizes the main feature: implementing DLSSperf to render the VR engine at upscaled resolution, which is the primary change across all modified files.
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 unit tests (beta)
  • Create PR with unit tests

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.20.0)

OpenGrep fatal error (exit code 2): [00.12][ERROR]: Error: exception Unix_error: No such file or directory stat src/Features/DLSSperf.cpp
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 from Sc


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.

@github-actions
Copy link
Copy Markdown

No actionable suggestions for changed features.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/Globals.cpp (1)

390-437: 💤 Low value

Consider extracting the magic vertex count to a named constant.

The VertexCount == 30 check identifies the scene-fade overlay draw. While the block comment explains this, a named constant would make the intent clearer and simplify future searches if this value ever needs to change across game versions.

+	// Vertex count for the engine's scene-fade overlay (fade-in/fade-out effect).
+	// Identified via reverse engineering; may need verification on future game updates.
+	static constexpr UINT kFadeOverlayVertexCount = 30;
+
 	struct ID3D11DeviceContext_Draw
 	{
 		static void thunk(ID3D11DeviceContext* This, UINT VertexCount, UINT StartVertexLocation)
 		{
-			if (VertexCount == 30 && globals::game::isVR) {
+			if (VertexCount == kFadeOverlayVertexCount && globals::game::isVR) {
🤖 Prompt for 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.

In `@src/Globals.cpp` around lines 390 - 437, Replace the magic literal 30 in the
ID3D11DeviceContext_Draw::thunk vertex-count check with a well-named constant
(e.g., FADE_OVERLAY_VERTEX_COUNT or kFadeOverlayVertexCount) declared near the
struct or in the globals/features dlssPerf scope; update the condition from
VertexCount == 30 to VertexCount == FADE_OVERLAY_VERTEX_COUNT and use the
constant name in any related comments so the purpose is explicit and easy to
find/modify later.
features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl (1)

16-20: ⚡ Quick win

Avoid per-pixel GetDimensions in this fullscreen pass.

Move srcSize to a constant buffer or push constants instead of querying dimensions in every fragment. This optimization saves per-pixel overhead in a hot path with negligible setup cost. Before deployment, validate the shader with hlslkit.

🤖 Prompt for 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.

In `@features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl` around lines 16 - 20,
The fragment shader currently calls SourceTex.GetDimensions per-pixel inside
main(PS_INPUT) to compute srcSize and texelSize; move srcSize (or directly
texelSize) into a constant buffer or push constants and read that in main
instead of calling GetDimensions, update uses of srcSize/texelSize in main to
use the CB/push constant values, and validate the updated BilinearCopyPS shader
with hlslkit before deployment to ensure correctness.
🤖 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/DLSSperf.cpp`:
- Around line 41-44: Validate and clamp the config-derived qualityMode and the
resulting scale before using them to compute renderEyeWidth/renderEyeHeight:
read globals::features::upscaling.settings.qualityMode into qualityMode, ensure
it is within the valid FfxFsr3QualityMode range (clamp to the min/max enum
values), call ffxFsr3GetUpscaleRatioFromQualityMode and verify the returned
scale is > 0 and sane (e.g., within expected bounds); if invalid, choose a safe
fallback (set scale = 1.0 or a default qualityMode) and log/error as appropriate
so the division w/scale and h/scale cannot produce zero/negative or overflow
sizes. Ensure all references to qualityMode,
ffxFsr3GetUpscaleRatioFromQualityMode, renderEyeWidth, and renderEyeHeight are
updated to use the validated/clamped values.
- Around line 540-650: DownscaleToKMain currently sets
bilinearCopyVS/bilinearCopyPS and a PS sampler (slot 0) but does not
save/restore the previous VS/PS/sampler bindings; before changing shaders and
samplers, query and store the current VS/PS (use VSGetShader/PSGetShader) and
the sampler at slot 0 (use PSGetSamplers), then after drawing restore them with
VSSetShader/PSSetShader and PSSetSamplers (restore the original sampler array
and count), releasing any COM refs you acquired (same pattern used for
savedGS/savedHS/etc.); ensure you reference bilinearCopyVS, bilinearCopyPS, and
linearSampler when locating the change points.

---

Nitpick comments:
In `@features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl`:
- Around line 16-20: The fragment shader currently calls SourceTex.GetDimensions
per-pixel inside main(PS_INPUT) to compute srcSize and texelSize; move srcSize
(or directly texelSize) into a constant buffer or push constants and read that
in main instead of calling GetDimensions, update uses of srcSize/texelSize in
main to use the CB/push constant values, and validate the updated BilinearCopyPS
shader with hlslkit before deployment to ensure correctness.

In `@src/Globals.cpp`:
- Around line 390-437: Replace the magic literal 30 in the
ID3D11DeviceContext_Draw::thunk vertex-count check with a well-named constant
(e.g., FADE_OVERLAY_VERTEX_COUNT or kFadeOverlayVertexCount) declared near the
struct or in the globals/features dlssPerf scope; update the condition from
VertexCount == 30 to VertexCount == FADE_OVERLAY_VERTEX_COUNT and use the
constant name in any related comments so the purpose is explicit and easy to
find/modify later.
🪄 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 Plus

Run ID: dcf4007f-3775-494b-874b-020b8393503a

📥 Commits

Reviewing files that changed from the base of the PR and between 8c9b18c and 2fa3233.

📒 Files selected for processing (8)
  • features/DLSSperf/Shaders/DLSSperf/BilinearCopyPS.hlsl
  • src/Features/DLSSperf.cpp
  • src/Features/DLSSperf.h
  • src/Features/Upscaling.cpp
  • src/Features/Upscaling.h
  • src/Globals.cpp
  • src/Globals.h
  • src/Hooks.cpp

Comment thread src/Features/DLSSperf.cpp Outdated
Comment thread src/Features/DLSSperf.cpp
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

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

Two CodeRabbit Major findings on scs#2357:

1. InstallRenderTargetSizeHook: validate qualityMode + scale before
   division. Clamp the raw setting to FfxFsr3QualityMode's [0..4]
   range, then verify ffxFsr3GetUpscaleRatioFromQualityMode returned
   a finite positive value. Fail closed (early-return without
   setting hookActive) if the FFX call returns 0 / inf / NaN — that
   would otherwise propagate to bogus renderEye dimensions and
   silently mis-size every engine RT. Logs the offending values for
   diagnosis.

2. DownscaleToKMain: save and restore VS, PS, and PS sampler 0
   alongside the existing GS/HS/DS/blend/depth-stencil/viewport
   chain. The function runs immediately before enginePost(); leaving
   our shader bound risks subsequent passes inheriting it if they
   don't explicitly set every slot. Pattern matches what
   VRStereoOptimizations does. Adds the corresponding Release()
   calls to the cleanup tail.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@alandtse
Copy link
Copy Markdown
Collaborator Author

Addressed CodeRabbit's two Majors in cce13c7:

  1. DLSSperf.cpp:44InstallRenderTargetSizeHook now clamps qualityMode to FFX's [0..4] range and verifies ffxFsr3GetUpscaleRatioFromQualityMode returned a finite positive value. Fail-closed (early-return without setting hookActive) on bad scale; logs the offending values for diagnosis. A corrupt JSON or a future FFX SDK that reshuffles the enum would otherwise silently mis-size every engine RT.

  2. DLSSperf.cpp:DownscaleToKMain — added VS, PS, and PS sampler 0 to the existing GS/HS/DS/blend/depth-stencil/viewport save+restore chain. Function runs immediately before enginePost(); pattern matches VRStereoOptimizations.cpp. Released the new COM pointers in the cleanup tail.

Skipped:

  • Globals.cpp 30 magic constant (CodeRabbit 💤 Low value): inline comment already explains the engine fade-overlay context. Naming a constant doesn't aid reverse-engineering future-version drift more than the existing comment.
  • BilinearCopyPS.hlsl GetDimensions micro-opt: marginal benefit for one fullscreen pass; adds CB plumbing for a single uniform that DXC would likely fold into a uniform branch anyway.

🤖 Reviewed by Claude Code via review-comment audit.

@alandtse alandtse added the deferred Defer to next cycle label May 16, 2026
@alandtse alandtse closed this May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deferred Defer to next cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant