Skip to content

feat(vr): foveated SSR raymarching#82

Merged
alandtse merged 10 commits into
devfrom
feat/vr-foveated-ssr
Jun 6, 2026
Merged

feat(vr): foveated SSR raymarching#82
alandtse merged 10 commits into
devfrom
feat/vr-foveated-ssr

Conversation

@alandtse

@alandtse alandtse commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Adds foveated SSR raymarching for VR: screen-space reflections raymarch at full cost in the center of view and progressively cheaper toward the periphery, using the active Foveated DLSS region as the mask. Central reflections are unchanged; peripheral pixels fall back to the cubemap / water reflection. A net VR GPU-time saving on reflective scenes, at the cost of peripheral SSR detail.

Ported from the foveation framework in ParticleTroned/skyrim-community-shaders, scoped to SSR only with no dead code (compute-dispatch helpers omitted).

How it works

  • Region model: we keep our existing rectangular DLSS subrect as the canonical foveation region. FoveatedRender::GetFoveationProfile() synthesizes the centered-superellipse params (coverage / horizontal scale / per-eye center offset) the mask consumes. We deliberately do not adopt the upstream "oval-as-source" foundation, which would collide with our PR feat(VR): add DLSS Enhancer with DLSSperf and subrect blend community-shaders/skyrim-community-shaders#2096 foveated-DLSS divergence.
  • Mask: FoveatedShaderDetail.hlsli + FoveatedMask.hlsli (superellipse, feathered or hard-cutoff) → a per-pixel 0..1 weight.
  • SSR shader: in VR, the raymarch + binary-search iteration counts scale with the weight down to a floor (minFoveatedIterations = 16 vs 64), the SSR alpha is multiplied by the weight, and pixels outside the mask early-out. Non-VR is behaviorally identical: the non-VR branch sets rayCount = iterations / binCount = binaryIterations / fovWeight = 1.0, collapsing the (now VR-shared) loop body to the original constants and weight 1.0. The loop body is shared with the VR path rather than duplicated, so the source/bytecode is not byte-identical — equivalence is by construction + runtime A/B, not a bytecode diff.
  • Constants: two float4s added to the shared PerFrame cbuffer (VRFoveationData0 + VRFoveationCenterOffsets), with matching C++ layout under the existing STATIC_ASSERT_ALIGNAS_16 size check.
  • Control: VR-only "Foveated Effects" UI with Foveate SSR Raymarching + Hard Cutoff toggles, gated (with hints) on Foveated DLSS being active and SSR enabled.

Scope decisions (per design discussion)

Validation

  • BuildRelease.bat ALL (universal SE/AE/VR) — clean, exit 0, no warnings on the changed TUs.
  • Targeted hlslkit compile of ISReflectionsRayTracing.hlsl0 errors / 0 warnings on both the VR and Flatrim configs.
  • Runtime-tested in VR (Tracy GPU A/B). Measured the ISReflectionsRayTracing GPU zone on an ALL-TRACY build, same scene and camera, Center 50% feathered foveation: the pass drops from ~88 µs to ~44 µs — a saving of ~44 µs, about 0.4% of the 90 fps frame budget (11.1 ms). Small in absolute terms, but reclaimed entirely in the periphery where reflections aren't scrutinized, and it scales with how much SSR the scene actually draws (reflective interiors / water gain more). The rig was present-throttled with the HMD off, so per-pass GPU time is the signal here, not frame rate.

Attribution

Foveation framework by ParticleTroned (ParticleTroned/skyrim-community-shaders).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • VR foveation for screen-space reflections (SSR): per-pixel foveation weighting adjusts SSR detail/iteration counts and skips work outside the foveal center.
    • Engine exposes a foveation profile (coverage scale, horizontal scale, per-eye center offsets) for rendering.
  • UI

    • New "Foveated Effects" settings section with enable toggle, hard-cutoff vs feathered option, and prerequisite warnings.
  • Settings

    • Added persistent settings to enable SSR foveation and hard-cutoff behavior.

