Skip to content

fix: misc fixes#1474

Merged
doodlum merged 7 commits into
devfrom
more-fixes
Sep 15, 2025
Merged

fix: misc fixes#1474
doodlum merged 7 commits into
devfrom
more-fixes

Conversation

@doodlum
Copy link
Copy Markdown
Collaborator

@doodlum doodlum commented Sep 15, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Improved interior/exterior detection for more consistent visual behavior across scenes.
  • Refactor

    • Standardized several render and interop textures to 8-bit formats to reduce memory usage and bandwidth.
    • Removed legacy high-precision render-target overrides for non-VR paths.
  • Documentation

    • Renamed the “High” Screen Space GI preset to “Extreme” and updated its resolution to full-res.
    • Updated tooltips: “Standard” now clarifies half-resolution; “Extreme” reflects full-resolution and cleaner output.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 15, 2025

Walkthrough

Updates adjust format choices and control paths: motion-vector calculations in a shader are now conditionally compiled for DLSS/XESS; several upscaling paths switch from 10/16-bit to 8-bit formats; ScreenSpaceGI preset labels/resolutions are revised; interior detection now keys off sky mode instead of player/cell.

Changes

Cohort / File(s) Summary of changes
Shader MV gating
features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl
Neighbor depth checks remain unconditional; neighbor motion-vector computation and longest-vector tracking are compiled only under DLSS or XESS. Control flow otherwise unchanged.
Upscaling formats and interop
src/Features/Upscaling.cpp, src/Features/Upscaling/DX12SwapChain.cpp
Removed forced 10-bit swap chain and render-target patches; NIS sharpening texture set to DXGI_FORMAT_R8G8B8A8_UNORM; DX12 interop texture format changed from R16G16B16A16_UNORM to R8G8B8A8_UNORM.
ScreenSpaceGI presets
src/Features/ScreenSpaceGI.cpp
Renamed “High” to “Extreme”; remapped “Extreme” to full resolution (ResolutionMode 0); updated tooltips to reflect half/full resolution changes.
Interior detection logic
src/Deferred.cpp
Interior determination now uses globals::game::sky mode (interior when sky mode ≠ kFull or sky missing) instead of player/cell interior checks.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Game as Game Loop
  participant Defer as Deferred::DeferredPasses
  participant Sky as globals::game::sky

  Game->>Defer: Run DeferredPasses()
  Defer->>Sky: Query sky pointer and mode
  alt Sky exists and mode == kFull
    Defer-->>Game: interior = false
  else Sky missing or mode != kFull
    Defer-->>Game: interior = true
  end
Loading
sequenceDiagram
  autonumber
  participant App as Upscaling::Setup/CreateInterop
  participant D3D11 as D3D11 Device
  participant D3D12 as D3D12 Device

  App->>D3D11: Create SRVs/RTVs with RGBA8
  Note right of D3D11: NIS sharpening texture\nDXGI_FORMAT_R8G8B8A8_UNORM
  App->>D3D12: Create shared resources
  App->>D3D11: Wrap interop textures (RGBA8)
  Note over App: Previous RGBA10/16 paths removed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • jiayev
  • alandtse
  • Pentalimbed

Poem

I hop through pixels, ears held high,
Swapping tens and sixteens for eights that fly.
Sky whispers “inside,” I nod and render,
GI goes Extreme—full-res, splendor.
Shaders hush vectors unless DLSS calls—
Carrots compiled, no wasted stalls.
boop boop ☆彡 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The PR title "fix: misc fixes" is overly generic and does not describe the primary changes in this changeset; the diff contains distinct, substantive changes (shader conditional scope, multiple texture-format reductions from 10/16-bit to 8-bit, a ScreenSpaceGI preset rename/resolution mapping, and altered interior-detection logic), so a reviewer cannot tell the main intent from the title alone. Because it uses non-descriptive language like "misc fixes," it fails to convey which change is most important or why the PR exists. A more specific title is needed. Please replace the generic title with a concise, single-sentence summary that highlights the primary change (for example, "fix: switch NIS and interop textures to R8G8B8A8 and remove forced 10-bit targets" if format changes are primary, or "fix: scope DLSS/XESS motion-vector code and adjust upscaling formats" if the shader/format work is the main intent); pick the single most important change if multiple areas were touched and summarize it succinctly rather than using "misc".
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch more-fixes

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.

Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
@github-actions
Copy link
Copy Markdown

