Skip to content

feat(sss): add burley normalized sss#1393

Merged
alandtse merged 29 commits into
community-shaders:devfrom
jiayev:burley-sss
Aug 29, 2025
Merged

feat(sss): add burley normalized sss#1393
alandtse merged 29 commits into
community-shaders:devfrom
jiayev:burley-sss

Conversation

@jiayev
Copy link
Copy Markdown
Collaborator

@jiayev jiayev commented Aug 13, 2025

This pull request adds a new Burley-based subsurface scattering (SSS) method alongside the existing separable SSS blur, providing more physically accurate skin rendering and greater user control. It introduces new shader code for the Burley profile, updates the configuration and UI to support both SSS methods, and refactors resource bindings and compute shader selection to accommodate the changes.

Burley SSS Implementation

  • Added a new Burley.hlsli shader implementing the Burley reflectance profile, including physically-based sampling, color bleed, and profile calculations for improved realism. (features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli)
  • Integrated Burley SSS compute shader logic and resource bindings into SeparableSSSCS.hlsl, including new texture inputs (albedo, normal), constants (sample count, mean free path), and conditional execution based on mode. (features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl) [1] [2] [3]

Configuration and UI Enhancements

  • Extended SSS settings with a mode selector (separable vs. Burley), Burley-specific parameters (sample count, mean free path color/distance), and updated serialization and UI to support these options. (src/Features/SubsurfaceScattering.cpp, src/Features/SubsurfaceScattering.h) [1] [2] [3] [4]

Resource Binding and Shader Dispatch

  • Updated resource bindings to pass additional textures (albedo, normal) and new constants to shaders, and refactored compute shader dispatch logic to select the appropriate shader and handle output copying for Burley mode. (src/Features/SubsurfaceScattering.cpp, src/Features/SubsurfaceScattering.h) [1] [2] [3] [4] [5] [6] [7]

Separable SSS Improvements

  • Improved color normalization and albedo clamping in separable SSS blur passes for more robust and artifact-free results. (features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli, package/Shaders/Common/Math.hlsli) [1] [2] [3] [4]

Refactoring and Maintenance

  • Added shader cache management for Burley SSS, ensuring proper resource cleanup and lazy compilation. (src/Features/SubsurfaceScattering.cpp, src/Features/SubsurfaceScattering.h) [1] [2]

These changes collectively enable a more advanced, configurable, and physically plausible subsurface scattering effect for character and skin rendering.

Summary by CodeRabbit

  • New Features
    • Introduces a Burley subsurface scattering mode for more realistic skin/translucent rendering with depth-aware sampling and stereo support.
    • Adds UI controls: mode selector (Separable vs. Burley), sample count, and Mean Free Path settings for Base and Human profiles (color and distance).
    • Integrates albedo and normal inputs into the SSS pass; outputs are gamma-corrected and clamped for stability.
    • Preserves existing separable blur path; users can switch modes per preference.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 13, 2025

Walkthrough

Adds a Burley-based subsurface scattering (SSS) path alongside existing separable SSS. Introduces a new shader Burley.hlsli, extends SeparableSSSCS.hlsl with BURLEY conditional flow, adds epsilon macro in Math.hlsli, and updates C++ SSS feature for settings/UI, constant buffer, shader compilation/dispatch, and resource bindings (albedo/normal).

Changes

Cohort / File(s) Summary
Burley SSS Shader
features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli
New shader implementing Burley-style SSS with Monte Carlo sampling: CDF/PDF/profile helpers, albedo scaling, and BurleyNormalizedSS entry. Uses GBuffer/util includes and RNG; depth/normal-aware sampling; outputs color.
Separable SSS Compute Entry
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
Adds SRVs AlbedoTexture (t3) and NormalTexture (t4). Extends PerFrameSSS with BurleySamples, MeanFreePathBase, MeanFreePathHuman. Conditional include of Burley.hlsli when BURLEY. Integrates Burley dispatch path using eye index; clamps output. Keeps separable horizontal/vertical paths otherwise.
Common Math Constants
package/Shaders/Common/Math.hlsli
Adds #define EPSILON_SSS_ALBEDO 1e-3f for SSS albedo clamping.
SSS Feature API & Dispatch
src/Features/SubsurfaceScattering.h, src/Features/SubsurfaceScattering.cpp
Public settings extended: SSMode, BurleySamples, MeanFreePathBase, MeanFreePathHuman. BlurCB gains matching fields. Adds burleySS handle and GetComputeShaderBurley(); shader cache cleared accordingly. UI exposes mode toggle and Burley controls. Draw path branches: separable H/V or Burley compute; binds albedo/normal SRVs; updates CB (incl. FOVY).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Renderer
  participant SSS as SubsurfaceScattering (C++)
  participant D3D as D3D11
  participant CS as SeparableSSSCS.hlsl

  App->>SSS: DrawSSS()
  SSS->>SSS: Read Settings.SSMode
  alt Mode 0 (Separable)
    SSS->>D3D: Bind H-pass CS + SRVs (color, depth, mask)
    SSS->>D3D: Update CB (blur params)
    SSS->>D3D: Dispatch H-pass
    SSS->>D3D: Bind V-pass CS + SRVs
    SSS->>D3D: Dispatch V-pass
  else Mode 1 (Burley)
    SSS->>SSS: GetComputeShaderBurley()
    SSS->>D3D: Compile/Cache CS with BURLEY (if needed)
    SSS->>D3D: Bind CS + SRVs (color, depth, mask, albedo, normal)
    SSS->>D3D: Update CB (BurleySamples, MFP base/human, FOVY)
    SSS->>D3D: Dispatch Burley
    SSS->>D3D: Copy result to main texture
  end
  D3D-->>App: Completed SSS pass
Loading
sequenceDiagram
  autonumber
  participant Thread as CS Thread (pixel)
  participant GBuf as GBuffer/Textures
  participant RNG as Random.hlsli

  Thread->>GBuf: Load center depth/color/albedo/normal/mask
  alt sssAmount == 0 or invalid depth
    Thread-->>Thread: Return center color
  else Burley
    Thread->>Thread: Pick MFP (base/human), scale by sssAmount
    Thread->>RNG: Seed per-pixel RNG
    loop i in BurleySamples
      Thread->>Thread: Sample radius/angle via CDF/PDF
      Thread->>GBuf: Fetch neighbor sample (color/depth/normal)
      Thread->>Thread: Weight by profile and normal/depth terms
      Thread->>Thread: Accumulate color/weight
    end
    Thread->>Thread: Normalize, blend with center
    Thread-->>Thread: Write clamped output
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • alandtse
  • Pentalimbed
  • doodlum

Poem

Bunny taps the shader keys—hop, hop—new light will roam,
Burley burrows through the skin, and softly scatters home.
Mean free paths and sampled rings, a warren of gentle glow,
Normals nod, depths agree, as petals blush below.
Carrots for the compiler; we ship—let photons flow!

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Aug 13, 2025

Using provided base ref: 7945fd0
Using base ref: 7945fd0
Base commit date: 2025-08-13T11:38:01+01:00 (Wednesday, August 13, 2025 11:38 AM)
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: 5

🧹 Nitpick comments (4)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

6-7: NormalTexture is declared but never used.

The NormalTexture at register(t4) is declared but not referenced anywhere in the shader code. Consider removing it if it's not needed, or ensure it's properly integrated for the Burley implementation.

If the normal texture is not needed, apply this diff:

 Texture2D<float4> AlbedoTexture : register(t3);
-Texture2D<float4> NormalTexture : register(t4);
src/Features/SubsurfaceScattering.cpp (1)

33-35: Consider adding tooltips for SSS mode selection.

The radio buttons for SSS mode selection would benefit from tooltips explaining the differences between Separable SSS and Burley modes to help users make informed choices.

Add tooltips after each radio button:

 ImGui::RadioButton("Separatable SSS", &settings.SSMode, 0);
+if (auto _tt = Util::HoverTooltipWrapper()) {
+    ImGui::Text("Traditional separable subsurface scattering using Gaussian blur profiles.");
+}
 ImGui::SameLine();
 ImGui::RadioButton("Burley", &settings.SSMode, 1);
+if (auto _tt = Util::HoverTooltipWrapper()) {
+    ImGui::Text("Physically-based Burley reflectance profile with better color bleeding.");
+}
features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (2)

30-35: Fix variable naming in RadiusApprox function.

The parameter d conflicts with the local variable d used in the formula comment. Consider renaming for clarity. Also, the approximation formula needs validation against the referenced paper.