Copilot AI review requested due to automatic review settings June 2, 2026 08:30
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

No actionable suggestions for changed features.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

PR changed again? Review this PR in Change Stack to compare snapshots and stay oriented.

Review Change Stack

Warning

Review limit reached

@alandtse, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 4 minutes and 31 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e1491b3b-2443-42a1-ab57-a534bba62a59

📥 Commits

Reviewing files that changed from the base of the PR and between eeb7bd9 and 7efffc4.

📒 Files selected for processing (9)
  • package/Shaders/Common/FoveatedMask.hlsli
  • package/Shaders/Common/FoveatedShaderDetail.hlsli
  • package/Shaders/ISReflectionsRayTracing.hlsl
  • src/Features/FoveatedCommon.h
  • src/Features/Upscaling/FoveatedRender.cpp
  • src/Features/Upscaling/FoveatedRender.h
  • src/Features/VR.h
  • src/State.cpp
  • src/State.h
📝 Walkthrough

Walkthrough

Implements VR foveated SSR: shader superellipse mask and detail modes, per-pixel SSR iteration scaling and alpha modulation, CPU helpers and foveation profile API, VR settings/UI, SharedData cbuffer fields, State wiring, and optional Tracy GPU timing hooks.

Changes

VR Foveated Screen-Space Reflections

Layer / File(s) Summary
Shader mask computation foundation
package/Shaders/Common/FoveatedMask.hlsli
Defines configurable superellipse-based foveation mask with parameter clamping, center UV derivation, radii calculation, feather normalization, distance evaluation, and blend weight generation using smoothstep.
Shader detail weighting modes
package/Shaders/Common/FoveatedShaderDetail.hlsli
Defines feathered and hard-cutoff detail modes, evaluates mode-based detail weight from mask distance or center blend, and provides detail activation checking.
Constant buffer VR foveation fields
package/Shaders/Common/SharedData.hlsli
Extends SharedData cbuffer with VRFoveationData0 and VRFoveationCenterOffsets float4 fields to carry per-pixel foveation parameters.
SSR shader foveation integration
package/Shaders/ISReflectionsRayTracing.hlsl
Adds VR-only per-pixel foveation weight computation, derives raymarch and binary iteration counts from that weight, extends GetReflectionColor with iteration and foveation parameters, uses runtime counts for VR loops, and multiplies output alpha by foveation weight in VR builds; early-returns when detail is inactive.
CPU-side foveation helpers
src/Features/FoveatedCommon.h
Defines FoveatedCommon namespace with DetailMode enum, mode getter/encoder, center-scale and horizontal-scale clamping with finite checks, and coverage activation logic.
Foveation profile API
src/Features/Upscaling/FoveatedRender.h, src/Features/Upscaling/FoveatedRender.cpp
Adds FoveationProfile struct and GetFoveationProfile() that computes coverageScale, centerHorizontalScale, and per-eye centerOffsets from eye UV subrects and availability gating.
VR settings for SSR foveation
src/Features/VR.h, src/Features/VR.cpp
Adds EnableSSRFoveation and EnableSSRFoveationHardCutoff booleans to VR::Settings and includes them in JSON (de)serialization.
Foveated Effects settings UI
src/Features/VR/SettingsUI.cpp
Introduces "Foveated Effects" UI section that checks prerequisites and exposes toggles for SSR foveation and hard-cutoff mode with conditional enabling and tooltips.
State constant buffer and foveation data computation
src/State.h, src/State.cpp
Inserts VR foveation fields into SharedDataCB layout and populates VRFoveationData0/VRFoveationCenterOffsets in State::UpdateSharedData when VR, SSR foveation, Dynamic Cubemaps SSR, and active coverage are present.
Optional SSR Tracy GPU zone hooks
src/Features/Upscaling.cpp
Adds TRACY-enabled GPU zone scope and vtable hook thunks to mark SSR raymarch draws for GPU timing, installed during PostPostLoad().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nibble code where foveas gleam,