Using provided base ref: c05fb6c
Using base ref: c05fb6c
Base commit date: 2025-09-15T17:15:09+01:00 (Monday, September 15, 2025 05:15 PM)
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: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c05fb6c and b7df12a.

📒 Files selected for processing (1)
  • src/Hooks.cpp (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{cpp,cxx,cc,c,h,hpp,hxx,hlsl,hlsli,fx,fxh,py}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not include TODO/FIXME placeholders; provide complete, working solutions

Files:

  • src/Hooks.cpp
src/**/*.{cpp,cxx,cc,h,hpp,hxx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{cpp,cxx,cc,h,hpp,hxx}: Ensure SE/AE/VR runtime compatibility; use runtime detection patterns (e.g., REL::RelocateMember())
Include robust error handling and resource management with graceful degradation in the plugin code

Files:

  • src/Hooks.cpp
🧠 Learnings (1)
📚 Learning: 2025-08-03T18:37:19.690Z
Learnt from: jiayev
PR: doodlum/skyrim-community-shaders#0
File: :0-0
Timestamp: 2025-08-03T18:37:19.690Z
Learning: ISReflectionsRayTracing.hlsl and ISWorldMap.hlsl in the skyrim-community-shaders repository are image-space post-processing shaders that perform color sampling and blending operations that need proper linear color space handling for the linear lighting system. ISReflectionsRayTracing handles screen-space reflections and should use conditional Color::IrradianceToLinear/Gamma conversions similar to ISCompositeLensFlareVolumetricLighting.hlsl. ISWorldMap performs 7x7 color accumulation that should be done in linear space similar to the pattern used in ISSAOComposite.hlsl.

Applied to files:

  • src/Hooks.cpp
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (4)
src/Hooks.cpp (4)

860-866: Thunk bypasses the vanilla routine—verify completeness.

Since we don’t call the original GeometrySetupConstantPointLights when LightLimitFix is absent, ensure our path writes all expected PS constants (counts, ranges, attenuation, etc.) for parity.

  • Compare bound PS constant blocks with and without LightLimitFix across SE/AE/VR (focus on g_NumPointLights and any attenuation constants).
  • Smoke-test: interior/exterior, >4 shadow lights, VR left/right eye separation correctness.

805-842: Verify sceneLights indexing (use of i + 1)

Code in src/Hooks.cpp (lines 805–842) assumes sceneLights[0] is the directional light and point lights start at index 1; confirm this is guaranteed at runtime. If not, compute/find the first point-light index or skip the directional light to avoid misbinding per-light PS constants.


844-856: Always write ShadowLightMask and avoid unsafe cast.

  • Always upload a zeroed mask even when ShadowLightCount == 0 to avoid stale PS constants.
  • Use a runtime-checked cast (dynamic_cast or equivalent) before reading shadowLightIndex to avoid undefined behavior.

Location: src/Hooks.cpp:844-856

- // Set shadow light mask select for shadow-casting lights
- if (ShadowLightCount > 0) {
-   std::array<float, 4> shadowLightMaskSelect = { 0.0f, 0.0f, 0.0f, 0.0f };
-   for (uint32_t i = 0; i < ShadowLightCount && i < 4; i++) {
-     if (auto bsLight = Pass->sceneLights[i + 1]) {
-       auto* shadowLight = static_cast<RE::BSShadowLight*>(bsLight);
-       GET_INSTANCE_MEMBER(shadowLightIndex, shadowLight);
-       shadowLightMaskSelect[i] = static_cast<float>(shadowLightIndex);
-     }
-   }
-   shadowState->SetPSConstant(shadowLightMaskSelect, RE::BSGraphics::ConstantGroupLevel::PerGeometry, shadowLightMaskSelectIndex);
- }
+ // Set shadow light mask select for shadow-casting lights (always write)
+ std::array<float, 4> shadowLightMaskSelect = { 0.f, 0.f, 0.f, 0.f };
+ const uint32_t cappedShadowCount = std::min<uint32_t>(ShadowLightCount, 4u);
+ for (uint32_t i = 0; i < cappedShadowCount; ++i) {
+   if (auto bsLight = Pass->sceneLights[i + 1]) {
+     if (auto* shadowLight = dynamic_cast<RE::BSShadowLight*>(bsLight)) {
+       GET_INSTANCE_MEMBER(shadowLightIndex, shadowLight);
+       shadowLightMaskSelect[i] = static_cast<float>(shadowLightIndex);
+     }
+   }
+ }
+ shadowState->SetPSConstant(shadowLightMaskSelect, RE::BSGraphics::ConstantGroupLevel::PerGeometry, shadowLightMaskSelectIndex);

Validate that Pass->sceneLights layout guarantees shadow casters are the first ShadowLightCount entries (post-sun), or adjust indexing accordingly.


805-842: Zero out unused light slots to prevent stale constants bleeding between draws.

File: src/Hooks.cpp Lines: 805-842

If current geometry has fewer lights than a previous one, old constants persist — clear remaining slots [LightCount..6] for position(s) and color; VR uses two position registers per light.

Apply:

- for (uint32_t i = 0; i < LightCount && i < 7; i++) {
+ const uint32_t cappedLightCount = std::min<uint32_t>(LightCount, 7u);
+ for (uint32_t i = 0; i < cappedLightCount; ++i) {
   ...
- }
+ }
+
+ // Clear remaining light constants to avoid stale data
+ const std::array<float, 4> zero = { 0.f, 0.f, 0.f, 0.f };
+ if (globals::game::isVR) {
+   for (uint32_t i = cappedLightCount; i < 7u; ++i) {
+     shadowState->SetPSConstant(zero, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + i * 2);
+     shadowState->SetPSConstant(zero, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + 1 + i * 2);
+     shadowState->SetPSConstant(zero, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightColorIndex + i);
+   }
+ } else {
+   for (uint32_t i = cappedLightCount; i < 7u; ++i) {
+     shadowState->SetPSConstant(zero, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + i);
+     shadowState->SetPSConstant(zero, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightColorIndex + i);
+   }
+ }

Confirm visually by toggling nearby lights and verifying removed lights stop affecting subsequent draws.

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

github-actions Bot commented Sep 15, 2025

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

doodlum and others added 2 commits September 15, 2025 18:29
Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
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: 0

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

806-813: Avoid CopyResource format mismatches for NIS output.

ApplyNISSharpening() copies nisSharpenerTexture into kFRAMEBUFFER via CopyResource, which requires identical formats. Hard-coding RGBA8 here can fail on setups where kFRAMEBUFFER isn’t RGBA8 (e.g., B8G8R8A8_UNORM, R10G10B10A2_UNORM). Derive the format from the current framebuffer at runtime to keep this resilient.

Apply this diff:

 D3D11_TEXTURE2D_DESC nisTexDesc = texDesc;
-nisTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+// Match the NIS scratch texture format to the current framebuffer to ensure CopyResource compatibility.
+DXGI_FORMAT fbFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+{
+  auto& framebuffer = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kFRAMEBUFFER];
+  if (framebuffer.RTV) {
+    winrt::com_ptr<ID3D11Resource> fbRes;
+    framebuffer.RTV->GetResource(fbRes.put());
+    if (fbRes) {
+      auto fbTex = static_cast<ID3D11Texture2D*>(fbRes.get());
+      D3D11_TEXTURE2D_DESC fbDesc{};
+      fbTex->GetDesc(&fbDesc);
+      fbFormat = fbDesc.Format;
+    }
+  }
+}
+nisTexDesc.Format = fbFormat;

Please sanity-check on systems where swapchain/framebuffer formats differ from RGBA8 (e.g., 10‑bit paths) to confirm no device removal or copy failures during NIS sharpening.

features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl (1)

20-21: Optional: strip unused UAV when not building DLSS/XESS.

When compiling without DLSS/XESS, MotionVectorOutput becomes dead code and is typically stripped, but to avoid any driver warnings and to reduce bound UAV slots, you can also guard the declaration:

Apply this diff:

- RWTexture2D<float2> MotionVectorOutput : register(u2);
+#if defined(DLSS) || defined(XESS)
+RWTexture2D<float2> MotionVectorOutput : register(u2);
+#endif

And in Upscaling.cpp, only bind u2 when the current method is DLSS/XeSS.

Also applies to: 71-73

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7df12a and 4d25d98.

📒 Files selected for processing (3)
  • features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl (1 hunks)
  • src/Features/Upscaling.cpp (1 hunks)
  • src/Features/Upscaling/DX12SwapChain.cpp (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{cpp,cxx,cc,c,h,hpp,hxx,hlsl,hlsli,fx,fxh,py}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not include TODO/FIXME placeholders; provide complete, working solutions

Files:

  • src/Features/Upscaling/DX12SwapChain.cpp
  • src/Features/Upscaling.cpp
  • features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl
src/**/*.{cpp,cxx,cc,h,hpp,hxx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{cpp,cxx,cc,h,hpp,hxx}: Ensure SE/AE/VR runtime compatibility; use runtime detection patterns (e.g., REL::RelocateMember())
Include robust error handling and resource management with graceful degradation in the plugin code

Files:

  • src/Features/Upscaling/DX12SwapChain.cpp
  • src/Features/Upscaling.cpp
features/*/Shaders/**/*.{hlsl,hlsli,fx,fxh}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

features/*/Shaders/**/*.{hlsl,hlsli,fx,fxh}: Place all feature shaders under features/YourFeature/Shaders/
Avoid GPU register/buffer conflicts in HLSL; verify register usage (e.g., with hlslkit buffer scanning)

Files:

  • features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (2)
src/Features/Upscaling/DX12SwapChain.cpp (1)

89-91: UI buffer forced to RGBA8 — confirm no downstream assumptions about format.

Switching uiBufferWrapped to RGBA8 should be fine for UI and helps perf, but verify nothing later reads this buffer assuming it matches swapChainDesc.Format (e.g., any blit/composite path expecting the same format).

If any such path exists, gate this to RGBA8 only when the swapchain is RGBA8; otherwise, fall back to swapChainDesc.Format.

features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl (1)

55-66: Good: narrower ifdef keeps depth-neighborhood TAA mask logic unconditionally active.

Moving the DLSS||XESS guard to only wrap motion‑vector calculations avoids dropping the TAA‑mask min across FSR/non‑MV builds. Looks correct.

@doodlum doodlum changed the title fix: use GeometrySetupConstantPointLights hook to fix perf fix: misc fixes Sep 15, 2025
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: 0

🧹 Nitpick comments (1)
src/Deferred.cpp (1)

411-414: Sky-mode–based interior detection: verify edge cases and consider a safer fallback.

Switching to sky->mode != RE::Sky::Mode::kFull is sensible and avoids player/cell lookups. However, defaulting to interior when sky is null can misclassify exterior frames during transient states (map/menu transitions, camera swaps, cubemap captures) and may inadvertently disable SKYLIGHTING/IBL in those frames.

  • Please sanity‑check on SE/AE/VR: world map open/close, interior cells flagged “has sky,” Blackreach/Sovngarde, and reflection/cubemap rendering.
  • If you observe flicker or occasional misclassification, consider a minimal, local hysteresis: keep the last known classification when sky is unavailable.

Optional diff (confines behavior to this site and avoids extra engine calls):

-    bool interior = true;
-    if (auto sky = globals::game::sky)
-        interior = sky->mode.get() != RE::Sky::Mode::kFull;
+    static bool lastInterior = true;
+    bool interior = lastInterior;
+    if (auto sky = globals::game::sky)
+        interior = sky->mode.get() != RE::Sky::Mode::kFull;
+    lastInterior = interior;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7bdedb1 and 09686b5.

📒 Files selected for processing (1)
  • src/Deferred.cpp (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{cpp,cxx,cc,c,h,hpp,hxx,hlsl,hlsli,fx,fxh,py}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not include TODO/FIXME placeholders; provide complete, working solutions

Files:

  • src/Deferred.cpp
src/**/*.{cpp,cxx,cc,h,hpp,hxx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{cpp,cxx,cc,h,hpp,hxx}: Ensure SE/AE/VR runtime compatibility; use runtime detection patterns (e.g., REL::RelocateMember())
Include robust error handling and resource management with graceful degradation in the plugin code

Files:

  • src/Deferred.cpp
🧠 Learnings (1)
📓 Common learnings
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#0
File: :0-0
Timestamp: 2025-07-05T05:20:45.823Z
Learning: In the skyrim-community-shaders repository, file deletion error handling improvements that replace existence checks and try-catch blocks with std::filesystem::remove error-code-based approaches are considered bug fixes rather than refactoring, as they address inadequate error handling and misleading log messages.
Learnt from: jiayev
PR: doodlum/skyrim-community-shaders#0
File: :0-0
Timestamp: 2025-08-03T18:37:19.690Z
Learning: ISReflectionsRayTracing.hlsl and ISWorldMap.hlsl in the skyrim-community-shaders repository are image-space post-processing shaders that perform color sampling and blending operations that need proper linear color space handling for the linear lighting system. ISReflectionsRayTracing handles screen-space reflections and should use conditional Color::IrradianceToLinear/Gamma conversions similar to ISCompositeLensFlareVolumetricLighting.hlsl. ISWorldMap performs 7x7 color accumulation that should be done in linear space similar to the pattern used in ISSAOComposite.hlsl.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Build plugin and addons
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)

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.

1 participant