diff --git a/package/Shaders/ISTemporalAA.hlsl b/package/Shaders/ISTemporalAA.hlsl index 659d4ccc4a..ab52a7722f 100644 --- a/package/Shaders/ISTemporalAA.hlsl +++ b/package/Shaders/ISTemporalAA.hlsl @@ -2,6 +2,7 @@ #include "Common/DisplayMapping.hlsli" #include "Common/DummyVSTexCoord.hlsl" #include "Common/FrameBuffer.hlsli" +#include "Common/VR.hlsli" typedef VS_OUTPUT PS_INPUT; @@ -264,9 +265,17 @@ PS_OUTPUT main(PS_INPUT input) // --- motion vector and history sample --- history.xy = drMax; motionReject.xy = velocityTex.Sample(velocitySampler, ClampScreenUV(motionReject.xy, history.xy)).xy; +# ifdef VR + // Eyes share one RT in VR; reproject within the current eye (mono-space velocity, per-eye + // clamp) so a pixel near the x=0.5 seam never samples the other eye's history. OOB feeds reject. + bool prevUVOutOfBounds; + float2 prevUV = Stereo::ApplyVelocityToUV(texCoord.xy, motionReject.xy, prevUVOutOfBounds); + tapMin.xy = FrameBuffer::GetPreviousDynamicResolutionAdjustedScreenPosition(prevUV); +# else motionReject.zw = texCoord.xy + motionReject.xy; - motionReject.x = sqrt(dot(motionReject.xy, motionReject.xy)); tapMin.xy = ClampHistoryUV(motionReject.zw); +# endif + motionReject.x = sqrt(dot(motionReject.xy, motionReject.xy)); history.xyw = historyTex.Sample(historySampler, tapMin.xy).xyz; # ifdef HDR_OUTPUT // history.x is stored as game-gamma luma (see EncodeFeedbackLuma on write). @@ -418,12 +427,17 @@ PS_OUTPUT main(PS_INPUT input) corner.xyz = history.yyy * corner.xyz + tapMin.xyz; // --- disocclusion / mask rejection --- - // motionReject.zw still holds reprojected UV from motion pass; motionReject.x = motion length + // motionReject.x = motion length (motionReject.zw held the reprojected UV on the SE path). +# ifdef VR + // VR resolves out-of-bounds per-eye in mono space; the SE stereo-space test misses the seam. + motionReject.z = prevUVOutOfBounds ? 1 : 0; +# else sampleUV.w = min(motionReject.z, motionReject.w); motionReject.zw = cmp(motionReject.zw >= float2(1, 1)); sampleUV.w = cmp(0 >= sampleUV.w); motionReject.z = (int)motionReject.z | (int)sampleUV.w; motionReject.z = (int)motionReject.w | (int)motionReject.z; +# endif history.yz = maskTex.Sample(maskSampler, sampleUV.xy).xy; motionReject.w = AlphaCoverageMask(sampleUV.xy); sampleUV.x = cmp(ThresholdParams.w < history.z); @@ -513,11 +527,8 @@ PS_OUTPUT main(PS_INPUT input) # else feedbackOut.x = saturate(sampleUV.x * motionReject.z); # endif -# if defined(VR) - colorOut.w = motionReject.x ? 1 : 0; -# else + // Vanilla writes opaque alpha unconditionally on both SE and VR (decompile o0.w = 1). colorOut.w = 1; -# endif feedbackOut.w = 1; # ifdef HDR_OUTPUT