Superellipse and shader dream,
Rays trimmed softly at the edge,
Center crisp where eyes allege,
A rabbit hops — reflections beam.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.04% 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
Title check ✅ Passed The title accurately describes the main change: adding foveated screen-space reflection raymarching for VR, which is the primary focus across all file modifications.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vr-foveated-ssr

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 VR-only foveated SSR raymarching by deriving a per-eye foveation profile from the active Foveated DLSS subrect and using it to (a) scale SSR raymarch/binary-search iterations and (b) attenuate/early-out SSR in the periphery. This fits into the existing VR + Upscaling (DLSS) pipeline by extending the shared per-frame cbuffer and adding small reusable CPU/GPU foveation helpers.

Changes:

  • Extend the shared PerFrame/SharedData constant buffer with VR foveation parameters and populate them in State::UpdateSharedData.
  • Add a FoveatedRender::GetFoveationProfile() adapter (rect subrect → centered-superellipse params) plus shared CPU clamping/mode helpers.
  • Update SSR shader to consume the foveation mask (VR only) and add a VR settings UI toggle + serialization.

Reviewed changes

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

Show a summary per file
File Description
src/State.h Adds VR foveation float4s to SharedDataCB and alignment assertions.
src/State.cpp Populates VR foveation constants per-frame when VR + foveated DLSS + SSR are active.
src/Features/VR/SettingsUI.cpp Adds VR UI toggles for foveated SSR and hard-cutoff mode, gated on DLSS foveation + SSR enabled.
src/Features/VR.h Adds new VR settings fields for SSR foveation controls.
src/Features/VR.cpp Persists the new VR settings via nlohmann JSON serialization.
src/Features/Upscaling/FoveatedRender.h Introduces FoveationProfile and GetFoveationProfile() API.
src/Features/Upscaling/FoveatedRender.cpp Implements profile synthesis from the DLSS subrect(s).
src/Features/FoveatedCommon.h New CPU-side shared constants, clamping, and mode encoding helpers.
package/Shaders/ISReflectionsRayTracing.hlsl VR-only SSR iteration scaling + alpha weighting + early-out using the foveation mask.
package/Shaders/Common/SharedData.hlsli Mirrors the new shared cbuffer fields for VR foveation parameters.
package/Shaders/Common/FoveatedShaderDetail.hlsli New GPU helper to evaluate per-pixel foveated “detail weight” (0..1).
package/Shaders/Common/FoveatedMask.hlsli New GPU superellipse mask implementation and feathering math.

Comment thread src/State.cpp Outdated
Comment thread src/Features/Upscaling/FoveatedRender.cpp Outdated
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from 3b04436 to 6544164 Compare June 2, 2026 08:40
Copilot AI review requested due to automatic review settings June 2, 2026 08:43
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from 6544164 to 1916141 Compare June 2, 2026 08:43

@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

🧹 Nitpick comments (1)
src/Features/Upscaling/FoveatedRender.cpp (1)

127-127: 💤 Low value

Use the named threshold constant instead of a hardcoded 0.999f.

FoveatedCommon::kFullCoverageThreshold (0.999f) already encodes the "full coverage" cutoff and is used by IsActiveCoverage. Referencing it here keeps the early-out and the activation check moving together.

♻️ Proposed change
-	if (leftUV.w >= 0.999f && leftUV.h >= 0.999f)
+	if (leftUV.w >= FoveatedCommon::kFullCoverageThreshold && leftUV.h >= FoveatedCommon::kFullCoverageThreshold)
 		return profile;