-float RadiusApprox(float d, float rand)
+float RadiusApprox(float dmfp, float rand)
 {
 	// g(ξ) = d((2 − c)ξ − 2)log(1 − ξ)
 	// minimal mean squared error when c = 2.5715
-	return d * ((2 - 2.5715f) * rand - 2) * log(1 - rand);
+	return dmfp * ((2 - 2.5715f) * rand - 2) * log(1 - rand);
 }

92-131: Sampling loop implementation looks solid.

The Monte Carlo sampling approach is well-implemented with:

  • Proper random number generation
  • Importance sampling with PDF weighting
  • Normal-based weighting for geometric consistency
  • Mask-based color bleeding

One minor optimization opportunity: pre-compute 2.0f * Math::PI as a constant.

+	const float TWO_PI = 2.0f * Math::PI;
 	[loop]
 	for (int i = 0; i < BurleySamples; ++i)
 	{
 		seed.z = seedStart++;
 		float2 rand = float2(Random::pcg3d(seed).xy) / 4294967296.0f;  // to [0, 1)
 
 		rand.x = centerRadiusCDF + rand.x * (1.0f - centerRadiusCDF);
 
 		// generate radius & angle for sampling
 		float radius = max(RadiusApprox(d, rand.x), 1e-5f);
-		float theta = rand.y * 2.0f * Math::PI;
+		float theta = rand.y * TWO_PI;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7945fd0 and 25c9665.

📒 Files selected for processing (6)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (1 hunks)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli (2 hunks)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3 hunks)
  • package/Shaders/Common/Math.hlsli (1 hunks)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
  • src/Features/SubsurfaceScattering.h (4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-01T18:01:07.079Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#0
File: :0-0
Timestamp: 2025-07-01T18:01:07.079Z
Learning: In the skyrim-community-shaders project, simple scalar constants in HLSL shaders use #define (e.g., #define NTHREADS 128), while more complex constants use static const within namespaces (e.g., Math namespace in Math.hlsli). For epsilon standardization, #define is the appropriate choice since epsilon values are simple scalar constants.

Applied to files:

  • package/Shaders/Common/Math.hlsli
📚 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
  • src/Features/SubsurfaceScattering.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). (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 (14)
package/Shaders/Common/Math.hlsli (1)

4-4: LGTM! Appropriate constant definition following project conventions.

The epsilon constant is correctly defined using #define which aligns with the project's convention for simple scalar constants.

features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli (1)

162-162: Verify the max operation for blend factor.

The change from profile.y to max(profile.y, 0.0001) ensures a minimum blend factor, but consider if this aligns with the intended SSS behavior when profile thickness is very small.

features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

60-60: Verify the albedo multiplication order in vertical pass.

The albedo is applied after converting from linear to gamma space. Ensure this is the intended behavior, as typically albedo modulation should occur in linear space before gamma conversion.

Consider if the albedo multiplication should happen before gamma conversion:

-		color.rgb = Color::LinearToGamma(color.rgb) * AlbedoTexture[DTid.xy].rgb;
+		color.rgb = Color::LinearToGamma(color.rgb * AlbedoTexture[DTid.xy].rgb);
src/Features/SubsurfaceScattering.h (1)

23-28: LGTM! Well-structured settings for Burley SSS mode.

The addition of SSMode selector and Burley-specific parameters (samples count and mean free path) provides appropriate control over the new rendering path with sensible defaults.

src/Features/SubsurfaceScattering.cpp (2)

296-297: Array size mismatch in cleanup.

The views array is declared with size 3 but you're clearing 5 elements with CSSetShaderResources(0, 5, views). This could lead to undefined behavior.

Fix the array size to match the number of resources being cleared:

-	ID3D11ShaderResourceView* views[5]{ nullptr, nullptr, nullptr };
+	ID3D11ShaderResourceView* views[5]{ nullptr, nullptr, nullptr, nullptr, nullptr };
 	context->CSSetShaderResources(0, 5, views);

Likely an incorrect or invalid review comment.


278-290: Confirm UAV binding for Burley mode
I wasn’t able to locate the src/Features/SubsurfaceScattering.cpp file or the settings.SSMode == 1 block in the repo. Please verify that the blurHorizontalTemp UAV is bound before dispatch in Burley mode:

  • Ensure the file src/Features/SubsurfaceScattering.cpp (or its actual path) exists and contains the SSMode == 1 branch.
  • In that branch, immediately before context->Dispatch(...), there must be a call to
    context->CSSetUnorderedAccessViews(..., blurHorizontalTemp->resource->GetUAV(), ...) (or equivalent)
  • After dispatch, copying from blurHorizontalTemp to main.texture without binding the UAV first will result in no data being written.
features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (8)

7-11: LGTM! Clean utility function for depth conversion.

The function correctly retrieves depth and converts it to linear space using the shared utility.


20-25: PDF calculation looks correct.

The probability density function implementation aligns with the Burley paper's formulation. The max(pdf, 1e-5f) guard prevents division by zero in downstream calculations.


37-44: Excellent implementation of the Burley profile.

The function correctly implements the reflectance profile from the paper with appropriate numerical guards to prevent underflow.


52-60: Early exit logic is correct.

The function properly handles edge cases where SSS should not be applied.


62-63: Good gamma correction handling.

Properly converts from gamma space and handles division by zero with the epsilon guard.


133-140: Final color composition is well-structured.

The normalization, blending, and gamma correction pipeline is correctly implemented. The function properly preserves the alpha channel from the original color texture.


65-74: Validate Mean Free Path in the Configuration Layer

Clamping to 1e-5f in the HLSL shader avoids division by zero, but invalid or zero-valued parameters may still slip through and only manifest as subtle rendering artifacts. Please review and add explicit validation where these fields are populated:

• features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (lines 20–21) define
– MeanFreePathBase
– MeanFreePathHuman

• Locate the CPU-side code (constant-buffer setup or configuration parser) that writes to these fields and ensure it enforces a sensible minimum (e.g. >0) or emits an error/warning for out-of-range values before they reach the GPU.


82-83: Please verify the GAME_UNIT_TO_CM constant and the mm conversion

I wasn’t able to locate the definition of GAME_UNIT_TO_CM in the repo—before shipping, please confirm:

  • Where and how GAME_UNIT_TO_CM is defined (should be the factor from game units to centimeters).
  • That multiplying by 0.1f actually converts the result to millimeters. If 1 cm = 10 mm, the multiplier would typically be 10, not 0.1. Either adjust the factor or update the comment to match the true unit scaling.

Affected location:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (around line 82)
    float2 uvScale = (GAME_UNIT_TO_CM * 0.1f * SSSScaleX) / centerDepth;  // Scale in mm

Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli Outdated
Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli Outdated
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

♻️ Duplicate comments (6)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli (2)

105-105: Inconsistent albedo sampling for center pixel in horizontal path.

The center pixel color is divided by its own albedo (from DTid.xy), but neighbor samples at line 155 are divided by the center pixel's albedo instead of their own.


155-155: Inconsistent albedo sampling for neighbor pixels.

In the neighbor sample loop, you're using AlbedoTexture[DTid.xy].rgb (the center pixel's albedo) instead of AlbedoTexture[coords].rgb (the neighbor pixel's albedo). This appears inconsistent with the intent of albedo normalization for each sample.

Apply this diff to use the correct albedo coordinates:

-		color.rgb = Color::GammaToLinear(color.rgb / max(AlbedoTexture[DTid.xy].rgb, EPSILON_SSS_ALBEDO));
+		color.rgb = Color::GammaToLinear(color.rgb / max(AlbedoTexture[coords].rgb, EPSILON_SSS_ALBEDO));
features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (4)

15-18: Address CDF numerical stability issues.

The CDF function can produce values outside [0,1] when r is very small relative to d, potentially causing negative values that could destabilize the sampling logic.

Consider clamping the result and protecting against division by zero:

 float3 GetCDF(float3 d, float3 r, float rand)
 {
-	return 1 - 0.25 * exp(-r / d) - 0.75 * exp(-r / (3 * d)) - rand;
+	d = max(d, 1e-6f);
+	return saturate(1 - 0.25 * exp(-r / d) - 0.75 * exp(-r / (3 * d)) - rand);
 }

46-55: Document the magic constants in scaling factor calculation.

The scaling factor function uses unexplained constants that need documentation for maintainability.

 float3 GetScalingFactor(float3 albedo)
 {
-	// we have three methods for calculating the scaling factor
-	// d = l / (1.85 − A + 7|A − 0.8|^3)
-	// d = l / (1.9 − A + 3.5(A − 0.8)^2)
-	// d = l / (3.5 + 100(A − 0.33)^4)
-	// here we choose the third to use diffuse mean free path as parameter.
+	// Based on Burley 2015 paper, method 3: d = l / (3.5 + 100(A − 0.33)^4)
+	// 0.33f: albedo offset for optimal fitting
+	// 3.5f: baseline scaling factor  
+	// 100.f: coefficient controlling profile curvature
 	float3 value = albedo - 0.33f;
 	return 3.5f + 100.f * value * value * value * value;
 }

87-92: Protect against division by zero in UV scale calculations.

The uvScale components could be zero when centerDepth is very large, leading to division by zero in the centerRadius calculation.

-	float2 uvScale = (GAME_UNIT_TO_CM * 0.1f * SSSScaleX) / centerDepth;  // Scale in mm
+	float2 uvScale = (GAME_UNIT_TO_CM * 0.1f * SSSScaleX) / max(centerDepth, 1e-5f);  // Scale in mm

 	// center sample weight
-	float centerRadius = 0.5f * (SharedData::BufferDim.z / uvScale.x + SharedData::BufferDim.w / uvScale.y);
+	float centerRadius = 0.5f * (SharedData::BufferDim.z / max(uvScale.x, 1e-5f) + SharedData::BufferDim.w / max(uvScale.y, 1e-5f));

138-140: Protect against division by zero in sample normalization.

If BurleySamples is 0, the rcp(BurleySamples) will cause division by zero.

-	colorSum *= bleedSum * rcp(BurleySamples);
+	colorSum *= bleedSum * rcp(max(BurleySamples, 1));
🧹 Nitpick comments (1)
src/Features/SubsurfaceScattering.cpp (1)

296-297: Update resource cleanup count to match binding count.

The shader resource cleanup should match the expanded resource binding count.

-	ID3D11ShaderResourceView* views[5]{ nullptr, nullptr, nullptr };
-	context->CSSetShaderResources(0, 5, views);
+	ID3D11ShaderResourceView* views[5]{ nullptr, nullptr, nullptr, nullptr, nullptr };
+	context->CSSetShaderResources(0, 5, views);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25c9665 and 7df2bf5.

📒 Files selected for processing (6)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (1 hunks)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli (2 hunks)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3 hunks)
  • package/Shaders/Common/Math.hlsli (1 hunks)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
  • src/Features/SubsurfaceScattering.h (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Features/SubsurfaceScattering.h
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-01T18:01:07.079Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#0
File: :0-0
Timestamp: 2025-07-01T18:01:07.079Z
Learning: In the skyrim-community-shaders project, simple scalar constants in HLSL shaders use #define (e.g., #define NTHREADS 128), while more complex constants use static const within namespaces (e.g., Math namespace in Math.hlsli). For epsilon standardization, #define is the appropriate choice since epsilon values are simple scalar constants.

Applied to files:

  • package/Shaders/Common/Math.hlsli
📚 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli
  • src/Features/SubsurfaceScattering.cpp
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli
⏰ 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: Build plugin and addons
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
🔇 Additional comments (10)
package/Shaders/Common/Math.hlsli (1)

4-4: LGTM! Epsilon constant follows established patterns.

The EPSILON_SSS_ALBEDO constant follows the existing naming convention and value format used in this file. The #define approach is consistent with other epsilon constants and appropriate for scalar constants as established in the project.

features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli (1)

162-162: LGTM! Improved numerical stability for profile scaling.

The addition of max(profile.y, 0.0001) prevents potential division by zero when profile.y is very small, improving the numerical stability of the depth difference blending calculation.

src/Features/SubsurfaceScattering.cpp (7)

15-20: LGTM! Settings structure properly extended for Burley mode.

The serialization properly includes all new settings fields for Burley SSS mode including the mode selector and Burley-specific parameters.


33-84: Well-structured dual-mode UI implementation.

The UI properly separates separable SSS and Burley modes with appropriate controls for each. The radio button selection and conditional UI sections provide a clean user experience.


201-217: LGTM! Proper constant buffer setup for both modes.

The constant buffer correctly populates both the existing separable SSS parameters and the new Burley-specific parameters including projection scaling and mean free path settings.


232-246: Resource binding properly extended for Burley mode.

The shader resource views array is correctly expanded to include albedo and normal textures required by the Burley implementation, maintaining backward compatibility with the separable SSS path.


249-290: Well-implemented dual rendering pipeline.

The conditional rendering logic properly separates the two-pass separable SSS from the single-pass Burley implementation. The resource copying from temporary to main texture for Burley mode is handled correctly.


378-381: LGTM! Shader cache management properly updated.

The Burley compute shader is correctly added to the cache cleanup routine to ensure proper resource management.


402-409: LGTM! Lazy compilation pattern maintained for Burley shader.

The Burley compute shader follows the established lazy compilation pattern used by the horizontal and vertical blur shaders.

features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (1)

57-145: Well-structured Monte Carlo sampling implementation.

The BurleyNormalizedSS function implements a comprehensive Monte Carlo sampling approach for subsurface scattering with proper:

  • Early exit conditions for invalid depth or zero SSS amount
  • Albedo-based scaling and gamma correction
  • World-space normal transformations
  • Proper PDF/CDF-based sampling
  • Depth-aware radius corrections
  • Normal-weighted blending

The implementation correctly follows the Burley BSSRDF model with appropriate physical parameterization.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Aug 13, 2025

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

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

🧹 Nitpick comments (1)
src/Features/SubsurfaceScattering.cpp (1)

201-217: Verify projection matrix access pattern and consider caching expensive calculations.

The code accesses cameraData.projMat.m[0][0] to get the projection distance, then performs trigonometric calculations each frame. While functionally correct, this could be optimized.

Consider caching the field of view calculation if the projection matrix doesn't change frequently:

 const float distanceToProjectionWindow = cameraData.projMat.m[0][0];
-
-blurCBData.SSSS_FOVY = atan(1.0f / distanceToProjectionWindow) * 2.0f * (180.0f / 3.14159265359f);
+
+// Cache FOV calculation if projection matrix is stable
+static float cachedFOVY = 0.0f;
+static float cachedProjectionDistance = 0.0f;
+if (cachedProjectionDistance != distanceToProjectionWindow) {
+    cachedProjectionDistance = distanceToProjectionWindow;
+    cachedFOVY = atan(1.0f / distanceToProjectionWindow) * 2.0f * (180.0f / 3.14159265359f);
+}
+blurCBData.SSSS_FOVY = cachedFOVY;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfd49cc and d0b1c07.

📒 Files selected for processing (1)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
🧰 Additional context used
🧠 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/Features/SubsurfaceScattering.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). (3)
  • GitHub Check: Build plugin and addons
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
🔇 Additional comments (6)
src/Features/SubsurfaceScattering.cpp (6)

