crest
crest copied to clipboard
SRP+URP iOS: Ocean rendering broken on Metal on devices with chip lower than A13
Describe the bug The Crest URP Main sample scene doesn't render correctly on an iPad Pro. A certain area in the center of the Ocean (the smallest tile) has a solid blue-ish color.
Screenshots / video
Here you can see a video of the bug as well.
Log
2020-07-01 16:34:20.310944+0300 PlainCrest[1183:339368] Built from '2019.4/release' branch, Version '2019.4.1f1 (e6c045e14e4e)', Build type 'Release', Scripting Backend 'il2cpp'
-> applicationDidFinishLaunching()
-> applicationDidBecomeActive()
[Subsystems] Discovering subsystems at path /private/var/containers/Bundle/Application/EC3546DB-5CC5-4A92-BFDB-D17746ACA384/PlainCrest.app/Data/UnitySubsystems
GfxDevice: creating device client; threaded=1
Initializing Metal device caps: Apple A12Z GPU
Initialize engine version: 2019.4.1f1 (e6c045e14e4e)
2020-07-01 16:34:23.836258+0300 PlainCrest[1183:340506] fopen failed for data file: errno = 2 (No such file or directory)
2020-07-01 16:34:23.836310+0300 PlainCrest[1183:340506] Errors found! Invalidating cache...
2020-07-01 16:34:24.472163+0300 PlainCrest[1183:340506] fopen failed for data file: errno = 2 (No such file or directory)
2020-07-01 16:34:24.472223+0300 PlainCrest[1183:340506] Errors found! Invalidating cache...
2020-07-01 16:34:24.578211+0300 PlainCrest[1183:339368] Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x100f8f990>.
UnloadTime: 1.305125 ms
Can't add component because class 'MeshCollider' doesn't exist!
Crest.ShapeGerstnerBatched:InitBatches()
[ line 956]
(Filename: Line: 956)
Can't add component because class 'MeshCollider' doesn't exist!
Crest.OceanDepthCache:InitCacheQuad()
Crest.OceanDepthCache:InitObjects()
Crest.OceanDepthCache:BeginCameraRendering(ScriptableRenderContext, Camera)
System.Action`2:Invoke(T1, T2)
UnityEngine.Rendering.Universal.UniversalRenderPipeline:RenderCameraStack(ScriptableRenderContext, Camera)
UnityEngine.Rendering.Universal.UniversalRenderPipeline:Render(ScriptableRenderContext, Camera[])
UnityEngine.Rendering.RenderPipelineManager:DoRenderLoop_Internal(RenderPipelineAsset, IntPtr)
[ line 956]
(Filename: Line: 956)
Versions Crest 4.3 URP from Asset Store Unity 2019.4.1f1 (LTS) Unity URP 7.3.1
To Reproduce
- Create a new project in this version of Unity
- Switch target platform to iOS
- Download Crest URP from the Asset Store
- Perform the Crest-necessary setup steps like enabling Opaque and Depth texture, add Terrain layer, etc.
- Build the Main sample scene for iOS
- Test on an iPad Pro (2020)
Platform
- iOS Build
- Xcode 11 or Xcode 12 Beta
Hardware Reproduced on:
- iPad Pro 12.9'' (2020 with LiDAR), A12Z Bionic chip with 64-bit architecture, https://www.apple.com/ipad-pro/specs/
- iPad Pro 11'' (2020 with LiDAR), A12Z Bionic chip with 64-bit architecture
Additional context
This is not reproducible on iPhone 11 Pro (2019) which has a A13 chip
https://www.apple.com/iphone-11-pro/specs/
On iPhone 11 Pro the same logs Can't add component because class 'MeshCollider' doesn't exist!
shown above appear, but there is no issue with the Ocean rendering.
Also not reproducible on MacOS in the Editor.
Here you can see a table of the Metal features that the A12Z and A13 chips support. They overlap for almost all features, but have some small differences. Maybe here we can find the one that could be causing this issue?
We observed that this solid color looks a lot like the Foam color.
So I disabled Foam generation on the Ocean and disabled Foam on the material, however this had no impact on the bug.
Could you please try disabling features/toggles on the ocean material? When I see weird rendering artifacts I disable shader features one at a time until it goes away and this often narrows down the issue to one area of the code.
Hi @huwb, I did try that but I'm afraid it didn't yield anything useful.
This is with Foam and a few other things disabled
And this is with pretty much everything that I could disable disabled. All checkboxes in the material off, all features in the Ocean gameObject, etc.
Thanks noted
Could you try user the material called OceanFramework ? It's using a different version of our ocean shader
Two other tests I can think of...
It kind if looks like the specular reflections. Setting specular to zero or changing the skybox might change the colour and narrow it down.
Also, can you try changing the LOD count on the ocean renderer? Reducing it might show something interesting.
This is the result using the Ocean/Framework
shader. Still the same issue. Will attempt @daleeidd 's suggestions too.
Setting specular to zero or changing the skybox might change the colour and narrow it down. Also, can you try changing the LOD count on the ocean renderer? Reducing it might show something interesting.
On the same Framework
material, I set Specular to 0 and updated the Skybox and some other stuff to the values shown here:
Which looks like this in the Editor:
But like this on the iPad:
I then switched to the default Ocean shader (default underwater material of the scene), set Specular to 0 and dropped LODs to 2 and this is the result:
As you can see in this video, the color is affected by the angle of view, as it should be. It's the transparency that seems to be the issue.
I was hoping to use Crest SRP for this... But no. The issue is there too (updated title to reflect this).
Actually maybe the shoreline can offer some hints into the issue? Zoom in to see how the shading changes as the water meets the terrain.
Screenshot from Crest SRP on Unity 2019.4.1f1 on default SRP, Sample Main scene:
Confirmed that this is an issue also on iPad Pro 2020 11'', as well as iPad Pro 2020 12.9''. I will also test on more iPads. I will update the Hardware list above with findings.
I am stumped. Huw might have further recommendations. I recommend opening an issue with Unity.
I currently have an issue that I experience on my 2014 MacBook Pro (was fine on 2018 Mac Mini) where there are issues with boolean values in the shader. If I change the following in the OceanEmission function:
if (!underwater)
{
// do A
}
else
{
// do B
}
if (underwater)
{
// do B
}
else
{
// do A
}
It "solves" the problem (I also have to remove the _ForceUnderwater from the underwater check to solve another problem). But as you can see they are functionally equivalent. I believe there are issues with the compiler on certain Metal API versions. So I am wondering if this might be one of those cases where the compiler is broken.
But I think bringing this to Unity's attention is the way to go (I have already submitted a bug report for my issue).
Hmm scary. Let me know if you think there's any particular boolean that could be causing the above that I could try flipping around.
Speaking of compilers, I updated the issue to mention this is issue is there when building both from Xcode 11 and Xcode 12 Beta.
Hmm... there is another test you can try. If you look at the source for the OceanRenderer component, there is a _followViewpoint attribute. If you set it to false, then the tile system won't follow the camera in play mode. It might reveal something.
Let me know if you think there's any particular boolean that could be causing the above that I could try flipping around.
It doesn't seem like an issue with a boolean since it would be applied across the entire ocean surface. So I will retract the statement that this might be a compiler issue, but rather it might be something wrong with the API. Have you tried using Xcode's frame debugger?
No, I will look into the Frame Debugger.
In the meantime I tested the Crest SRP Sample Scene on a few more devices and actually this is a more common issue it seems so you may be able to reproduce it. It can be reproduced on:
- iPhone X iOS 13.4.1
- iPad Air (3 years old)
- iPad Pro 12.9 (2018)
- iPad Pro 11 and 12.9 LiDAR (2020) iOS 13.x
It can NOT be reproduced on
- iPhone 11 Pro iOS 13.4.1
Also reproduced with Unity 2019.3.13 along with the initially reported 2019.4.1 LTS
Can you grab a GPU capture? If so you could compare the pipeline state when it draws LOD0 vs LOD1 tiles. Maybe the depth buffer is not bound, or maybe some other parameters are different.
Additionally it might be worth commenting out some things for the ocean shader to see if you can find an area of the code that causes it.
Suggestions:
- https://github.com/crest-ocean/crest/blob/master/crest/Assets/Crest/Crest/Shaders/Ocean.shader#L297
- Maybe all lines in Ocean.shader from 315-382 to stop it sampling ocean data.
One more thought - maybe its something specific to the geometry used closest to the camera. You could replace PatchType.Interior
with leadSideType
here:
https://github.com/crest-ocean/crest/blob/master/crest/Assets/Crest/Crest/Scripts/OceanBuilder.cs#L423
Apologies again that we dont have better support for mobile!
@doukasd #815 looks very similar to this issue. It could be that the precision fix in that PR could be the solution, or another precision issue elsewhere. Are you still experiencing this problem?
Indeed!