🤖 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/Features/Upscaling/FoveatedRender.cpp` at line 127, Replace the hardcoded
0.999f comparison in FoveatedRender (the early-out that checks leftUV.w and
leftUV.h) with the named constant FoveatedCommon::kFullCoverageThreshold so the
early-exit uses the same threshold as IsActiveCoverage; update the conditional
that currently checks leftUV.w >= 0.999f && leftUV.h >= 0.999f to compare
against FoveatedCommon::kFullCoverageThreshold for both leftUV.w and leftUV.h.
🤖 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/FoveatedRender.cpp`:
- Around line 137-139: GetFoveationProfile currently computes
profile.coverageArea from leftUV.h only, causing full-height but reduced-width
subrects to appear as full coverage and skip activation; change it to derive
coverage from both axes (e.g., compute float coverage = std::max(leftUV.w,
leftUV.h) or another combined metric and pass that to
FoveatedCommon::ClampCenterArea) so IsActiveCoverage(profile.coverageArea)
reflects narrow-width cases; update the assignment of profile.coverageArea and
ensure profile.centerHorizontalScale still uses the existing leftUV.w / leftUV.h
guard as before in GetFoveationProfile.

---

Nitpick comments:
In `@src/Features/Upscaling/FoveatedRender.cpp`:
- Line 127: Replace the hardcoded 0.999f comparison in FoveatedRender (the
early-out that checks leftUV.w and leftUV.h) with the named constant
FoveatedCommon::kFullCoverageThreshold so the early-exit uses the same threshold
as IsActiveCoverage; update the conditional that currently checks leftUV.w >=
0.999f && leftUV.h >= 0.999f to compare against
FoveatedCommon::kFullCoverageThreshold for both leftUV.w and leftUV.h.
🪄 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: 2c73b40b-2324-4ba9-a8b2-5fd8aaba7de9

📥 Commits

Reviewing files that changed from the base of the PR and between 629b1d2 and 3b04436.

📒 Files selected for processing (12)
  • package/Shaders/Common/FoveatedMask.hlsli
  • package/Shaders/Common/FoveatedShaderDetail.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/ISReflectionsRayTracing.hlsl
  • src/Features/FoveatedCommon.h
  • src/Features/Upscaling/FoveatedRender.cpp
  • src/Features/Upscaling/FoveatedRender.h
  • src/Features/VR.cpp
  • src/Features/VR.h
  • src/Features/VR/SettingsUI.cpp
  • src/State.cpp
  • src/State.h

Comment thread src/Features/Upscaling/FoveatedRender.cpp Outdated

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 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread src/Features/Upscaling/FoveatedRender.cpp
Comment thread src/Features/Upscaling/FoveatedRender.cpp
Comment thread src/State.h
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

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

Copilot AI review requested due to automatic review settings June 3, 2026 07:13
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from 5e1a997 to 102d52b Compare June 3, 2026 07:13

@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.

♻️ Duplicate comments (1)
src/Features/Upscaling/FoveatedRender.cpp (1)

137-140: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Coverage activation ignores reduced-width subrects.

profile.coverageArea is derived solely from leftUV.h, so a full-height but reduced-width region (e.g. w=0.5, h=1.0) passes the && early-out at Line 127, then yields coverageArea ≈ 1.0 and is treated as full coverage by downstream IsActiveCoverage(), disabling foveation even though width was reduced. Derive coverage from both axes.