15-20: LGTM! Clean addition of new configuration fields.

The serialization fields for the new Burley SSS parameters are correctly added to the JSON mapping with appropriate types and naming conventions.


33-84: Well-structured UI implementation with proper mode separation.

The UI correctly implements a radio button mode selector and conditionally shows appropriate controls based on the selected SSS mode. The parameter ranges and tooltips are appropriate for their respective use cases.


296-297: Update resource cleanup to match new binding count.

The cleanup code should match the number of bound shader resources (now 5 instead of the previous count).


378-381: LGTM! Proper shader cache management.

The Burley compute shader is correctly added to the cache cleanup routine, following the same pattern as existing shaders.


402-409: LGTM! Consistent shader compilation pattern.

The Burley compute shader compilation follows the established pattern and correctly uses the BURLEY define to compile the specialized variant.


232-246: Ensure ALBEDO and NORMALROUGHNESS are always initialized before binding
The code now binds ALBEDO and NORMALROUGHNESS SRVs unconditionally in both SSS modes, but only Burley mode consumes them. You must guarantee these render targets exist whenever subsurface scattering is enabled to avoid null‐pointer binds at runtime.

• src/Features/SubsurfaceScattering.cpp (lines 232–246): SRV binding of albedo and normal
• Renderer initialization (e.g. your RenderTargetsManager or similar): verify that ALBEDO and NORMALROUGHNESS are registered in renderTargets[] whenever SSS is active

Consider adding explicit null‐checks or assertions to catch missing targets early.

Comment thread src/Features/SubsurfaceScattering.cpp
Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli Outdated
Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSS.hlsli Outdated
Comment thread src/Features/SubsurfaceScattering.cpp
Comment thread src/Features/SubsurfaceScattering.cpp Outdated
Comment thread src/Features/SubsurfaceScattering.cpp Outdated
Comment thread src/Features/SubsurfaceScattering.cpp
Comment thread src/Features/SubsurfaceScattering.cpp Outdated
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

♻️ Duplicate comments (2)
src/Features/SubsurfaceScattering.cpp (2)

33-36: Typo and clarity: “Separatable” → “Separable”

Minor labeling nit. Also consider a hover tooltip to explain each mode succinctly.

Apply this diff:

-        ImGui::RadioButton("Separatable SSS", &settings.SSMode, 0);
+        ImGui::RadioButton("Separable SSS", &settings.SSMode, 0);
         ImGui::SameLine();
         ImGui::RadioButton("Burley", &settings.SSMode, 1);

290-301: Burley path should write directly to main UAV; remove extra CopyResource (and avoid SRV/UAV hazard)

Currently, UAV 0 is still blurHorizontalTemp (set at Line 248), so Burley writes to temp and then copies to main. This is unnecessary overhead. Bind main.UAV before dispatch and remove the copy. If BURLEY doesn’t sample t0, unbind t0 to avoid SRV/UAV aliasing on main.

Apply this diff:

         } else if (settings.SSMode == 1) {
             // Burley pass to main texture
             {
                 TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Burley");
 
+                // Write directly to main UAV and avoid extra copy
+                ID3D11UnorderedAccessView* uavMain[1] = { main.UAV };
+                context->CSSetUnorderedAccessViews(0, 1, uavMain, nullptr);
+
+                // If BURLEY path doesn't read main.SRV (t0), prevent read-write hazard
+                // by unbinding SRV slot 0. Leave t1..t4 (depth/mask/albedo/normal) intact.
+                ID3D11ShaderResourceView* nullSRV[1]{ nullptr };
+                context->CSSetShaderResources(0, 1, nullSRV);
+
                 auto shader = GetComputeShaderBurley();
                 context->CSSetShader(shader, nullptr, 0);
 
                 context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
-
-                context->CopyResource(main.texture, blurHorizontalTemp->resource.get());
             }
         }

To confirm whether BURLEY samples main (t0), please run:

#!/bin/bash
# Check if BURLEY path samples main SRV (t0) in SeparableSSSCS.hlsl
fd -a SeparableSSSCS.hlsl Burley.hlsli
rg -n "register\\(t0\\)|Texture2D.*main|MainTexture|gColor|t0" -A 6 -B 3 features
rg -n "BURLEY" -A 20 -B 5 features/Subsurface\ Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
  • If t0 is read under BURLEY, we must keep writing to a different UAV (temp) or ping-pong, or rework to a different input buffer to avoid SRV/UAV aliasing. In that case, we can still eliminate the copy by swapping handles or ping-ponging textures.
  • If t0 isn’t read, the above diff is safe and optimal.

I can provide a handle-swap variant if we confirm aliasing is required for input.

🧹 Nitpick comments (2)
src/Features/SubsurfaceScattering.cpp (2)

76-77: Tooltip grammar: “channel” → “channels”

Minor wording nit to improve clarity.

Apply this diff:

-                    ImGui::Text("Controls how far light goes into the subsurface in the red, green, and blue channel. It is scaled by the Mean Free Path Distance.");
+                    ImGui::Text("Controls how far light goes into the subsurface in the red, green, and blue channels. It is scaled by the Mean Free Path Distance.");

(Apply in both Base and Human profile tooltips.)

Also applies to: 88-89


244-246: Bind albedo/normal only when in Burley mode (minor CPU overhead reduction)

Albedo and normal SRVs are only needed for Burley. Binding them unconditionally is harmless but avoidable work.

I can sketch a small refactor to move their binding under the SSMode == 1 branch if desired.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 07436ff and dc2a76a.

📒 Files selected for processing (1)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
🧰 Additional context used
🧠 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/Features/SubsurfaceScattering.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). (3)
  • GitHub Check: Build plugin and addons
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
🔇 Additional comments (7)
src/Features/SubsurfaceScattering.cpp (7)

15-20: Settings JSON: confirm defaults/back-compat for new fields

Adding SSMode, BurleySamples, MeanFreePathBase, and MeanFreePathHuman looks fine with NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT, but please ensure:

  • Settings defaults initialize SSMode to separable (0) to preserve old behavior.
  • MeanFreePathBase/Human have sane defaults (e.g., human MFP tuned values) when loading existing configs lacking these fields.

If helpful, I can scan SubsurfaceScattering.h and existing saved JSONs to verify defaults and back-compat.


252-259: LGTM on SRV fan-out and ARRAYSIZE usage

Using an SRV array with ARRAYSIZE(views) is tidy and consistent with engine patterns.


261-289: Separable path looks correct (UAV ping-pong + main writeback)

Horizontal writes to temp, vertical reads from temp and writes to main. Unbinds are handled. Good.


308-310: LGTM on complete SRV unbind

Nulling all five SRV slots after dispatch avoids lingering bindings and hazards across passes.


390-393: LGTM on shader cache cleanup for Burley

Properly releasing burleySS alongside existing shaders is correct.


414-421: LGTM on lazy BURLEY shader compile

Compiling SeparableSSSCS.hlsl with BURLEY define on demand is consistent with existing pattern.


225-229: HLSL declares BurleySamples as float — the UB concern is incorrect; verify C++ CB layout

PerFrameSSS cbuffer in features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl declares:

  • float BurleySamples
  • float4 MeanFreePathBase
  • float4 MeanFreePathHuman

Action items:

  • Check the C++ constant-buffer struct (blurCBData / BlurCB) to ensure it uses matching types (float for BurleySamples; a 4-component float type for MeanFreePathBase/MeanFreePathHuman) and respects 16-byte packing for CBs.
  • I could not find blurCBData or the C++ CB struct in the repository search — please point me to the C++ file if you want me to verify the C++ side.

Likely an incorrect or invalid review comment.

Comment thread src/Features/SubsurfaceScattering.cpp Outdated
Comment thread src/Features/SubsurfaceScattering.cpp Outdated
Comment thread src/Features/SubsurfaceScattering.cpp Outdated
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

♻️ Duplicate comments (2)
src/Features/SubsurfaceScattering.cpp (2)

72-72: Use integer slider for “Burley Samples”.

Samples are counts; using a float invites fractional states and type drift vs HLSL.

Apply:

-            ImGui::SliderFloat("Burley Samples", &settings.BurleySamples, 1.0f, 64.0f, "%.0f", ImGuiSliderFlags_AlwaysClamp);
+            ImGui::SliderInt("Burley Samples", &settings.BurleySamples, 1, 64);

If the backing C++/HLSL types are float, consider switching them to int/uint consistently in C++ (Settings/BlurCB) and HLSL (cbuffer) to remove implicit casts.


213-220: FOVy and projection scales are computed from fx (m[0][0]); should use fy (m[1][1]).

This currently stores FOVx into SSSS_FOVY and derives aspect-incorrect scales. Pass per-axis projection scales.

Apply:

-        const float distanceToProjectionWindow = cameraData.projMat.m[0][0];
-
-        blurCBData.SSSS_FOVY = atan(1.0f / distanceToProjectionWindow) * 2.0f * (180.0f / 3.14159265359f);
-        const float SSSScaleZ = distanceToProjectionWindow;
-        const float SSSScaleX = SSSScaleZ * 0.5f;
-
-        blurCBData.SSSScaleX = SSSScaleX;
-        blurCBData.SSSScaleZ = SSSScaleZ;
+        const float fx = cameraData.projMat.m[0][0];
+        const float fy = cameraData.projMat.m[1][1];
+
+        // FOVy = 2 * atan(1 / fy)
+        blurCBData.SSSS_FOVY = 2.0f * atan(1.0f / fy) * (180.0f / 3.14159265358979323846f);
+        // Pass projection scale terms per-axis for correct aspect handling.
+        blurCBData.SSSScaleX = fx;
+        blurCBData.SSSScaleZ = fy;

Note: If shader semantics allow, consider renaming SSSScaleZ to SSSScaleY for clarity in a follow-up.

🧹 Nitpick comments (1)
src/Features/SubsurfaceScattering.cpp (1)

414-421: On-demand BURLEY compile looks correct; optional: set debug name for easier GPU debugging.

Consider calling SetPrivateData(WKPDID_D3DDebugObjectName, ...) on the shader for PIX/NSight clarity, mirroring other shaders if applicable.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dc2a76a and 1682e1e.

