Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ namespace ExtendedMaterials
float2 GetParallaxCoords(float distance, float2 coords, float mipLevel, float3 viewDir, float3x3 tbn, float noise, Texture2D<float4> tex, SamplerState texSampler, uint channel, DisplacementParams params, out float pixelOffset)
#endif
{
pixelOffset = 0.5;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
float3 viewDirTS = normalize(mul(tbn, viewDir));
#if defined(LANDSCAPE)
viewDirTS.xy /= viewDirTS.z * 0.7 + 0.3 + params[0].FlattenAmount; // Fix for objects at extreme viewing angles
Expand Down Expand Up @@ -496,7 +497,7 @@ namespace ExtendedMaterials
#endif
nearBlendToFar *= nearBlendToFar;
float offset = (1.0 - parallaxAmount) * -maxHeight + minHeight;
pixelOffset = lerp(parallaxAmount * scale, 0, nearBlendToFar);
pixelOffset = saturate(lerp(parallaxAmount, 0.5, nearBlendToFar));
return lerp(viewDirTS.xy * offset + coords.xy, coords, nearBlendToFar);
}

Expand All @@ -509,7 +510,7 @@ namespace ExtendedMaterials
weights[5] = input.LandBlendWeights2.y;
#endif

pixelOffset = 0;
pixelOffset = 0.5;
return coords;
}

Expand Down
18 changes: 18 additions & 0 deletions features/Screen Space GI/Shaders/ScreenSpaceGI/blur.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ RWTexture2D<unorm float> outAccumFrames : register(u0);
RWTexture2D<float4> outIlY : register(u1);
RWTexture2D<float2> outIlCoCg : register(u2);

#if defined(VR_STEREO_OPT)
Texture2D<uint> StereoOptModeTexture : register(t16);
#endif