🤖 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/Features/Upscaling/FoveatedRender.cpp` around lines 137 - 140,
profile.coverageArea currently only uses leftUV.h which ignores reduced-width
subrects; update the assignment of profile.coverageArea to derive coverage from
both leftUV.w and leftUV.h (for example compute an area factor like leftUV.w *
leftUV.h and pass that into FoveatedCommon::ClampCenterArea) so downstream
IsActiveCoverage() correctly treats reduced-width regions as partial coverage;
keep the existing centerHorizontalScale calculation
(profile.centerHorizontalScale) but ensure it still guards against zero height
as it does now.
🤖 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.

Duplicate comments:
In `@src/Features/Upscaling/FoveatedRender.cpp`:
- Around line 137-140: profile.coverageArea currently only uses leftUV.h which
ignores reduced-width subrects; update the assignment of profile.coverageArea to
derive coverage from both leftUV.w and leftUV.h (for example compute an area
factor like leftUV.w * leftUV.h and pass that into
FoveatedCommon::ClampCenterArea) so downstream IsActiveCoverage() correctly
treats reduced-width regions as partial coverage; keep the existing
centerHorizontalScale calculation (profile.centerHorizontalScale) but ensure it
still guards against zero height as it does now.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d8d7ee34-6c4d-4670-a011-2e821c108dd4

📥 Commits

Reviewing files that changed from the base of the PR and between 3b04436 and 102d52b.

📒 Files selected for processing (12)
  • package/Shaders/Common/FoveatedMask.hlsli
  • package/Shaders/Common/FoveatedShaderDetail.hlsli
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/ISReflectionsRayTracing.hlsl
  • src/Features/FoveatedCommon.h
  • src/Features/Upscaling/FoveatedRender.cpp
  • src/Features/Upscaling/FoveatedRender.h
  • src/Features/VR.cpp
  • src/Features/VR.h
  • src/Features/VR/SettingsUI.cpp
  • src/State.cpp
  • src/State.h
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/Features/VR.cpp
  • src/Features/Upscaling/FoveatedRender.h
  • package/Shaders/Common/SharedData.hlsli
  • src/Features/VR/SettingsUI.cpp
  • src/Features/VR.h
  • src/Features/FoveatedCommon.h
  • src/State.cpp
  • package/Shaders/Common/FoveatedMask.hlsli

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 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread src/State.h Outdated
Comment thread src/Features/Upscaling/FoveatedRender.cpp Outdated
Comment thread package/Shaders/Common/SharedData.hlsli Outdated
alandtse added a commit that referenced this pull request Jun 3, 2026
…ge comment

Address Copilot review on #82:
- GetFoveationProfile now disables only when BOTH eyes are full-eye and
  derives coverageArea/horizontalScale from the less-foveated (max) extent
  of the two eyes, so an asymmetric per-eye crop can't wrongly disable the
  profile and the single shared scale never foveates inside either eye's
  full-quality region. No-op for the symmetric seeded presets.
- Clarify the VRFoveationData0.x comment as 'center coverage scale' (set
  from FoveationProfile::coverageArea) to disambiguate from horizontal scale.

The disk-shader-cache stale-offset concern on SharedData layout changes is a
pre-existing, general ShaderCache behavior (skip-unchanged-without-file-watcher
ignores include mtimes) — tracked separately, not specific to this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
alandtse added a commit that referenced this pull request Jun 3, 2026
…ge comment

Address Copilot review on #82:
- GetFoveationProfile now disables only when BOTH eyes are full-eye and
  derives coverageArea/horizontalScale from the less-foveated (max) extent
  of the two eyes, so an asymmetric per-eye crop can't wrongly disable the
  profile and the single shared scale never foveates inside either eye's
  full-quality region. No-op for the symmetric seeded presets.
- Clarify the VRFoveationData0.x comment as 'center coverage scale' (set
  from FoveationProfile::coverageArea) to disambiguate from horizontal scale.

The disk-shader-cache stale-offset concern on SharedData layout changes is a
pre-existing, general ShaderCache behavior (skip-unchanged-without-file-watcher
ignores include mtimes) — tracked separately, not specific to this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 09:20
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from cb5d115 to 02a3b04 Compare June 3, 2026 09:20

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 12 out of 12 changed files in this pull request and generated no new comments.

alandtse added a commit that referenced this pull request Jun 3, 2026
…ge comment

Address Copilot review on #82:
- GetFoveationProfile now disables only when BOTH eyes are full-eye and
  derives coverageArea/horizontalScale from the less-foveated (max) extent
  of the two eyes, so an asymmetric per-eye crop can't wrongly disable the
  profile and the single shared scale never foveates inside either eye's
  full-quality region. No-op for the symmetric seeded presets.
- Clarify the VRFoveationData0.x comment as 'center coverage scale' (set
  from FoveationProfile::coverageArea) to disambiguate from horizontal scale.

The disk-shader-cache stale-offset concern on SharedData layout changes is a
pre-existing, general ShaderCache behavior (skip-unchanged-without-file-watcher
ignores include mtimes) — tracked separately, not specific to this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from 02a3b04 to 73d7d0c Compare June 3, 2026 10:24
alandtse added a commit that referenced this pull request Jun 4, 2026
…ge comment

Address Copilot review on #82:
- GetFoveationProfile now disables only when BOTH eyes are full-eye and
  derives coverageArea/horizontalScale from the less-foveated (max) extent
  of the two eyes, so an asymmetric per-eye crop can't wrongly disable the
  profile and the single shared scale never foveates inside either eye's
  full-quality region. No-op for the symmetric seeded presets.
- Clarify the VRFoveationData0.x comment as 'center coverage scale' (set
  from FoveationProfile::coverageArea) to disambiguate from horizontal scale.

The disk-shader-cache stale-offset concern on SharedData layout changes is a
pre-existing, general ShaderCache behavior (skip-unchanged-without-file-watcher
ignores include mtimes) — tracked separately, not specific to this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 4, 2026 06:37
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from 73d7d0c to 415ccf6 Compare June 4, 2026 06:37
alandtse and others added 3 commits June 5, 2026 17:34
Address review feedback on the foveation profile adapter: replace the
hard-coded 0.999f full-eye threshold with FoveatedCommon::kFullCoverageThreshold
(same value, shared constant), and document that the mask carries a single
scale for both eyes — size comes from the left eye since seeded presets are
symmetric in size and only the per-eye center offset differs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ge comment

Address Copilot review on #82:
- GetFoveationProfile now disables only when BOTH eyes are full-eye and
  derives coverageArea/horizontalScale from the less-foveated (max) extent
  of the two eyes, so an asymmetric per-eye crop can't wrongly disable the
  profile and the single shared scale never foveates inside either eye's
  full-quality region. No-op for the symmetric seeded presets.
- Clarify the VRFoveationData0.x comment as 'center coverage scale' (set
  from FoveationProfile::coverageArea) to disambiguate from horizontal scale.

The disk-shader-cache stale-offset concern on SharedData layout changes is a
pre-existing, general ShaderCache behavior (skip-unchanged-without-file-watcher
ignores include mtimes) — tracked separately, not specific to this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The value is a linear center coverage scale (vertical UV extent, used as radiusY = scale/2), not an area ratio. Rename the misleading 'Area' cluster to 'Scale' across C++ (FoveationProfile field, FoveatedCommon constants/helpers) and the HLSL mask include, matching the centerScale vocabulary the shader entry points already use. Pure identifier rename; no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 5, 2026 17:34
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from e7c3a82 to 1ce96da Compare June 5, 2026 17:34

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 12 out of 12 changed files in this pull request and generated 1 comment.

Comment thread src/Features/Upscaling/FoveatedRender.cpp
available was set true whenever either eye was non-full, but coverageScale takes the max of both eyes' extent, so a single full eye clamps the scale to full coverage while available stayed true — contradicting the header contract and forcing State.cpp to re-check IsActiveCoverage(). Derive available from the final clamped coverageScale and early-return when inactive; drop the now-redundant both-eyes full check and the caller-side coverage check. Consumer behavior unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 6, 2026 02:40

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 13 out of 13 changed files in this pull request and generated no new comments.

alandtse and others added 2 commits June 5, 2026 20:02
The PR added VRFoveationData0 / VRFoveationCenterOffsets to the SharedData
cbuffer but only asserted the overall struct alignment. Add per-field
offsetof % 16 == 0 guards (incl. the shifted HDRData) so a stray scalar
inserted above can't silently misalign the float4s and corrupt shader reads.
Addresses the Copilot review note on State.h.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cut incidental detail from the GetFoveationProfile mapping comment and the
UpdateSharedData default-state comment; keep the load-bearing invariants
(rect->superellipse mapping, max-of-two-eyes rationale, full-eye gate).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 6, 2026 03:04
@alandtse alandtse force-pushed the feat/vr-foveated-ssr branch from 6d35f08 to de4f54b Compare June 6, 2026 03:04
@alandtse

alandtse commented Jun 6, 2026

Copy link
Copy Markdown
Owner Author

Split the Tracy GPU profiling hook out into #106 (chore(upscaling)) — it's independent diagnostic instrumentation (profiles the SSR pass regardless of foveation), not part of this feature. Force-pushed to drop that commit; this PR is now 12 files / +398 and is feat(vr) end-to-end. Also trimmed some over-verbose foveation comments.

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 12 out of 12 changed files in this pull request and generated 2 comments.

Comment thread src/Features/Upscaling/FoveatedRender.cpp Outdated
Comment thread package/Shaders/Common/FoveatedMask.hlsli
alandtse and others added 2 commits June 5, 2026 20:11
FoveatedComputeMaskDistance ran three transcendental pow() calls per pixel; the default squircle (shape power 4) now uses (t*t)^2 and sqrt(sqrt()) instead, with the generic pow() path kept under #else for other powers. Also reword the GetFoveationProfile comment: the max-of-both-eyes center is a superset enclosing each eye's sharp region (the old wording said inside, the opposite of max).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply the tightened comment-length standard to the foveation comments this
branch introduced: trim the file/namespace headers and the incidental block
comments to 1-2 lines, pushing the long-form rationale to commit messages.
Leaves the GetFoveationProfile max-of-both-eyes invariant intact (load-bearing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 6, 2026 03:16

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 12 out of 12 changed files in this pull request and generated 1 comment.

Comment thread package/Shaders/ISReflectionsRayTracing.hlsl
Conform the namespace contract header to the tightened 1-2 line comment
rule; keep the GPU-mirror + encoding contract and the compute-helpers-
omitted note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
alandtse added a commit that referenced this pull request Jun 6, 2026
Adds a diagnostic-only Tracy GPU zone around the engine SSR raymarch
pass (`ISReflectionsRayTracing`), so the pass is visible on the Tracy
GPU timeline. Split out of #82 (foveated SSR) since it's independent
profiling infrastructure, not part of the feature.

## What it does

Wraps the SSR raymarch DRAW with a `tracy::D3D11ZoneScope`, opened on
the shader's `PreRender` (vfunc `0x0A`) and closed on `PostRender`
(`0x0B`).

## Why these hook points

RenderDoc callstacks proved the effect renders as a pixel-shader DRAW
issued by the deferred batch renderer through the **non-virtual**
`BSImagespaceShader::Render` — not the `ImageSpaceManager` vtable Render
slot and not `DispatchComputeShader` (both of which were tried first and
never fired). `Render` brackets the draw with the per-shader
`PreRender`/`PostRender` vfuncs, which CommonLib keeps at stable indices
across SE/AE/VR (the VR-only `FakeDispatchComputeShader` inserts at
`0x0D`, after them), so hooking `0x0A`/`0x0B` on the cross-versioned
`ReflectionsRayTracing` vtable wraps exactly the SSR draw on all three
runtimes with no per-version addresses.

## Safety

- `TRACY_ENABLE`-gated — zero impact on shipping builds.
- Behaviour-preserving: each thunk only chains the original vfunc.
- Single raw zone holder is safe: render-thread only, non-nested for
this shader; the `PreRender` thunk defensively closes any prior zone if
`PostRender` were ever skipped.

Verified live (ALL-TRACY build): zone fires ~525/530 frames, ~88us
baseline.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alandtse alandtse merged commit 4c873cc into dev Jun 6, 2026
20 checks passed
@alandtse alandtse deleted the feat/vr-foveated-ssr branch June 6, 2026 05:52
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