📒 Files selected for processing (1)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
🧰 Additional context used
🧠 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/Features/SubsurfaceScattering.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). (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 (6)
src/Features/SubsurfaceScattering.cpp (6)

15-20: Settings JSON schema extension looks good; confirm defaults for new fields.

The WITH_DEFAULT macro will tolerate missing keys in old configs. Ensure the C++ struct initializes sane defaults for SSMode, BurleySamples, MeanFreePathBase/Human to avoid undefined runtime behavior on first run.

Would you like me to scan SubsurfaceScattering.h and the HLSL CBs to verify default values and type alignment for these new fields?


33-36: Mode selector UI is clear and minimal.

Radio buttons for Separable vs Burley are a good UX fit.


308-309: Good cleanup: unbinding all SRVs via ARRAYSIZE.

Prevents SRV leakage into subsequent passes.


390-393: Shader cache: correctly releasing burleySS.

Matches existing cache-clearing pattern.


225-229: Verify CB types/packing for BurleySamples and MeanFreePath in PerFrameSSS

HLSL shows PerFrameSSS defines:

  • float BurleySamples;
  • float4 MeanFreePathBase;
  • float4 MeanFreePathHuman
    (in features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl).

I could not find the CPU-side constant-buffer struct (the blurCBData / BlurCB definition or src/Features/SubsurfaceScattering.cpp is not present in this branch). Please confirm the C++ CB field types and packing match the HLSL layout. If BurleySamples is an integer sample count, change the CPU and shader fields to int/uint (and keep proper 16‑byte packing) to avoid implicit float→int casts and packing misalignment.

Please check:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (PerFrameSSS)
  • CPU-side CB definition that populates blurCBData (wherever blurCBData/BlurCB is defined)

247-249: Fix Burley pass comment and unbind UAV before CopyResource

Short: SeparableSSSCS.hlsl writes to u0 (SSSRW) and reads t0..t4, so the temp→main pattern makes sense; I couldn't find the referenced C++ file to verify the exact binding — please confirm the file path or apply the patch below.

Files of interest:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl — declares RWTexture2D SSSRW : register(u0) and reads ColorTexture (t0), MaskTexture (t2), AlbedoTexture (t3), etc.
  • src/Features/SubsurfaceScattering.cpp — not found in the repo (original review referenced lines 247-249 and 291-301); I couldn't verify the C++ binding/COPY calls.

Suggested change (update comment + unbind UAV before CopyResource):

-        } else if (settings.SSMode == 1) {
-            // Burley pass to main texture
+        } else if (settings.SSMode == 1) {
+            // Burley pass to temporary texture, then copy to main
             {
                 TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Burley");
 
                 auto shader = GetComputeShaderBurley();
                 context->CSSetShader(shader, nullptr, 0);
 
                 context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
 
+                // Unbind UAV before copying resources to avoid driver hazards.
+                uav = nullptr;
+                context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
+
                 context->CopyResource(main.texture, blurHorizontalTemp->resource.get());
             }
         }

Notes: If the BURLEY shader definitely does NOT sample main.SRV, you can avoid the copy by binding main.UAV for the dispatch (ensure no SRV slot still references main). I can locate and patch the exact C++ file if you provide the correct path or allow me to search for the binding code.

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: 4

🔭 Outside diff range comments (1)
src/Features/SubsurfaceScattering.h (1)

41-51: Mirror CB layout change: make BurleySamples integral in BlurCB

Keep C++<->HLSL CB in sync to avoid undefined behavior from mismatched layouts.

         float4 HumanProfile;
         float SSSS_FOVY;
-        float BurleySamples;
+        int   BurleySamples;
         float2 pad;
         float4 MeanFreePathBase;
         float4 MeanFreePathHuman;

Note: int is 32-bit; packing with float2 pad still preserves 16-byte alignment for the subsequent float4s.

♻️ Duplicate comments (3)
src/Features/SubsurfaceScattering.cpp (3)

71-96: Use an integer slider for “Burley Samples” to prevent fractional values

Samples are counts and should be integral. This also aligns with the proposed HLSL/C++ type change.

-            ImGui::SliderFloat("Burley Samples", &settings.BurleySamples, 1.0f, 64.0f, "%.0f", ImGuiSliderFlags_AlwaysClamp);
+            ImGui::SliderInt("Burley Samples", &settings.BurleySamples, 1, 64);

If you keep BurleySamples as uint, use a local int mirror for UI and clamp/assign back.


213-216: Compute FOVy from projMat.m[1][1] (fy), not m[0][0] (fx)

Current math yields FOVx but stores in SSSS_FOVY. Use fy for correctness.

-        const float distanceToProjectionWindow = cameraData.projMat.m[0][0];
-
-        blurCBData.SSSS_FOVY = atan(1.0f / distanceToProjectionWindow) * 2.0f * (180.0f / 3.14159265359f);
+        const float fy = cameraData.projMat.m[1][1];
+        blurCBData.SSSS_FOVY = 2.0f * atan(1.0f / fy) * (180.0f / 3.14159265358979323846f);

If shaders rely on SSSS_FOVY to scale taps, this improves kernel correctness across aspect ratios.


285-296: Avoid post-dispatch CopyResource in Burley path; bind main UAV and read from temp SRV

The current flow writes to blurHorizontalTemp and then copies to main, adding an extra pass. You can flip it: seed temp with main (once), read from temp, and write directly to main — same copy count but no post-dispatch stall. Also avoids SRV/UAV hazards on main.

