Screen distortion (shrinking) - continuation

I was able to reproduce the issue in the Jira above in the Editor in latest on a 4070 Super, and have reached out to the team to see if this might be a related issue.

[Attachment Removed]

Sorry, haven’t had time to re-put my eyes on that issue but have you tried the method I described adding a shader permutation?

I haven’t been able to reproduce the issue after adding a shader permutation like you described above, so it definitely seems to have some impact on the issue, however even after I revert the shader permutation I cannot reproduce the issue even after clearing PSOs, recompiling shaders etc so a bit of a mystery there I’m still looking into. I’d be curious if anyone else experiencing this issue has a chance to try adding that permutation to see if it has an effect in their games.

[Attachment Removed]

Yes, in order to use the permutation you would modify SeparateTranslucency.cpp in 2 places like you have above, these are the changes I made:

class FComposeSeparateTranslucencyPS : public FGlobalShader
{
	DECLARE_GLOBAL_SHADER(FComposeSeparateTranslucencyPS);
	SHADER_USE_PARAMETER_STRUCT(FComposeSeparateTranslucencyPS, FGlobalShader);
 
	class FNearestDepthNeighborUpsampling : SHADER_PERMUTATION_BOOL("PERMUTATION_NEARESTDEPTHNEIGHBOR");
// After Motion Blur Permutation begin
	// Add a new permutation class for after motion blur
	class FAfterMotionBlur : SHADER_PERMUTATION_BOOL("PERMUTATION_AFTERMOTIONBLUR");
	using FPermutationDomain = TShaderPermutationDomain<FNearestDepthNeighborUpsampling,FAfterMotionBlur>;
// After Motion Blur Permutation end

and use it later on in the file in AddPass

	FComposeSeparateTranslucencyPS::FPermutationDomain PermutationVector;
	PermutationVector.Set<FComposeSeparateTranslucencyPS::FNearestDepthNeighborUpsampling>(DepthUpscampling);
// After Motion Blur Permutation Begin
	PermutationVector.Set<FComposeSeparateTranslucencyPS::FAfterMotionBlur>(bPostMotionBlur);
// After Motion Blur Permutation End
 
