fix(deferred): restore UAV bind on vanilla normals targets#2271
Conversation
PR community-shaders#2178 removed the CreateRenderTarget_Normals and CreateRenderTarget_NormalsSwap hooks because the PS-variant deferred composite path from PR community-shaders#2150 didn't need UAV access on the vanilla kNORMAL_TAAMASK_SSRMASK target. PR community-shaders#2150 was later reverted, restoring the CS path, but the hook removal stayed. DeferredCompositeCS still binds normals.UAV as UAV1 and writes EncodeNormalVanilla(normalVS) through it so the post-pass vanilla SSAO chain (ISSAORawAO -> ISSAOComposite) sees current-frame normals. Without the hooks, the target's UAV is null, the CS write is silently dropped, and vanilla SSAO samples uninitialized data -- producing hard wedge-shaped shadow artifacts visible to users without Screen Space GI installed (SSGI was masking the issue by force-disabling vanilla SSAO every frame). Restoring the two hooks brings the vanilla SSAO chain back in line with v1.4.11 behavior. The other parts of community-shaders#2178 already went away with the community-shaders#2150 revert, so this is the only piece left to undo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughTwo new render-target hook thunks for normals creation ( ChangesNormals Render-Target Hooks
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
No actionable suggestions for changed features. |
|
✅ A pre-release build is available for this PR: |
Summary
CreateRenderTarget_NormalsandCreateRenderTarget_NormalsSwaphooks removed in fix: deferredcomposite texture rubberbanding #2178.Root cause
DeferredCompositeCS.hlsl:333writes vanilla-encoded normals through UAV1 (normals.UAVinDeferred::DeferredPasses) so the post-pass vanilla SSAO chain (ISSAORawAO->ISSAOComposite) sees current-frame normals. Those hook structs addedD3D11_BIND_UNORDERED_ACCESStokNORMAL_TAAMASK_SSRMASKand its swap, which is what makes that UAV non-null.#2178 removed them because the PS-variant deferred composite from #2150 didn't need that UAV. #2150 was later reverted (
1e3b6faa7), restoring the CS path, but the hook removal stayed. Result: UAV1 is null, the CS write is silently dropped, vanilla SSAO samples uninitialized data, and produces hard wedge-shaped shadow artifacts.The bug only surfaced for users without SSGI installed. The Screen Space GI feature force-disables vanilla SSAO every frame at
src/Features/ScreenSpaceGI.cpp:710-712regardless of its own enabled state, so any rig with SSGI installed never saw the broken output.Why just restore the hooks instead of
git revert fcc5921ddThe other two hunks of #2178 (
DeferredCompositePS.hlslsignature fixes and aDeferred.cppSetupRenderTarget(normalRoughnessRT, ...)removal) were tied to #2150's PS path. Both went away with the #2150 revert --DeferredCompositePS.hlslno longer exists andnormalRoughnessRTisn't a thing in HEAD. The hook removal insrc/Hooks.cppis the only surviving piece, so a targeted re-add is functionally identical to a revert and reads more clearly in the log.Diagnosis evidence
RenderDoc capture of an affected frame (event IDs from the bug capture):
DeferredCompositeCSdispatch at EID 47449:UAVs = [Main(63), NULL, MotionVectors(92)]— UAV1 isResourceId(0).kNORMAL_TAAMASK_SSRMASK(resource 82) usage timeline:Clear@41356, PS_Resource@47484, PS_Resource@47821, PS_Resource@47910— never written, only sampled.ISSAORawAOat EID 47821 reads resource 82 as t1 and produces wedge-banded AO into the SAO chain, ending up inSAOTex(resource 154) consumed byISSAOCompositeat EID 47910.Test plan
ALLpreset, deploy to a Skyrim install that does not have Screen Space GI installed.DeferredCompositeCSdispatch now shows a non-null UAV1 bound tokNORMAL_TAAMASK_SSRMASK, and that the target is written each frame (not just cleared).EnableVanillaSSAO=false) still look identical -- SSGI's runtime patch zeroes the vanilla SSAO enable byte before this UAV is ever sampled, so it should be unaffected.EnableVanillaSSAO=truenow produce a correct vanilla SSAO contribution rather than the previous artifact.0x5B0/0x5C3).🤖 Generated with Claude Code
Summary by CodeRabbit