-        } else if (settings.SSMode == 1) {
-            // Burley pass to main texture
-            {
-                TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Burley");
-
-                auto shader = GetComputeShaderBurley();
-                context->CSSetShader(shader, nullptr, 0);
-
-                context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
-
-                context->CopyResource(main.texture, blurHorizontalTemp->resource.get());
-            }
+        } else if (settings.SSMode == 1) {
+            // Burley pass: copy main -> temp (SRV), write directly to main (UAV)
+            {
+                TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Burley");
+
+                // Seed temp with current main color for SRV reads
+                context->CopyResource(blurHorizontalTemp->resource.get(), main.texture);
+
+                // Bind temp as input color (t0) to avoid SRV/UAV hazard on main
+                views[0] = blurHorizontalTemp->srv.get();
+                context->CSSetShaderResources(0, 1, views);
+
+                // Set main as output UAV
+                ID3D11UnorderedAccessView* uavs[1] = { main.UAV };
+                context->CSSetUnorderedAccessViews(0, 1, uavs, nullptr);
+
+                auto shader = GetComputeShaderBurley();
+                context->CSSetShader(shader, nullptr, 0);
+
+                context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
+            }

If Burley doesn’t read ColorTexture at all, you can skip the pre-copy, null out SRV slot 0, and bind main.UAV directly.

🧹 Nitpick comments (3)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (2)

6-7: NormalTexture is declared but not used

Binding an unused SRV wastes a bind slot and may incur unnecessary bandwidth. If Burley doesn't consume normals yet, defer adding/binding it or guard behind the BURLEY path where it’s actually needed.

Apply one of these diffs:

Option A — keep declaration but bind only for BURLEY builds:

-Texture2D<float4> NormalTexture : register(t4);
+#if defined(BURLEY)
+Texture2D<float4> NormalTexture : register(t4);
+#endif

Option B — remove until used:

-Texture2D<float4> NormalTexture : register(t4);

38-45: Prefer explicit float literal in max to avoid implicit int→float conversions

Minor clarity/readability nit.

-    SSSRW[DTid.xy] = max(0, color);
+    SSSRW[DTid.xy] = max(0.0f, color);
src/Features/SubsurfaceScattering.cpp (1)

33-36: Add brief hover tooltips for SSS mode choice

Non-experts may not know the difference between Separable and Burley. A one-liner tooltip improves UX without clutter.

-        ImGui::RadioButton("Separable SSS", &settings.SSMode, 0);
+        if (ImGui::RadioButton("Separable SSS", &settings.SSMode, 0)) {}
+        if (auto _tt = Util::HoverTooltipWrapper()) {
+            ImGui::Text("Faster two-pass blur approximation.");
+        }
         ImGui::SameLine();
-        ImGui::RadioButton("Burley", &settings.SSMode, 1);
+        if (ImGui::RadioButton("Burley", &settings.SSMode, 1)) {}
+        if (auto _tt = Util::HoverTooltipWrapper()) {
+            ImGui::Text("Physically-based Burley diffusion (more accurate, costlier).");
+        }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1682e1e and 72c1271.

📒 Files selected for processing (4)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli (1 hunks)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3 hunks)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
  • src/Features/SubsurfaceScattering.h (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli
🧰 Additional context used
🧠 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/Features/SubsurfaceScattering.cpp
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.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 (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (6)
src/Features/SubsurfaceScattering.h (2)

64-65: LGTM: Dedicated compute shader handle for Burley

New handle and accessor are appropriate and scoped alongside existing blur shaders.


106-107: LGTM: Public accessor for Burley compute shader

Consistent with the existing horizontal/vertical getters.

src/Features/SubsurfaceScattering.cpp (4)

15-21: Ensure Settings JSON mapping includes new fields

The new fields are correctly listed in the macro. Keep in mind any future type change for BurleySamples (int) must be reflected here, but nlohmann supports it transparently.


303-307: Good state cleanup

Nulling CBs/SRVs/UAVs after use avoids binding hazards down the line.


375-389: Shader cache clears include Burley

Releasing burleySS here matches existing pattern; safe and complete.


409-416: On-demand Burley shader compilation is consistent with others

Builds SeparableSSSCS.hlsl with BURLEY define — good reuse of the entrypoint.

Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl Outdated
Comment thread src/Features/SubsurfaceScattering.cpp
Comment thread src/Features/SubsurfaceScattering.h
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

♻️ Duplicate comments (4)
src/Features/SubsurfaceScattering.h (1)

26-26: Use integer type for “BurleySamples” in Settings (counts shouldn’t be float)

Sample count is discrete; store it as an int in Settings to avoid fractional states and type drift. Keep BlurCB.BurleySamples as float if HLSL expects float, casting on upload.

-        float BurleySamples = 16.0f;
+        int   BurleySamples = 16;
src/Features/SubsurfaceScattering.cpp (3)

213-213: Fix FOVY computation: use projMat.m[1][1] (fy), not m[0][0] (fx)

Current code computes FOVx but stores in SSSS_FOVY.

-        blurCBData.SSSS_FOVY = atan(1.0f / cameraData.projMat.m[0][0]) * 2.0f * (180.0f / 3.14159265359f);
+        blurCBData.SSSS_FOVY = 2.0f * atan(1.0f / cameraData.projMat.m[1][1]) * (180.0f / 3.14159265359f);

71-73: Make “Burley Samples” an integer slider

Samples are counts; using float permits fractional UI states and mismatches Settings if you switch it to int.

-            ImGui::SliderFloat("Burley Samples", &settings.BurleySamples, 1.0f, 64.0f, "%.0f", ImGuiSliderFlags_AlwaysClamp);
+            ImGui::SliderInt("Burley Samples", &settings.BurleySamples, 1, 64);

245-248: Compile error: trailing comma instead of semicolon

This line won’t compile.

-        views[1] = terrainBlending.loaded ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV,
+        views[1] = terrainBlending.loaded ? terrainBlending.blendedDepthTexture16->srv.get() : depth.depthSRV;
🧹 Nitpick comments (2)
src/Features/SubsurfaceScattering.cpp (2)

74-95: Avoid aliasing cast in ColorEdit3; pass the x component pointer

Minor clarity/readability improvement; avoids reinterpret cast on float4.

-                ImGui::ColorEdit3("Mean Free Path Color", (float*)&settings.MeanFreePathBase);
+                ImGui::ColorEdit3("Mean Free Path Color", &settings.MeanFreePathBase.x);
...
-                ImGui::ColorEdit3("Mean Free Path Color", (float*)&settings.MeanFreePathHuman);
+                ImGui::ColorEdit3("Mean Free Path Color", &settings.MeanFreePathHuman.x);

240-242: Bind UAVs inside mode branches; optionally write Burley pass directly to main (avoid copy) with SRV/UAV safety

Unconditionally binding blurHorizontalTemp UAV (Line 240) means Burley also writes to temp and then copies. Move UAV binding into the per‑mode branches. If Burley doesn’t sample main.SRV, bind main.UAV and remove the CopyResource. If it does sample main.SRV, keep the temp (or unbind SRV 0 before binding main.UAV).

Proposed refactor:

-        ID3D11UnorderedAccessView* uav = blurHorizontalTemp->uav.get();
-        context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
+        // Defer UAV binding to per-mode branches

Bind for separable horizontal pass only:

             // Horizontal pass to temporary texture
             {
                 TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Horizontal");
+                // Output to temp
+                ID3D11UnorderedAccessView* uavH[1] = { blurHorizontalTemp->uav.get() };
+                context->CSSetUnorderedAccessViews(0, 1, uavH, nullptr);

                 auto shader = GetComputeShaderHorizontalBlur();
                 context->CSSetShader(shader, nullptr, 0);

                 context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
             }

For Burley, write directly to main.UAV (only if the shader doesn’t read main SRV; otherwise keep current temp+copy):

         } else if (settings.SSMode == 1) {
             // Burley pass to main texture
             {
                 TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Burley");
-                auto shader = GetComputeShaderBurley();
-                context->CSSetShader(shader, nullptr, 0);
-
-                context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
-
-                context->CopyResource(main.texture, blurHorizontalTemp->resource.get());
+                // If Burley path does NOT sample main.SRV: unbind SRV[0] to avoid SRV/UAV conflict
+                ID3D11ShaderResourceView* nullSRV[1]{ nullptr };
+                context->CSSetShaderResources(0, 1, nullSRV);
+
+                // Set main UAV as output
+                ID3D11UnorderedAccessView* uavMain[1]{ main.UAV };
+                context->CSSetUnorderedAccessViews(0, 1, uavMain, nullptr);
+
+                auto shader = GetComputeShaderBurley();
+                context->CSSetShader(shader, nullptr, 0);
+
+                context->Dispatch(dispatchCount.x, dispatchCount.y, 1);
             }
         }

Verification needed:

  • If the BURLEY shader samples SRV slot 0 (main), keep the current temp + CopyResource approach, or switch SRV slot 0 to a non-conflicting texture and unbind it before binding main.UAV.
  • Run with D3D11 debug layer to catch SRV/UAV conflicts during Burley.

Also applies to: 254-283, 283-295

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 72c1271 and b365cf0.

📒 Files selected for processing (2)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
  • src/Features/SubsurfaceScattering.h (4 hunks)
🧰 Additional context used
🧠 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/Features/SubsurfaceScattering.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). (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 (11)
src/Features/SubsurfaceScattering.h (5)

23-23: SS mode field addition looks good

Public setting is integer (mode selector), consistent with UI and shader branching.


27-28: Mean Free Path defaults: sensible and self‑documenting

RGB in xyz and distance in w is clear. Good defaults.


47-51: CB layout: addition and alignment look correct

Keeping BurleySamples as float with pad[2] preserves 16‑byte alignment before the two float4s. Matches typical HLSL packing.


64-64: Compute shader handle for Burley path

New handle is properly introduced; ensure it’s released (verified in ClearShaderCache).


106-107: Accessor for Burley compute shader

Necessary for lazy compilation and selection at runtime.

src/Features/SubsurfaceScattering.cpp (6)

15-20: JSON (de)serialization updated correctly

New fields are included in NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT; defaults handle backward compat.


33-36: Mode selector UI: clear and consistent

Radio buttons for Separable vs Burley are straightforward.


218-222: Per-frame CB fields are populated correctly

Values mapped 1:1 from Settings to CB; implicit int→float cast for BurleySamples is fine if Settings switches to int.


252-252: Nice: using ARRAYSIZE for SRV binding count

Prevents drift if views array changes.


383-386: Shader cache cleanup includes Burley shader

Prevents leaks and ensures recompile on cache clear.


407-414: Lazy compilation of Burley compute shader with define

Compiles SeparableSSSCS.hlsl with BURLEY define — matches header and runtime branching.

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

🔭 Outside diff range comments (1)
src/Features/SubsurfaceScattering.cpp (1)

25-31: Avoid casting uint to bool in ImGui checkbox (UB risk)*

Casting a uint* to bool* is unsafe; bool is 1 byte vs uint 4 bytes. Use a local bool and write back.

-        ImGui::Checkbox("Enable Character Lighting", (bool*)&settings.EnableCharacterLighting);
+        {
+            bool enabled = settings.EnableCharacterLighting != 0u;
+            if (ImGui::Checkbox("Enable Character Lighting", &enabled)) {
+                settings.EnableCharacterLighting = enabled ? 1u : 0u;
+            }
+        }
♻️ Duplicate comments (4)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

62-63: Fix color-space math: multiply in linear, then encode to gamma

Currently multiplies gamma(color) by gamma(albedo). Convert albedo to linear, multiply in linear, then convert the final result if the target expects gamma.

-        color.rgb = Color::LinearToGamma(color.rgb) * AlbedoTexture[DTid.xy].rgb;
-        SSSRW[DTid.xy] = float4(color.rgb, 1.0);
+        float3 albedoLin = Color::GammaToLinear(saturate(AlbedoTexture[DTid.xy].rgb));
+        float3 outLin    = color.rgb * albedoLin;
+        SSSRW[DTid.xy]   = float4(Color::LinearToGamma(outLin), 1.0f);

If this stage already operates in linear and writes to a linear target, drop the gamma conversions and write outLin directly.

src/Features/SubsurfaceScattering.cpp (3)

213-213: Compute FOVy from projMat.m[1][1] (fy), not m[0][0] (fx)

You’re currently storing FOVx into SSSS_FOVY. Use fy for FOVy.

-        blurCBData.SSSS_FOVY = atan(1.0f / cameraData.projMat.m[0][0]) * 2.0f * (180.0f / 3.14159265359f);
+        blurCBData.SSSS_FOVY = 2.0f * atan(1.0f / cameraData.projMat.m[1][1]) * (180.0f / 3.14159265359f);

72-72: Don’t cast uint to int for SliderInt**

Avoid pointer type punning. Use a local int and write back to the uint.

-            ImGui::SliderInt("Burley Samples", (int*)&settings.BurleySamples, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
+            {
+                int samples = static_cast<int>(settings.BurleySamples);
+                if (ImGui::SliderInt("Burley Samples", &samples, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp)) {
+                    settings.BurleySamples = static_cast<uint>(samples);
+                }
+            }

283-295: Fix D3D11 resource hazard: CopyResource while main is bound as SRV

In the Burley path you write to blurHorizontalTemp UAV and then CopyResource to main.texture while main.SRV is still bound (and blurHorizontalTemp UAV is also bound). This is illegal with the D3D11 debug layer and can cause undefined behavior.

Either:

  • Keep writing to temp (to avoid read/write hazards with ColorTexture=t0=main.SRV), but unbind SRVs/UAVs referencing the src/dst before CopyResource; or
  • Rebind main.UAV and avoid the copy, but only if you don’t read from main.SRV in the same dispatch (not true here).

Apply the safe unbind-before-copy fix:

         } else if (settings.SSMode == 1) {
             // Burley pass to main texture
             {
                 TracyD3D11Zone(globals::state->tracyCtx, "Subsurface Scattering - Burley");

                 auto shader = GetComputeShaderBurley();
                 context->CSSetShader(shader, nullptr, 0);

                 context->Dispatch(dispatchCount.x, dispatchCount.y, 1);

-                context->CopyResource(main.texture, blurHorizontalTemp->resource.get());
+                // Unbind SRVs/UAVs that alias the copy destination/source before copying.
+                ID3D11ShaderResourceView* nullSRVs[5]{ nullptr, nullptr, nullptr, nullptr, nullptr };
+                context->CSSetShaderResources(0, ARRAYSIZE(nullSRVs), nullSRVs);
+                ID3D11UnorderedAccessView* nullUAV{ nullptr };
+                context->CSSetUnorderedAccessViews(0, 1, &nullUAV, nullptr);
+
+                context->CopyResource(main.texture, blurHorizontalTemp->resource.get());
             }
         }

Optional follow-up: to save bandwidth, consider binding main.UAV for the Burley dispatch and sampling ColorTexture from a history or pre-SSS buffer so you can eliminate the copy altogether.

🧹 Nitpick comments (1)
src/Features/SubsurfaceScattering.h (1)

56-59: Remove unused ‘validMaterial’ (singular) to avoid confusion with ‘validMaterials’

There are both validMaterial and validMaterials; only validMaterials is used. Keep one.

-    bool validMaterial = true;
     bool updateKernels = true;
     bool validMaterials = false;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b365cf0 and 70f833e.

📒 Files selected for processing (3)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3 hunks)
  • src/Features/SubsurfaceScattering.cpp (6 hunks)
  • src/Features/SubsurfaceScattering.h (4 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent 4-byte size, proper 16-byte alignment in constant buffers, and cross-platform compatibility when passing data between C++ and HLSL shaders.

Applied to files:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent size, alignment, and cross-platform compatibility when passing data to shader constant buffers.

Applied to files:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
📚 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
  • src/Features/SubsurfaceScattering.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). (3)
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (10)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (4)