// samples = 8, min distance = 0.5, average samples on radius = 2
static const float3 g_Poisson8[8] = {
float3(-0.4706069, -0.4427112, +0.6461146),
Expand Down Expand Up @@ -88,6 +92,20 @@ float2x2 getRotationMatrix(float noise)
// Early exit if dispatch thread is outside frame bounds
if (any(dtid >= uint2(OUT_FRAME_DIM)))
return;

#if defined(VR_STEREO_OPT)
{
float2 uv = (dtid + .5) * RCP_OUT_FRAME_DIM;
uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(uv);
if (eyeIndex == 1) {
uint2 fullResPx = uint2(uv * FrameDim);
uint mode = StereoOptModeTexture[fullResPx];
if (mode == 1 || mode == 2)
return;
}
}
#endif

const float2 frameScale = FrameDim * RcpTexDim;

float radius = BlurRadius;
Expand Down
13 changes: 13 additions & 0 deletions features/Screen Space GI/Shaders/ScreenSpaceGI/gi.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Texture2D<float4> srcPrevY : register(t6); // maybe half-res
Texture2D<float2> srcPrevCoCg : register(t7); // maybe half-res
Texture2D<float4> srcPrevGISpecular : register(t8); // maybe half-res

#if defined(VR_STEREO_OPT)
Texture2D<uint> StereoOptModeTexture : register(t16);
#endif

RWTexture2D<unorm float> outAo : register(u0);
RWTexture2D<float4> outY : register(u1);
RWTexture2D<float2> outCoCg : register(u2);
Expand Down Expand Up @@ -343,6 +347,15 @@ void CalculateGI(
float2 uv = (pxCoord + .5) * RCP_OUT_FRAME_DIM;
uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(uv);

#if defined(VR_STEREO_OPT)
if (eyeIndex == 1) {
uint2 fullResPx = uint2(uv * FrameDim);
uint mode = StereoOptModeTexture[fullResPx];
if (mode == 1 || mode == 2)
return;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
#endif

float viewspaceZ = READ_DEPTH(srcWorkingDepth, pxCoord);

float2 normalSample = FULLRES_LOAD(srcNormalRoughness, pxCoord, uv * frameScale, samplerLinearClamp).xy;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "Common/Color.hlsli"
#include "Common/FrameBuffer.hlsli"
#include "Common/GBuffer.hlsli"
#include "Common/Math.hlsli"
#include "Common/VR.hlsli"
#include "ScreenSpaceGI/common.hlsli"

Expand All @@ -16,6 +15,10 @@ Texture2D<half4> srcPrevIlY : register(t7); // maybe half-res
Texture2D<half2> srcPrevIlCoCg : register(t8); // maybe half-res
Texture2D<half4> srcPrevGISpecular : register(t9); // maybe half-res

#if defined(VR_STEREO_OPT)
Texture2D<uint> StereoOptModeTexture : register(t16);
#endif

RWTexture2D<float3> outRadianceDisocc : register(u0);
RWTexture2D<unorm float> outAccumFrames : register(u1);
RWTexture2D<float> outRemappedAo : register(u2);
Expand Down Expand Up @@ -76,6 +79,16 @@ void readHistory(

const float2 uv = (pixCoord + .5) * RCP_OUT_FRAME_DIM;
const uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(uv);

#if defined(VR_STEREO_OPT)
if (eyeIndex == 1) {
uint2 fullResPx = uint2(uv * FrameDim);
uint mode = StereoOptModeTexture[fullResPx];
if (mode == 1 || mode == 2)
return;
}
Comment on lines +83 to +89
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reset the temporal outputs before taking this Eye 1 fast path.

Unlike the curr_depth < FP_Z branch below, this path returns before touching any UAVs. That leaves stale outAccumFrames/outRemapped* data behind for culled pixels, so a pixel that later stops being culled can pick up old history instead of starting clean.

💡 Proposed fix
 `#if` defined(VR_STEREO_OPT)
 	if (eyeIndex == 1) {
 		uint2 fullResPx = uint2(uv * FrameDim);
 		uint mode = StereoOptModeTexture[fullResPx];
-		if (mode == 1 || mode == 2)
-			return;
+		if (mode == 1 || mode == 2) {
+#ifdef GI
+			outRadianceDisocc[pixCoord] = 0;
+#endif
+#ifdef TEMPORAL_DENOISER
+			outAccumFrames[pixCoord] = 1.0 / 255.0;
+			outRemappedAo[pixCoord] = 0;
+			outRemappedIlY[pixCoord] = 0;
+			outRemappedIlCoCg[pixCoord] = 0;
+			outRemappedPrevGISpecular[pixCoord] = 0;
+#endif
+			return;
+		}
 	}
 `#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@features/Screen` Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl around
lines 83 - 89, The VR_STEREO_OPT fast-path for eyeIndex==1 returns early for
modes 1 and 2 without writing UAVs, leaving stale temporal outputs; before the
early return in that block (the if (mode == 1 || mode == 2) branch) write/reset
the temporal outputs (clear outAccumFrames and the outRemapped* UAVs — e.g.
outRemappedDepth/outRemappedColor or their actual variable names used in this
shader) to a neutral/zero state so culled pixels do not retain history, then
return. Ensure the reset uses the same output formats/types as the normal code
paths so layout remains consistent.

#endif

const float2 screen_pos = Stereo::ConvertFromStereoUV(uv, eyeIndex);

float2 prev_screen_pos = screen_pos;
Expand Down Expand Up @@ -127,7 +140,7 @@ void readHistory(
prev_ao, prev_y, prev_co_cg, prev_ambient, accum_frames, prev_gi_specular, wsum);

if (wsum > 1e-2) {
float rcpWsum = rcp(wsum + EPSILON_WEIGHT_SUM);
float rcpWsum = rcp(wsum + 1e-10);
# ifdef TEMPORAL_DENOISER
prev_ao *= rcpWsum;
prev_y *= rcpWsum;
Expand Down
15 changes: 15 additions & 0 deletions features/Screen Space GI/Shaders/ScreenSpaceGI/stereoSync.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Texture2D<float> srcAo : register(t1);
Texture2D<float4> srcIlY : register(t2);
Texture2D<float2> srcIlCoCg : register(t3);

# if defined(VR_STEREO_OPT)
Texture2D<uint> StereoOptModeTexture : register(t16);
# endif

RWTexture2D<float> outAo : register(u0);
RWTexture2D<float4> outIlY : register(u1);
RWTexture2D<float2> outIlCoCg : register(u2);
Expand Down Expand Up @@ -59,6 +63,17 @@ float4 SampleCrossDepths(float2 centerUV, float2 step, float2 texScale, uint eye

uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(uv);

# if defined(VR_STEREO_OPT)
if (eyeIndex == 1) {
uint2 fullResPx = uint2(uv * FrameDim);
uint mode = StereoOptModeTexture[fullResPx];
if (mode == 1 || mode == 2) {
Passthrough(dtid);
return;
}
}
# endif

// SSGI working depth is linear view-space Z.
// 0.0 = mask (outside lens area). FP_Z = first-person hands threshold (~18.0).
float depth = srcDepth.SampleLevel(samplerPointClamp, uv * frameScale, RES_MIP);
Expand Down
18 changes: 18 additions & 0 deletions features/Screen Space GI/Shaders/ScreenSpaceGI/upsample.cs.hlsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// depth-aware upsampling: https://gist.github.com/pixelmager/a4364ea18305ed5ca707d89ddc5f8743

#include "Common/FastMath.hlsli"
#include "Common/VR.hlsli"
#include "ScreenSpaceGI/common.hlsli"

Texture2D<half> srcDepth : register(t0);
Expand All @@ -9,6 +10,10 @@ Texture2D<half4> srcIlY : register(t2); // half-res
Texture2D<half2> srcIlCoCg : register(t3); // half-res
Texture2D<half4> srcGiSpecular : register(t4); // half-res

#if defined(VR_STEREO_OPT)
Texture2D<uint> StereoOptModeTexture : register(t16);
#endif

RWTexture2D<half> outAo : register(u0);
RWTexture2D<half4> outIlY : register(u1);
RWTexture2D<half2> outIlCoCg : register(u2);
Expand All @@ -23,6 +28,19 @@ RWTexture2D<half4> outGiSpecular : register(u3);
// Early exit if dispatch thread is outside frame bounds
if (any(dtid >= uint2(FrameDim)))
return;

#if defined(VR_STEREO_OPT)
{
float2 uv = (dtid + .5) * RcpFrameDim;
uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(uv);
if (eyeIndex == 1) {
uint mode = StereoOptModeTexture[dtid];
if (mode == 1 || mode == 2)
return;
}
}
#endif

#ifdef HALF_RES
int2 px00 = (dtid >> 1) + (dtid & 1) - 1;
#else // QUARTER_RES
Expand Down
4 changes: 2 additions & 2 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace SharedData
bool InInterior; // If the area lacks a directional shadow light e.g. the sun or moon
bool InMapMenu; // If the world/local map is open (note that the renderer is still deferred here)
bool HideSky; // HideSky flag in WorldSpace, e.g. Blackreach
float MipBias; // Offset to mip level for TAA sharpness#
float MipBias; // Offset to mip level for TAA sharpness
float pad0;
float4 AmbientSHR;
float4 AmbientSHG;
Expand Down Expand Up @@ -52,7 +52,7 @@ namespace SharedData
bool EnableShadows;
bool ExtendShadows;
bool EnableParallaxWarpingFix;
float1 pad0;
bool pad0;
};

struct CubemapCreatorSettings
Expand Down
1 change: 1 addition & 0 deletions package/Shaders/Common/VR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ cbuffer VRValues : register(b13)
float2 EyeOffsetScale : packoffset(c0.z);
float4 EyeClipEdge[2] : packoffset(c1);
}

#endif

namespace Stereo
Expand Down
14 changes: 14 additions & 0 deletions package/Shaders/DeferredCompositeCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ RWTexture2D<float4> NormalTAAMaskSpecularMaskRW : register(u1);
RWTexture2D<float2> MotionVectorsRW : register(u2);
Texture2D<float> DepthTexture : register(t4);

#if defined(VR_STEREO_OPT)
Texture2D<uint> StereoOptModeTexture : register(t16);
#endif

#if defined(DYNAMIC_CUBEMAPS)
Texture2D<float3> ReflectanceTexture : register(t5);
TextureCube<float3> EnvTexture : register(t6);
Expand Down Expand Up @@ -92,6 +96,16 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, inout float ao, out float3 il,
uv *= FrameBuffer::DynamicResolutionParams2.xy; // adjust for dynamic res

uint eyeIndex = Stereo::GetEyeIndexFromTexCoord(uv);

#if defined(VR_STEREO_OPT)
if (eyeIndex == 1) {
uint mode = StereoOptModeTexture[uint2(dispatchID.xy)] & 0x0F;
if (mode == 2 || mode == 1) { // MODE_MAIN or MODE_EDGE — stencil-culled, reprojected by StereoBlend
return;
}
}
#endif
Comment thread
coderabbitai[bot] marked this conversation as resolved.

uv = Stereo::ConvertFromStereoUV(uv, eyeIndex);

float3 normalGlossiness = NormalRoughnessTexture[dispatchID.xy];
Expand Down
10 changes: 9 additions & 1 deletion package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3166,7 +3166,15 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
}
# endif

psout.Reflectance = float4(indirectLobeWeights.specular, psout.Diffuse.w);
# if defined(VR) && (defined(EMAT) || defined(TRUE_PBR)) && (defined(PARALLAX) || defined(LANDSCAPE) || defined(TRUE_PBR))
// VR: store POM parallax amount for stereo reprojection depth correction.
// Read by StereoBlendCS to adjust Eye 1 (right eye) reprojection depth
// at POM-displaced surfaces. Not consumed on flat (SE/AE).
psout.Reflectance = float4(indirectLobeWeights.specular,
(pixelOffset > 0.0) ? saturate(pixelOffset) : 0.0);
# else
psout.Reflectance = float4(indirectLobeWeights.specular, 0.0);
# endif
psout.NormalGlossiness = float4(GBuffer::EncodeNormal(screenSpaceNormal), saturate(1.0 - material.Roughness), psout.Diffuse.w);

# if defined(SNOW)
Expand Down
1 change: 0 additions & 1 deletion package/Shaders/RunGrass.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,6 @@ PS_OUTPUT main(PS_INPUT input)

# if defined(RENDER_DEPTH)
float diffuseAlpha = input.VertexColor.w * baseColor.w;

if ((diffuseAlpha - AlphaTestRefRS) < 0) {
discard;
}
Expand Down
Loading
Loading