Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Depth of Field NaNs make black flicker boxes because of the Bloom #786

Open
wowaaa opened this issue Mar 29, 2019 · 4 comments

Comments

Projects
None yet
3 participants
@wowaaa
Copy link

commented Mar 29, 2019

What happened?

When testing on android device I've noticed black flickering boxes around some objects. After some investigation and some help from frame-debugger it seems like the DoF surface on some angles or edge intersections with the model polygons creates small black areas (NaN's or Inf's). This causes Bloom Pyramid to freak out and just render big black box around those areas. For me it only reproduces on the device and not seen issues in editor yet.
I've seen the related issue but I believe that it is not platform specific and that was V1.
Tested on SamsungS8+(Exynos)
Here are the images from frame-debugger
1_beforePostEffects
2_DoF_firstStep
3_afterDoF
4_bloomPyramidStart
5_bloomPyromidEnd
6_afterPostEffects

Post-processing stack version (v1, v2)?

V2 2.1.3, 2.1.5(with reverted change related to colorFormat)

Unity version, operating system, target platform (standalone windows, mac, iOS, PS4...)?

2018.3.6f1, Windows, Android

@wowaaa

This comment has been minimized.

Copy link
Author

commented Mar 29, 2019

RenderDoc helped after all.
So the problem is inside DepthOfField shader!
There are no NaN pixels before it. And even the same RenderDoc state works flawlessly on different hardware. But the issue is there!
And with a bit of diving into the shader file and editing inside RenderDoc the issue was found on this line:
u_xlat16_4 = max(u_xlat16_4, 9.99999975e-06);
Because the next line is the division to this variable.
Now notice how that translates into the real shader (DepthOfField.hlsl):

// Weighted average of the color samples
half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3;
avg /= max(w0 + w1 + w2 + w3, 1e-5);

And the issue here is the precision, because we divide in half format by 1e-5 value. As far as I remember we have different precision on different hardware and Unity docs shows that half is about 3 decimals precision and about 60000 max value for their reference. So we have overflow after division and NaN as result on some hardware.
For me change towards 1e-4 fixed produced NaN artifacts.
P.S. There is also this line almost on top of the shader half coc = (depth - _Distance) * _LensCoeff / max(depth, 1e-5); which also uses 1e-5 on half variable. So for myself I've also quick-fixed that place.
Please review shader file and fix the precision or these constants!

@AtomicJoe1

This comment has been minimized.

Copy link

commented Apr 1, 2019

I have the same problem on Android Vulkan (both editor and build)
Changing the variables from half to float or changing 1e-5 to 1e-4 doesn't fix it however.
Changing line 164 in DepthOfField.cs to force a true HDR buffer fixes it though:
var colorFormat = RenderTextureFormat.DefaultHDR;// context.sourceFormat;

@wowaaa

This comment has been minimized.

Copy link
Author

commented Apr 1, 2019

The true HDR buffer fix is a different issue though. Just as I've described without that fix, both latest versions(2.1.4 and 2.1.5) are completely broken on many mobile platforms and even in the editor while targeting them.
But this specific problem is hardware dependent and without a doubt caused by mismatch variable types and those small constants causing overflow on some devices.

@KichangKim

This comment has been minimized.

Copy link

commented Apr 10, 2019

RenderDoc helped after all.
So the problem is inside DepthOfField shader!
There are no NaN pixels before it. And even the same RenderDoc state works flawlessly on different hardware. But the issue is there!
And with a bit of diving into the shader file and editing inside RenderDoc the issue was found on this line:
u_xlat16_4 = max(u_xlat16_4, 9.99999975e-06);
Because the next line is the division to this variable.
Now notice how that translates into the real shader (DepthOfField.hlsl):
// Weighted average of the color samples
half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3;
avg /= max(w0 + w1 + w2 + w3, 1e-5);

And the issue here is the precision, because we divide in half format by 1e-5 value. As far as I remember we have different precision on different hardware and Unity docs shows that half is about 3 decimals precision and about 60000 max value for their reference. So we have overflow after division and NaN as result on some hardware.
For me change towards 1e-4 fixed produced NaN artifacts.
P.S. There is also this line almost on top of the shader half coc = (depth - _Distance) * _LensCoeff / max(depth, 1e-5); which also uses 1e-5 on half variable. So for myself I've also quick-fixed that place.
Please review shader file and fix the precision or these constants!

Thanks, this hotfix does perfectly work for my project! I hope that Unity applies this fix officialy as fast as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.