6-7: Bindings and include selection look correct

  • SRV slots t0–t4 map as expected from C++ bindings (Color, Depth, Mask, Albedo, Normal).
  • Conditional include via BURLEY/HORIZONTAL matches the dispatch paths compiled in C++.

Also applies to: 27-31


17-20: Good: BurleySamples moved to uint; CB alignment preserved

Using uint for sample count matches semantics and avoids float→int casts in HLSL. The padding keeps the 16-byte alignment intact.


36-37: Eye index retrieval is fine (VR-safe, no-op in mono)

Stereo::GetEyeIndexFromTexCoord is cheap and benign in mono; okay to keep here.


38-45: Burley and horizontal branches look consistent; clamping to non-negative is sensible

  • Burley path uses mask channels as sssAmount/humanProfile and writes max(0, color).
  • Horizontal pass switches direction to float2(1,0) and also clamps negative values.

Also applies to: 46-53

src/Features/SubsurfaceScattering.h (3)

23-28: Settings types align with shader usage

  • SSMode as int is fine for UI branching.
  • BurleySamples as uint matches the HLSL CB (PerFrameSSS::BurleySamples).
  • Defaults for mean free paths look reasonable.

40-51: CB layout mirrors HLSL (two 21-sample kernels + new fields)

BaseKernel/HumanKernel map cleanly to the single HLSL float4 Kernels[42] array; added fields and padding maintain alignment.


64-64: Burley shader handle and accessor are appropriate

Shader handle addition and lazy compilation accessor for Burley mode align with the dispatch logic in cpp.

Also applies to: 106-107

src/Features/SubsurfaceScattering.cpp (3)

245-252: SRV array size matches shader declarations (t0–t4)

Five SRVs are bound in order: main, depth (or blended), mask, albedo, normal. Matches the HLSL t0–t4 layout.


373-386: Shader cache cleanup correctly releases burleySS

Ensures the new shader is released in ClearShaderCache.


407-414: Lazy compilation path for Burley shader is sound

Compiles SeparableSSSCS.hlsl with BURLEY define, consistent with HLSL conditional includes.

Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/Burley.hlsli Outdated
Comment thread features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl Outdated
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

♻️ Duplicate comments (1)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

58-64: Fix color-space: multiply SSS result by albedo in linear, then gamma-encode; also clamp negatives

Right now you convert the SSS result to gamma and then multiply by AlbedoTexture, which yields incorrect results whether the albedo fetch is linear or gamma. Multiply in linear, clamp, then convert once at the end.

Apply:

-        float4 color = SSSSBlurCS(DTid.xy, texCoord, float2(0.0, 1.0), sssAmount, humanProfile);
-        color.rgb = Color::LinearToGamma(color.rgb) * AlbedoTexture[DTid.xy].rgb;
-        SSSRW[DTid.xy] = float4(color.rgb, 1.0);
+        float4 colorLin   = SSSSBlurCS(DTid.xy, texCoord, float2(0.0, 1.0), sssAmount, humanProfile);
+        // If AlbedoTexture SRV is not sRGB-typed, this explicit decode is required. If it is sRGB-typed, keep albedoLin = AlbedoTexture[...].rgb.
+        float3 albedoLin  = Color::GammaToLinear(saturate(AlbedoTexture[DTid.xy].rgb));
+        float3 outLin     = max(0.0, colorLin.rgb) * albedoLin;
+        SSSRW[DTid.xy]    = float4(Color::LinearToGamma(outLin), 1.0f);

If your render target expects linear, skip the LinearToGamma and write outLin directly.

🧹 Nitpick comments (3)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3)

36-41: Compute eyeIndex only when BURLEY is enabled

eyeIndex is only used by the Burley path; compute it inside that branch to avoid unnecessary work and potential compile issues if Stereo utilities are not available in other variants.

Apply:

-    uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(texCoord);
-
-#if defined(BURLEY)
-
-    float sssAmount = MaskTexture[DTid.xy].x;
-    bool humanProfile = MaskTexture[DTid.xy].y > 0.0;
+#if defined(BURLEY)
+    uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(texCoord);
+    float2 mask = MaskTexture[DTid.xy].xy;
+    float sssAmount   = mask.x;
+    bool  humanProfile = mask.y > 0.0;

38-45: Unify MaskTexture fetch; standardize output alpha and color space with the vertical path

  • Avoid two texture reads; fetch MaskTexture.xy once.
  • Alpha handling is inconsistent: vertical path writes alpha=1, Burley path preserves whatever BurleyNormalizedSS returns. Prefer alpha=1.0 for consistency unless alpha is deliberately carrying metadata.
  • Color space: vertical path gamma-encodes at write. Burley path currently writes without explicit encoding. If BurleyNormalizedSS returns linear (expected), gamma-encode before write to match the vertical path.

Proposed change (assumes BurleyNormalizedSS returns linear RGB and RT expects gamma):

-    float sssAmount = MaskTexture[DTid.xy].x;
-    bool humanProfile = MaskTexture[DTid.xy].y > 0.0;
-
-    float4 color = BurleyNormalizedSS(DTid.xy, texCoord, eyeIndex, sssAmount, humanProfile);
-    SSSRW[DTid.xy] = max(0, color);
+    float2 mask       = MaskTexture[DTid.xy].xy;
+    float  sssAmount  = mask.x;
+    bool   humanProfile = mask.y > 0.0;
+
+    float4 colorLin = BurleyNormalizedSS(DTid.xy, texCoord, eyeIndex, sssAmount, humanProfile);
+    SSSRW[DTid.xy]  = float4(Color::LinearToGamma(max(0.0, colorLin.rgb)), 1.0f);

