googlevr / gvr-unity-sdk

Google VR SDK for Unity
http://developers.google.com/vr/unity/
Other
2.71k stars 1.09k forks source link

Cardboard (and hybrid 2D+Daydream) apps crash on S8 when screen resolution is not WQHD+ (Switching Between VR.enabled cause crash) #671

Closed VadimTikhonyuk closed 7 years ago

VadimTikhonyuk commented 7 years ago

Hi, everyone

I had issue with switching between 2D and VR Mode This method cause crash

StartCoroutine(LoadDevice("cardboard"));

IEnumerator LoadDevice(string newDevice)
{
    yield return null;
    VRSettings.LoadDeviceByName(newDevice);
    yield return null;
    VRSettings.enabled = true;
}

` LOGCAT libEGL : eglCreateWindowSurface: native_window_api_connect (win=0xc687d808) failed (0xffffffed) (already connected to another API?) libEGL : eglCreateWindowSurface:484 error 3003 (EGL_BAD_ALLOC) Unity : [EGL] Failed to create window surface: EGL_BAD_ALLOC: EGL failed to allocate resources for the requested operation. Unity : Unity : (Filename: ./Runtime/GfxDevice/egl/WindowContextEGL.cpp Line: 141) Unity : libEGL : call to OpenGL ES API with no current context (logged once per thread)

Im using Unity 5.6.0f3 and Samsung S8

I see many similar problem with this method but anyone find solution?

VadimTikhonyuk commented 7 years ago

Update, On Unity 2017.1.0f3 same issue

VadimTikhonyuk commented 7 years ago

Update, On my old Fly IQ4516 everething works fine. I think this crash happens on Samsung S8 after android update, which I got few days ago, after this update I didnt test VR mode in my app.

tedruxpin commented 7 years ago

Hi VadimTikhonyuk, can you attach a full log for this crash?

WeaselKing commented 7 years ago

I have the same use case and what appears to be the same problem.

Phone: Samsung Galaxy S8 Plus Unity version: 2017.1.0f3 Code that I am using to crash the game:

    public void initiatevr()
    {
        StartCoroutine(initiatevrcoroutine());
    }

    IEnumerator initiatevrcoroutine()
    {
        Debug.Log("Initiating the VR Sequence");
        VRSettings.LoadDeviceByName("Cardboard");
        yield return null;
        VRSettings.enabled = true;
        Debug.Log("VR Sequence initiation complete");
    }

I put Debug.log strings in the code so you can see it in the logcat output more easily.

Some things of note: The game does not crash if you disable Google VR Services. This is replicated with the version that shipped with the phone, as well as the latest version which as of this moment is 1.7.161000338

The game does not crash on my old handset which is an LG G2.

Building with a mono back end or using IL2CPP makes no difference. Crash is the same.

I attached the logcat for the crash so you can check it out.

bestiLogcat.txt

VadimTikhonyuk commented 7 years ago

Hi, tedruxpin, There is log file, I cut it from adb logcat, so something important maybe lost, because full logfile is huge log.txt

fredsa commented 7 years ago

On S8+, can you let us know if the Cardboard app runs correctly (no crash) when you set the phone's screen resolution to the native device resolution:

Settings > Display > Screen resolution > WQHD+ > APPLY

Pseudopode commented 7 years ago

I have the same problem with a S8.

@fredsa : I made the test you asked for. Here's the results, with the latest Google VR Services update :

VadimTikhonyuk commented 7 years ago

@fredsa There have any way to open native settings and give user to change resolution. Similar to how this work in Gear VR. I have some skills in writing plugins on java

fredsa commented 7 years ago

@Pseudopode, thank you for confirming and sharing your results with WQHD+ and FHD+.

The behavior you're seeing when deactivating Google VR Services is expected as this service is responsible for entering VR mode, which includes enabling Low Persistence mode, which helps greatly with user comfort and image quality.

fredsa commented 7 years ago

@VadimTikhonyuk We're looking into this underlying issue. If in the mean time you have a workaround, please feel free to share here.

OmegaMule commented 7 years ago

Hi, is there any progress? We are having the same issue, instant crash on S8/S8+ when using non-native resolution. It would be really wonderful to get a fix asap.

Or is there a way to force user or Android to always switch to native resolution before staring an app? Thx.

sigmaxipi commented 7 years ago

One possible workaround is to add android:configChanges="density" to your Activity's manifest entry. I haven't tried this on Unity, but it works for a similar Android issue on the S8.

fredsa commented 7 years ago

Using a test apk, built using Unity 2017.1.0p4, it appears that it's not quite enough to use android:configChanges="density|…" in the app's activity.

Although this does prevent the app from immediately closing when it's launched at a less than full screen resolution, the result is that the stereo output is rendered at the wrong scale.

hd-plus fhd-plus

fredsa commented 7 years ago

We're looking into a couple of potential routes to fix this issue:

  1. An update to the Unity Android Player and the build process, to handle the density change event.
  2. An update to Google VR Services, to avoid the density change in the first place.
OmegaMule commented 7 years ago

Thank you for response. Just my two cents on the first solution/workaround:

  1. That would require new Unity (patch) release and re-import of ALL projects for every developer. Also from my experience with Unity, it might work in one release and stops working in another...

Could anyone please point me to the root cause of the crash? Is it GVR SDK, GVR service or Unity Player causing this? Thx.

guneyozsan commented 7 years ago

We get the same reports from users with S8+. If it is WQHD it works fine, if not it crashes during switch from 2D to VR. Since the app starts 2D we don't have info on what happens during switch from VR to 2D.

GavinThornton commented 7 years ago

Same on the Samsung Galaxy Note 8, I'm starting in "none" standard mode and loading Cardboard later, at that point crashes out if the device is in FHD+ 2200x1080 mode, change the device to WQHD 2960x1440 and is fine.

Log:

Could not recreate VR window because GfxDevice is in an invalid state (device lost)
[EGL] Attaching window :0xd413b808
onPause
D/VrManagerService: DisableKeycodeWink, component = ComponentInfo{com.conquermobile.ubc.eyetrackpd/com.unity3d.player.UnityPlayerNativeActivity}, enabled = true
V/SystemKeyManager: requestSystemKeyEvent() is called keyCode = 1082 componentName = ComponentInfo{com.conquermobile.ubc.eyetrackpd/com.unity3d.player.UnityPlayerNativeActivity} request = true
ANativeWindow: (2220/1080) RequestedResolution: (0/0) RenderingResolution: (0/0) EGLSurface: (2220/1080)
Error trying to call delegated method pause. null
dustinkerstein commented 7 years ago

Just wanted to check up on this issue as I'm getting more and more reports from users of this crash.

This is likely affecting the majority of S8 / S8+ / Note 8 users as those devices ship from the factory at FHD.

I was thinking about pushing out an update to my app that warns these users and prevents VR mode, but since I have the "daydream" VR device as the first in the list (and needs to stay this way for Daydream approval), my app will crash immediately at launch since it loads in VR mode from the beginning.

If anyone has a workaround or insight as to when this might be fixed, I'd very much appreciate it.

OmegaMule commented 7 years ago

It is becoming to be a really pressing issue, especially for developers who have their apps already on Google Play. Bad reviews could bury their apps, nobody cares it's not their fault. I just hope they will be able to fix it via GVR Services update which should be released at the end of this month. If not, then I'll have to do some ugly workarounds.

Also, IMHO, VR (or any app) should keep the resolution user has selected and shouldn't try to switch to native. Software should respect users settings, not override it. This problem shouldn't exist.

fredsa commented 7 years ago

We're actively working on a fix for this issue.

In the mean time the best available workaround is to have users change their device's default resolution to WQHD+:

Settings > Display > Screen resolution > WQHD+ > APPLY

dustinkerstein commented 7 years ago

Thank for the update @fredsa

Do you happen to know if it's going to be a fix to VR services or Unity? Any ETA?

Asking users to switch resolutions isn't really practical as I have no way to reach out to them, and in my case the application crashes immediately at launch so I can't warn them at all.

GavinThornton commented 7 years ago

We're actively working on a fix for this issue.

Is there an ETA of less than a few days or will it be longer?

Just want to know if it is worth working on a "detect and ask S8/S8+/Note8 users" system and pushing it out, or if this fix will come soon.

dustinkerstein commented 7 years ago

Just a quick note - I believe this bug will result in all Daydream Unity apps crashing on startup when set to FHD (the default resolution) on S8 / Note 8 devices, at least on the Unity / VR services versions where this bug exists. Please let me know if I can help at all. I'm happy to test any potential fixes or workarounds as this is a bit of a showstopper for me at the moment.

fredsa commented 7 years ago

Is there an ETA of less than a few days or will it be longer?

@GavinThornton It will very likely take longer than a few days.

fredsa commented 7 years ago

@dustinkerstein This bug covers Cardboard apps. If you're seeing issues with Daydream-only or Daydream/non-VR hybrid apps on S8, it would be great if you could file a separate issues with repro steps there.

dustinkerstein commented 7 years ago

@fredsa I was able to directly test a Galaxy S8 via http://developer.samsung.com/remotetestlab and understand the behavior a bit more now. The crash won't happen for most Daydream apps as it appears to only happen when VR mode is toggled (VRSettings.enabled = false <-> true) but it will immediately crash under the exact same conditions as this #671 bug. The only difference is that VR device = "daydream". Should I still create a separate bug?

Also, please see the attached log for the crash - Crash.txt

Effectively, all S8 / Note 8 devices will crash when toggling VR by default due to Samsung setting FHD at the factory.

fredsa commented 7 years ago

Thanks @dustinkerstein. Since the root cause appears to be the same, let's track that in this issue. I've updated the issue title to reflect this.

dustinkerstein commented 7 years ago

Until this Galaxy S8 / S8+ / Note 8 showstopper is fixed, I'm going to warn these users with this condition: if (SystemInfo.deviceModel.Contains("G950") || SystemInfo.deviceModel.Contains("G955") || SystemInfo.deviceModel.Contains("N950")) but I really would only like to warn users that are set to a resolution other than WQHD+. Has anyone figured out a way in Unity to detect when the device isn't in WQHD+ mode?

It seems like no matter what resolution is set (HD+, FHD+, WQHD+) all of these methods return the values corresponding to WQHD+

Are there any other ways to possibly detect this condition?

guneyozsan commented 7 years ago

@dustinkerstein You should be able to get the current resolution by using a full screen canvas and reading canvas width and height in screen space (rotating the device will switch parameters, so you may need to use min and max for determining width and height). Screen class is useless as it always returns native resolution for some reason. If canvas method doesn't work let me know and I'll dig into my projects to find how I solved it before.

dustinkerstein commented 7 years ago

Thanks @guneyozsan I will give that a shot.

Also, it's interesting to note that this crash does not happen on the Galaxy S7 / S7 Edge when set to HD, FHD (default in Nougat), or WQHD. The crash is specific to the taller screen (2960 pixels vs. 2560 pixels) of the S8 / Note 8 line of phones.

dustinkerstein commented 7 years ago

@guneyozsan I tried both GalaxyWorkaround.transform.localPosition and GalaxyWorkaround.pixelRect.width where GalaxyWorkaround is a Pixel Perfect Screen Space Overlay Canvas and I get the same results for all of the resolutions.

guneyozsan commented 7 years ago

@dustinkerstein I checked and this is how I get the current resolution:

CanvasScaler canvasScaler;
int shortSide = Mathf.Min(Mathf.RoundToInt(canvasScaler.referenceResolution.x), Mathf.RoundToInt(canvasScaler.referenceResolution.y));
int longSide = Mathf.Max(Mathf.RoundToInt(canvasScaler.referenceResolution.x), Mathf.RoundToInt(canvasScaler.referenceResolution.y));
dustinkerstein commented 7 years ago

@guneyozsan I wasn't able to get that working as it seems to always return the reference size, not the current scaled size. Would you be able to send over a screenshot of your Canvas and CanvasScaler properties?

guneyozsan commented 7 years ago

@dustinkerstein Ops, you are right. Sorry, it has been a year I did this and the inconsistent results mislead me. Actually Canvas.pixelRect.width/height should also be the solution. Since both Screen class and Canvas.pixelRect.width/height gives native resolution I suspect that Unity always runs in native WQHD and the device downscales the display from WQHD to FHD.

dustinkerstein commented 7 years ago

@guneyozsan Yeah, which in turn means that I won't be able to detect this condition and am forced to warn all S8 / S8+ / Note 8 users regardless of their selected resolution :(

OmegaMule commented 7 years ago

There is another interesting bug related to this issue. Calling Screen.SetResolution() in Unity doesn't affect Cardboard's VR viewports at all. They are always being rendered at the initial size (being rendered outside of screen borders for example). What makes this even worse is that calling VRSettings.RenderScale or ViewportRenderScale changes their resolution, but not their on-screen size. So first of all SetResolution() should work correctly, without it nobody can really do any workarounds.

Also, since apps do NOT crash with VR Services turned off, probably because resolution is not being enforced, how hard can it be to release hotfix VRServices version which wouldn't enforce the native res for Cardboard apps?

fredsa commented 7 years ago

@OmegaMule Please create a separate issues for the Screen.SetResolution() and VRSettings.renderScale / VRSettings.renderViewportScale issues you're seeing, and link to the Unity bug which will help us track any fixes which need to happen there.

dustinkerstein commented 7 years ago

Just wanted to check in to see if there was any ETA for this fix. Happy to help test any beta code or potential workarounds.

jdduke commented 7 years ago

No definitive ETA, but we're actively exploring several solutions together with Samsung. We'll keep this thread posted as we have more concrete details to share.

dustinkerstein commented 7 years ago

FYI, in case anyone was wondering about the newest Google VR Services update, it doesn't have any effect on this particular issue.

dustinkerstein commented 7 years ago

Just wanted to check in. Any news from the Samsung / Unity / GVR side of things?

OmegaMule commented 7 years ago

@dustinkerstein: Unity 2017.1.2p1 "XR: Fixed handling of Android density (screen resolution) changes to avoid a crash."

rusmaxham commented 7 years ago

A fix for this is also coming to Unity 5.6.x.

dustinkerstein commented 7 years ago

@OmegaMule Nice! I just confirmed this is working correctly in 2017.1.2p1 for both FHD+ and WQHD+ resolutions. Toggling VR mode also works correctly.

OmegaMule commented 7 years ago

OK I've tested the crashfix change on Unity 2017.1.2p1 and Unity 5.6.4p1, the result is as I've predicted. Unity devs just added "density" to Android Manifest, which prevents the crash when GVR Services enforce resolution change. The scaling, however, is still not fixed. VR viewports are incorrectly scaled and positioned due to resolution difference.

So this is just first step. Users still need to change resolution to WQHD to use Cardboard.

Is there any ETA for the scaling fix? Thanks.

Update: Luckily it's possible to create a fully working workaround using Screen.SetResolution() to make it work without user intervention.

dustinkerstein commented 7 years ago

@OmegaMule Can you post a screenshot of that? I haven't seen that when testing on the devices here - http://developer.samsung.com/remotetestlab/rtlDeviceList.action

OmegaMule commented 7 years ago

@dustinkerstein: https://user-images.githubusercontent.com/1235362/30393677-baf78ef4-9875-11e7-971b-f217abded447.png

It looks exactly like that on real Galaxy S8 device and clean Unity version I mentioned before.

Update: I've also tried it on S8 simulator you posted with the same result.

dustinkerstein commented 7 years ago

@OmegaMule Interesting, I am not able to replicate that behavior with my app when testing on the Samsung Remote Device lab (which I believe are in fact real devices, not emulators or simulators). Is it possible to post your project online?

jdduke commented 7 years ago

Is there any ETA for the scaling fix? Thanks.

The plan is to push an updated Google VR Services build to resolve the second half of the problem (properly responding to "density" changes when declared in the manifest). We expect the rollout to hit 100% by the end of next week (Nov. 3).

jdduke commented 7 years ago

The fix to allow "density" changes without an app restart (by way of the app manifest) has rolled out to 100%. Note that the resolution change will still occur if the user has not explicitly changed the resolution to native.

Separately, we're exploring rollout of a global prompt to change the resolution of the device to native, sometime in December. That will avoid the resolution switch entirely, though it may be suboptimal for some users who don't want their device always running at native resolution.