	TShaderMapRef<FComposeSeparateTranslucencyPS> PixelShader(View.ShaderMap, PermutationVector);
	FPixelShaderUtils::AddFullscreenPass(

Then in ComposeSeparateTranslucency.usf use the permutation to do something that has not effect on the final output

	// Final composition
	OutColor.rgb = SceneColorSample.rgb * SeparateTranslucencySample.a * SeparateModulationSample.rgb + SeparateTranslucencySample.rgb;
 
// After Motion Blur Permutation Begin
#if PERMUTATION_AFTERMOTIONBLUR 
	OutColor.rgb = max(0.0f, OutColor.rgb);
#endif
// After Motion Blur Permutation End

[Attachment Removed]

(Apparently, I wrote so much that it needs a second post.)

Finally, I’ve spent some time using the information from this thread to try to debug the issue.

While I haven’t figured out where it originates from, I will share what I learned, as it might help.

  • Turning off “Separate Translucency”, either via CVar or via ShowFlags, causes the flickering to stop, as well as stops it from starting.
  • I breakpointed several places throughout the Renderer code path, such as the suggested “FTranslucencyComposition::AddPass”, but couldn’t see any wrong UV-parameters.
    • Now this can be me, not knowing exactly what I’m looking for. The “OutputViewport.Rect” and “TranslucencyTexture.ViewRect” always match the current window resolution.
    • I tried breakpointing without the flickering being active (e.g., no scope on screen or TAA turned off), and it looks the same in terms of values as if the flickering was going on.
    • I also tried breakpointing during several different frames while the flickering is active. Both on normal frames and frames where the zoomed-in/out frame occurred, and I can’t see any strange value.
      • I must note that often I can’t properly inspect the properties, even with the Test build.
  • I tried using Pix, but as soon as I started the game with “-attachpix”, I couldn’t reproduce the issue anymore.
  • I took several GPUDumps, both on normal frames and broken frames, but I couldn’t see anything wrong during any of the earlier or later passes, including the translucency pass.
    • I will probably try this once more, however.

So far, that’s all I could figure out on my own. I believe, due to the “Separate Translucency” CVar/ShowFlag stopping the issue, that Alex is probably right about something going wrong within those split passes and how TAA makes use of them.

I haven’t been able to reproduce the issue after commenting out the `ViewFamily.AllowTranslucencyAfterDOF()` case inside `FDeferredShadingSceneRenderer::RenderTranslucency`.

So, in other words, always calling the single line of `RenderTranslucencyInner` with `ETranslucencyPass::TPT_AllTranslucency`, instead of the complex, split case.

I only tested this once, so I can’t be sure yet that this wasn’t a coincidence. However, since the CVar/ShowFlag basically controls the if/else, and “Separate Translucency” being turned off causes it to go into the else, it would be expected to have the same effect and stop the flickering.

/*
if (ViewFamily.AllowTranslucencyAfterDOF())
{
	RenderTranslucencyInner(Renderer, GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, OutSharedDepthTexture, InViews, ViewsToRender, SeparateTranslucencyDimensions, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyStandard, InstanceCullingManager, bStandardTranslucentCanRenderSeparate);
	if (ViewFamily.AllowStandardTranslucencySeparated() && bStandardTranslucentCanRenderSeparate)
	{
		RenderTranslucencyInner(Renderer, GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, OutSharedDepthTexture, InViews, ViewsToRender, SeparateTranslucencyDimensions, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyStandardModulate, InstanceCullingManager, bStandardTranslucentCanRenderSeparate);
	}
 
	if (GetHairStrandsComposition() == EHairStrandsCompositionType::AfterTranslucentBeforeTranslucentAfterDOF)
	{
		RenderHairComposition(GraphBuilder, InViews, SceneTextures.Color.Target, SceneTextures.Depth.Target, SceneTextures.Velocity, *OutTranslucencyResourceMap);
	}
	RenderTranslucencyInner(Renderer, GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, OutSharedDepthTexture, InViews, ViewsToRender, SeparateTranslucencyDimensions, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyAfterDOF, InstanceCullingManager, bStandardTranslucentCanRenderSeparate);
	RenderTranslucencyInner(Renderer, GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, OutSharedDepthTexture, InViews, ViewsToRender, SeparateTranslucencyDimensions, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyAfterDOFModulate, InstanceCullingManager, bStandardTranslucentCanRenderSeparate);
	RenderTranslucencyInner(Renderer, GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, OutSharedDepthTexture, InViews, ViewsToRender, SeparateTranslucencyDimensions, SceneColorCopyTexture, ETranslucencyPass::TPT_TranslucencyAfterMotionBlur, InstanceCullingManager, bStandardTranslucentCanRenderSeparate);
}
else // Otherwise render translucent primitives in a single bucket.
*/
{
	RenderTranslucencyInner(Renderer, GraphBuilder, SceneTextures, TranslucentLightingVolumeTextures, OutTranslucencyResourceMap, OutSharedDepthTexture, InViews, ViewsToRender, SeparateTranslucencyDimensions, SceneColorCopyTexture, ETranslucencyPass::TPT_AllTranslucency, InstanceCullingManager, bStandardTranslucentCanRenderSeparate);
}

Which means something must be going wrong in one or more of those additional `RenderTranslucencyInner` calls.

I tried to look at the `OutTranslucencyResourceMap` between the different calls, but couldn’t spot anything wrong.

I’m not sure if I was able to properly view the map, because I’m sure some of the entries are set, while I still see {0, 0} throughout those entries.

I think only the `TPT_TranslucencyAfterDOF` entry is readable and always has the correct resolution for its ViewRect.

Now, with this all out of the way, I would be interested in knowing what else I could do to debug this and hopefully find the cause.

I can share visuals and data, but only via private file links. I’m not sure if it would be worth much, however, because it wouldn’t be much different than what Dmytro already tried and shared.

Cheers,

Cedric

[Attachment Removed]

Hello there.

> The original post mentioned the issue was occurring in UE 5.4 and we’ve had several related fixes in UE 5.5 that might be worth back porting:

I read from other users that it started happening after upgrading to 5.6. If the OP experienced it in 5.4 already, then that’s good to know, and I missed that part.

I don’t want to hijack the thread, so I’ll try to only address parts that might help the OP as well.

Given that we are on 5.6 already, any of the listed 5.4 and 5.6 CLs are already part of our codebase and do not fix the issue for us.

Chances are high that if it’s the same underlying issue, those won’t fix the issue for the OP either.

The 5.8 fix is something I’ll give a go at. The description mentions that it’s more related to “r.SeparateTranslucencyScreenPercentage” values that aren’t equal to 100, as well as the Scale not being 1.0f, which isn’t the case for us, so I’m not too sure this will resolve anything, but I’ll get back to you with information on that.

Regarding the scope material, I had a look at it, or rather them, now. I’m not that good with the material stuff, but here is what I gathered so far:

The material that does not trigger the flicker has its “BlendMode” set to “Masked”, which makes sense.

The material that does trigger the flicker has its “BlendMode” set to “Translucent”, which isn’t surprising. Its “TranslucencyPass” is set to “After Motion Blur”.

I did find one material that has its “BlendMode” set to “Translucent” and its “TranslucencyPass” set to “After DOF”; however, that one isn’t used for any of the weapon scopes. I tried reproducing it while the mesh that uses that material was on the screen, but couldn’t trigger the flicker. That could be a false-positive. However, I was able to instantly make it flicker with the “After Motion Blur” material again, so chances are high that “After DOF” is not causing it.

> If you are able to provide a simple repro project in vanilla UE for us that would also help.

I doubt that’s gonna work out. It already only happens in very specific setups and under load. For now, it might be more feasible to discuss how one could debug this with the new information about the material.

Cheers.

[Attachment Removed]

Thanks!

Usually, OP (in that case, me) would receive an email notification about it. And it won’t happen until somebody from Epic responds to the question (or unless explicitly closed)

[Attachment Removed]

Ah, my bad. Better safe than sorry, I guess. Thanks for clarifying!

[Attachment Removed]

Yes, we can still reproduce it. Happy to try any additional ideas you’d like us to test if that helps

[Attachment Removed]

Hey Alex,

Got a message from QA that they are still able to reproduce the issue, but at a much lower rate.

[Attachment Removed]

Hello there,

I had a very busy few weeks, so I only now got the chance to look at the thread again.

I also tried this, but wasn’t able to get a proper test setup going to confirm it. When I checked the values of `bRenderInSeparateTranslucency` before and after the linked commit, I couldn’t see any difference, however. So my guess would also be that this doesn’t resolve the problem.

[Attachment Removed]

So, to ensure that this issue doesn’t go stale, I wanted to ask if this here could be a reasonable solution/fix for the issue.

It doesn’t seem like the issue is straightforward enough to spot. I’m not a graphics programmer, so my knowledge about all of this is very limited.

However, the code around the whole shader passes, etc., seems “simple” enough that an obvious issue, such as using the wrong matrix or similar, would be easy to spot.

The idea of the two passes using the same UShader object, due to being practically the same shader code, would be unusual enough to make sense here.

That’s something that not a lot of people would instantly think about.

Which brings me to a few questions:

  • Did anyone else try this solution? (We have not, I have not had the time to learn how to apply said fix.)
  • I would need to re-read the answer once more, but is there an option for getting a plug-and-play solution that we can apply? Maybe a PR/CL with the exact required changes on some fork of UE, that we can have a look at?
  • Does this whole idea make sense to [mention removed]​ and/or anyone else?

We have opted out of Separate Translucency, but I still want to make sure we follow up on this, in case we want to re-enable it.

Cheers,

Cedric

[Attachment Removed]

Hey [mention removed]​ ,

Wanted to check if there are any updates/thoughts on how the issue could be fixed.

Let me know if I can help you in any way.

[Attachment Removed]

Hi Alex,

Yes, it looks like it is the issue we were after all the time. Do you know if there are any plans to resolve the issue?

Apologies for the long reply.

[Attachment Removed]

Hello !

Sorry, haven’t had time to re-put my eyes on that issue but have you tried the method I described adding a shader permutation ?

I’m curious to know if that change helps on your end too ? On our end, I have not seen it (or heard of it) being repro-ed since I pushed this workaround.

JB

[Attachment Removed]

Hey, I’m still hovering this thread and keeping up with it.

However, due to how much dev time it costs us to investigate this problem, seemingly without getting anywhere, we’ve opted to disable separate translucency via r.SeparateTranslucency=0 for now.

I could try and repro it once more during my own time and try out the permutation fix, in case I can reproduce it. I would need to know exactly what I need to do for the permutation stuff. I usually don’t touch the shader files, so I’m not sure what this all involves. What I gathered so far from Jean-Baptiste’s post is that I would need to modify “ComposeSeparateTranslucency.usf” and add something to it that makes it unique while not actually changing the logic, is that correct?

So, for example, the suggested

#if PERMUTATION
	OutColor.rgb = max(0.0f, OutColor.rgb);
#endif // PERMUTATION

after

OutColor.rgb = SceneColorSample.rgb * SeparateTranslucencySample.a * SeparateModulationSample.rgb + SeparateTranslucencySample.rgb;

Is that all that would be required? Afterwards, probably have to re-cook content (aka create a new packaged build). Let me know if there is anything else required for the potential fix.

Cheers.

EDIT: The #if PERMUATION part seems to require something extra still, I guess. I looked at how PERMUTATION_NEARESTDEPTHNEIGHBOR works, and it seems to be defined like this:

class FNearestDepthNeighborUpsampling : SHADER_PERMUTATION_BOOL("PERMUTATION_NEARESTDEPTHNEIGHBOR");
using FPermutationDomain = TShaderPermutationDomain<FNearestDepthNeighborUpsampling>;
 
FComposeSeparateTranslucencyPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FComposeSeparateTranslucencyPS::FNearestDepthNeighborUpsampling>(DepthUpscampling);

Would I need to do something similar for the PERMUTATION one and adjust the code like this?

class FNearestDepthNeighborUpsampling : SHADER_PERMUTATION_BOOL("PERMUTATION_NEARESTDEPTHNEIGHBOR");
class FTranslucencyFlickerFix : SHADER_PERMUTATION_BOOL("PERMUTATION");
using FPermutationDomain = TShaderPermutationDomain<FNearestDepthNeighborUpsampling, FTranslucencyFlickerFix>;
 
FComposeSeparateTranslucencyPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FComposeSeparateTranslucencyPS::FNearestDepthNeighborUpsampling>(DepthUpscampling);
PermutationVector.Set<FComposeSeparateTranslucencyPS::FTranslucencyFlickerFix>(bPostMotionBlur);

[Attachment Removed]