If your SSSRW target is linear, drop LinearToGamma and keep the max(0.0, ...) with alpha=1.0.


46-53: Reduce redundant MaskTexture reads and standardize alpha in HORIZONTAL pass

Two reads from MaskTexture for .x and .y are unnecessary; also, consider writing alpha=1.0 like the vertical path.

Apply:

-    float sssAmount = MaskTexture[DTid.xy].x;
-    bool humanProfile = MaskTexture[DTid.xy].y > 0.0;
+    float2 mask       = MaskTexture[DTid.xy].xy;
+    float  sssAmount  = mask.x;
+    bool   humanProfile = mask.y > 0.0;
 
-    float4 color = SSSSBlurCS(DTid.xy, texCoord, float2(1.0, 0.0), sssAmount, humanProfile);
-    SSSRW[DTid.xy] = max(0, color);
+    float4 color = SSSSBlurCS(DTid.xy, texCoord, float2(1.0, 0.0), sssAmount, humanProfile);
+    SSSRW[DTid.xy] = float4(max(0.0, color.rgb), 1.0f);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9188641 and 1d92ee7.

📒 Files selected for processing (1)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
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/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
🧠 Learnings (3)
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent 4-byte size, proper 16-byte alignment in constant buffers, and cross-platform compatibility when passing data between C++ and HLSL shaders.

Applied to files:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent size, alignment, and cross-platform compatibility when passing data to shader constant buffers.

Applied to files:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
📚 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.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: Build plugin and addons
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
🔇 Additional comments (4)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (4)

17-20: Good: BurleySamples switched to uint; CB alignment stays 16‑byte clean

The uint type matches sampling semantics and avoids float→int casts. With SSSS_FOVY (float) + BurleySamples (uint) + pad (uint2) you fill a 16‑byte slot, then the float4s remain aligned.

Confirm the corresponding C++ struct(s)/UI were updated to uint/int and that serialization preserves the new type boundaries.


27-31: Conditional include is correct; prevents symbol clashes between Burley vs. Separable

Including only one implementation per compile keeps function/CB namespaces clean. Ensure both headers agree on external resource expectations (e.g., Albedo/Normal presence).


11-21: No register(b1) conflicts found
A ripgrep search for any cbuffer … : register(b1) across all features/**/Shaders/**/*.hlsl* files returned no matches, confirming no other constant buffers are bound to b1. This usage is safe.


6-7: Verify SRV slots t3/t4 and sRGB decode for AlbedoTexture/NormalTexture

• Declarations in SeparableSSSCS.hlsl (lines 6–7):

Texture2D<float4> AlbedoTexture : register(t3);
Texture2D<float4> NormalTexture : register(t4);

• t3/t4 are also bound in multiple Screen Space GI shaders (e.g., upsample.cs.hlsl, radianceDisocc.cs.hlsl, blur.cs.hlsl, gi.cs.hlsl). Ensure your SSS compute‐shader root signature or descriptor tables rebind these slots per‐pass to avoid conflicts.
• Call sites (e.g., line 62 in SeparableSSSCS.hlsl) must bind the correct SRVs for each SSS mode—double‐check your dispatch setup.
• If AlbedoTexture is using an sRGB UNORM format, decide whether to rely on hardware‐linear fetch or to decode manually to prevent double‐decoding in your color-space math.
• NormalTexture is consumed in this CS; the earlier suggestion to remove it if unused elsewhere isn’t applicable.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

56-64: Consolidate Mask fetch and clamp before gamma conversion

The vertical‐pass should sample the mask only once and clamp to non‐negative before applying gamma to avoid NaNs. The gamma conversion belongs only in this final pass—BURLEY and horizontal passes remain linear. If you instead target a linear RT, remove this LinearToGamma here and mirror that change in the BURLEY path so all modes match.

• In features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl, replace the two MaskTexture fetches with a single float2 mask = MaskTexture[DTid.xy].xy;
• Clamp color.rgb using max(color.rgb, 0.0f) before calling Color::LinearToGamma
• Leave gamma conversion only in this final (vertical) pass; BURLEY and horizontal passes output linear values

-   float sssAmount = MaskTexture[DTid.xy].x;
-   if (sssAmount > 0.0) {
-       bool humanProfile = MaskTexture[DTid.xy].y > 0.0;
-
-       float4 color = SSSSBlurCS(DTid.xy, texCoord, float2(0.0, 1.0), sssAmount, humanProfile);
-       color.rgb = Color::LinearToGamma(color.rgb);
-       SSSRW[DTid.xy] = float4(color.rgb, 1.0);
-   }
+   float2 mask       = MaskTexture[DTid.xy].xy;
+   float  sssAmount  = mask.x;
+   if (sssAmount > 0.0f) {
+       bool   humanProfile = mask.y > 0.0f;
+       float4 color        = SSSSBlurCS(DTid.xy, texCoord, float2(0.0, 1.0), sssAmount, humanProfile);
+       color.rgb            = max(color.rgb, 0.0f);                  // clamp negative before gamma
+       SSSRW[DTid.xy]       = float4(Color::LinearToGamma(color.rgb), 1.0f);
+   }
♻️ Duplicate comments (1)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

17-21: CB layout LGTM; uint for BurleySamples matches semantics and alignment

Using uint for BurleySamples avoids float→int casts in loops and keeps 16-byte packing correct with the added uint2 pad and MFP vectors. Nice.

Please confirm the C++ PerFrameSSS/Settings structs and UI slider now use an unsigned integer for BurleySamples:

#!/bin/bash
set -euo pipefail
rg -nP -C3 '\b(BurleySamples|PerFrameSSS|MeanFreePath(Base|Human))\b' src || true
🧹 Nitpick comments (3)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (3)

27-31: Guard shader permutations to prevent invalid macro combos

Add a small preprocessor guard to avoid accidental compilation with both BURLEY and HORIZONTAL defined.

Apply:

 #include "Common/SharedData.hlsli"

+#if defined(BURLEY) && defined(HORIZONTAL)
+#error "BURLEY and HORIZONTAL cannot be defined together for SeparableSSSCS."
+#endif
+
 #if defined(BURLEY)
 #	include "SubsurfaceScattering/Burley.hlsli"
 #else
 #	include "SubsurfaceScattering/SeparableSSS.hlsli"
 #endif

Also ensure the build system emits three permutations only: BURLEY, HORIZONTAL (separable pass 1), and default vertical (separable pass 2).


36-37: Avoid unused local in separable permutations; move eyeIndex inside BURLEY block

eyeIndex is computed for all permutations but only used in BURLEY. Move it under the BURLEY branch to avoid warnings and a tiny amount of redundant work.

Apply:

-uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(texCoord);
-
-#if defined(BURLEY)
+#if defined(BURLEY)
+	uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(texCoord);

46-53: Literal type nit: prefer 0.0f in max to avoid implicit int→float promotion

Small readability tweak in both BURLEY and HORIZONTAL writes.

Apply:

-	SSSRW[DTid.xy] = max(0, color);
+	SSSRW[DTid.xy] = max(0.0f, color);

And the same change in the HORIZONTAL block’s write.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1d92ee7 and 1e162d7.

📒 Files selected for processing (1)
  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (2 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
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/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
🧠 Learnings (3)
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent 4-byte size, proper 16-byte alignment in constant buffers, and cross-platform compatibility when passing data between C++ and HLSL shaders.

Applied to files:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
PR: doodlum/skyrim-community-shaders#577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent size, alignment, and cross-platform compatibility when passing data to shader constant buffers.

Applied to files:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl
📚 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:

  • features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.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 (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (1)
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (1)

6-7: Bind correctness: verify t3/t4 SRV slots and NormalTexture usage

Our scan of the HLSL sources shows that NormalTexture : register(t4) is only declared in
features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl (line 7) and never referenced elsewhere. Please:

  • Remove the unused SRV to avoid wasted binds/reads:

    - Texture2D<float4> NormalTexture : register(t4);
  • Confirm your C++ binding code sets shader resource slots in the same order:
    t3 → AlbedoTexture, t4 → NormalTexture for this compute shader.

  • Scan all HLSL under features/Subsurface Scattering/Shaders for any other register(t3) / register(t4) usages to prevent conflicts.

@alandtse alandtse merged commit 256a385 into community-shaders:dev Aug 29, 2025
15 checks passed
This was referenced May 9, 2026
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.

3 participants