MonoBehaviour.OnRenderObject() differences desktop vs. Android

Hello, all

I’m relatively new to mobile development, having mostly worked in desktop platforms. I’m hoping someone can help with a rendering and/or threading question on Android.

I’ve got some code that hooks OnRenderObject() to draw procedural geometry using Graphics.DrawMeshNow() calls. There are two cameras in the scene, and some boolean flags determine whether the procedural objects render on one camera, both cameras, nor none.

Everything works flawlessly in the editor and a standalone desktop build, but on Android things are crashing on the call to Graphics.DrawMeshNow() from within OnRenderObject(), but only under certain conditions.

If the object is set to render on both cameras by a static boolean flag, I get the crash.

If the object is set to render on zero or one cameras, no crash.

If the object is set to render on both cameras by explicitly testing Camera.current to see if it is one of the two desired cameras, no crash.

Since I can’t replicate the problem outside Android, I think it’s related to some kind of threading in the render pipeline, that may be causing OnRenderObject() to be called reentrantly, as if it starts rendering on one camera before it finishes rendering on the other.

Is that something that happens in Android? Is there a simple way for me to issue Debug.Log() calls, or equivalent, and have the output go back to the Unity editor? (I’m doing “build and run” from the editor but am not seeing log messages.)

I’m not really sure what to be looking for here. I’ll keep digging at this, but it’s frustrating to see it render correctly on both cameras when I do the “which camera” test from instance variables, but it fails when the same test gets a “true” on the static variable. And it never replicates on desktop. Whatever this is, I’m bumping up against something deep in the pipeline, I think. Any suggestions?

Could you attach logcat?

Also, a long shot, but do you have multithreaded rendering enabled?

Doh! Yes, I am an idiot! I actually captured this last night and just forgot to attach it. Sorry! I also should have mentioned that I’m running Unity 2017.3.0f3 (no patches).

Yes, but based on your question I retested after turning that off, and it didn’t help. Good suggestion, though.

I’m attaching the log. The error I think is of interest is this one:

02-13 23:11:34.047 11950 11973 F libc : Fatal signal 11 (SIGSEGV), code 2, fault addr 0xcbd81fb4 in tid 11973 (UnityGfxDeviceW)
02-13 23:11:34.175 12014 12014 F DEBUG : pid: 11950, tid: 11973, name: UnityGfxDeviceW >>> com.j4th.MagicMarkersDemo <<<

@Tomas1856 , if you or someone else at Unity can tell me what Unity’s engine is trying to do at that point, it would be really helpful even without a traceback context. I’m really confused by what I’m observing, not sure if it’s an Android bug, a bug in my code, or a bug in Unity. My asset was working correctly on this Android device before, with this same Unity version, but I changed the asset C# code and happened to catch a major Android update on the device during that workflow, so I have multiple variables changing. My old code version still runs, but I can’t tell if I broke the code here, or if I’ve simply uncovered an Android or Unity bug that has been there all along but just wasn’t triggered by my old version.

I’ve also tried wrapping my OnRenderObject() implementation with a static bool so I skip the body of the method if the method is already running (presumably from another thread), but that didn’t help.

If there was a way for me to see the Debug.Log() output from the Android device, it would really help, because then I could do a trace of Camera.current.name to see which camera is causing the error, and also definitively whether the method is being called reentrantly.

Thanks for the post; I’m really new at the Android side of things. My asset isn’t officially targeted as a tool for mobile; I’m just trying to be a good citizen and support all the platforms for which I have physical hardware to test.

3391435–266643–AndroidErrorLog.txt (8.44 KB)

UnityGfxDeviceW looks like a worker thread in Unity… though it’s weird there’s no stacktrace, is this a non development player? Did you try development player, maybe it will have more info, looking at your log there’s no Unity log at all, that basically indicates this is a non development player. That would also probably enable Debug.Log messages in logcat.

Thanks, I’ll retest with that option enabled. As I mentioned, I’m fairly new to mobile. It’s not my main focus in Unity, just something I’m trying to be sure my asset supports. :slight_smile:

I’ve got a more detailed log tonight, which I’m attaching here.

Relevant sections (I think):

02-16 01:00:12.638 14434 14473 I Unity   : PreviewCamera
02-16 01:00:12.638 14434 14473 I Unity   : UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
02-16 01:00:12.638 14434 14473 I Unity   : UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
02-16 01:00:12.638 14434 14473 I Unity   : UnityEngine.Logger:Log(LogType, Object)
02-16 01:00:12.638 14434 14473 I Unity   : UnityEngine.Debug:Log(Object)
02-16 01:00:12.638 14434 14473 I Unity   : MagicMarkers.MagicMarkerAbstract:OnRenderObject() (at C:\Users\Shared\gamingdev\unity\Projects\MagicMarkers-Upload\Assets\Plugins\MagicMarkers\Scripts\MagicMarkerAbstract.cs:462)
02-16 01:00:12.638 14434 14473 I Unity   :
02-16 01:00:12.638 14434 14473 I Unity   : (Filename: C Line: 0)
02-16 01:00:12.638 14434 14473 I Unity   :
02-16 01:00:12.651 14434 14473 E Unity   : The given primitive topology does not match with the topology expected by the geometry shader
02-16 01:00:12.651 14434 14473 E Unity   : UnityEngine.Graphics:INTERNAL_CALL_Internal_DrawMeshNow1(Mesh, Int32, Vector3&, Quaternion&)
02-16 01:00:12.651 14434 14473 E Unity   : UnityEngine.Graphics:Internal_DrawMeshNow1(Mesh, Int32, Vector3, Quaternion) (at /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/GraphicsBindings.gen.cs:680)
02-16 01:00:12.651 14434 14473 E Unity   : UnityEngine.Graphics:smile:rawMeshNow(Mesh, Vector3, Quaternion, Int32) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Graphics.cs:400)
02-16 01:00:12.651 14434 14473 E Unity   : UnityEngine.Graphics:smile:rawMeshNow(Mesh, Vector3, Quaternion) (at /Users/builduser/buildslave/unity/build/Runtime/Export/Graphics.cs:393)
02-16 01:00:12.651 14434 14473 E Unity   : MagicMarkers.MagicMarkerAbstract:smile:rawMarkerPass(Int32) (at C:\Users\Shared\gamingdev\unity\Projects\MagicMarkers-Upload\Assets\Plugins\MagicMarkers\Scripts\MagicMarkerAbstract.cs:515)
02-16 01:00:12.651 14434 14473 E Unity   : MagicMarkers.MagicMarkerAbstract:smile:rawMarker() (at C:\Users\Shared\gamingdev\unity\Projects\MagicMarkers-Upload\Assets\Plugins\MagicMarkers\Scripts\MagicMarkerAbstract.cs:500)
02-16 01:00:12.651 14434 14473 E Unity   : MagicMarkers.
02-16 01:00:12.666  2318  2318 D GyroRender: onSensorChanged event.sensor.getType() = 65579
02-16 01:00:12.677 14434 14473 I Unity   : MapCamera
02-16 01:00:12.677 14434 14473 I Unity   : UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
02-16 01:00:12.677 14434 14473 I Unity   : UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
02-16 01:00:12.677 14434 14473 I Unity   : UnityEngine.Logger:Log(LogType, Object)
02-16 01:00:12.677 14434 14473 I Unity   : UnityEngine.Debug:Log(Object)
02-16 01:00:12.677 14434 14473 I Unity   : MagicMarkers.MagicMarkerAbstract:OnRenderObject() (at C:\Users\Shared\gamingdev\unity\Projects\MagicMarkers-Upload\Assets\Plugins\MagicMarkers\Scripts\MagicMarkerAbstract.cs:462)
02-16 01:00:12.677 14434 14473 I Unity   :
02-16 01:00:12.677 14434 14473 I Unity   : (Filename: C Line: 0)
02-16 01:00:12.677 14434 14473 I Unity   :
02-16 01:00:12.684  2318  2318 D GyroRender: onSensorChanged event.sensor.getType() = 65579
02-16 01:00:12.700 14434 14473 I Unity   : Main Camera
02-16 01:00:12.700 14434 14473 I Unity   : UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
02-16 01:00:12.700 14434 14473 I Unity   : UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
02-16 01:00:12.700 14434 14473 I Unity   : UnityEngine.Logger:Log(LogType, Object)
02-16 01:00:12.700 14434 14473 I Unity   : UnityEngine.Debug:Log(Object)
02-16 01:00:12.700 14434 14473 I Unity   : MagicMarkers.MagicMarkerAbstract:OnRenderObject() (at C:\Users\Shared\gamingdev\unity\Projects\MagicMarkers-Upload\Assets\Plugins\MagicMarkers\Scripts\MagicMarkerAbstract.cs:462)
02-16 01:00:12.700 14434 14473 I Unity   :
02-16 01:00:12.700 14434 14473 I Unity   : (Filename: C Line: 0)
02-16 01:00:12.700 14434 14473 I Unity   :

((( SNIP )))

02-16 01:00:14.138  2423  2605 D EPDG -- [EPDGService]: onDataActivity: direction=0
--------- beginning of crash
02-16 01:00:14.208 14434 14473 F libc    : Fatal signal 11 (SIGSEGV), code 2, fault addr 0xcf6fcff8 in tid 14473 (UnityMain)
02-16 01:00:14.210   503   503 W         : debuggerd: handling request: pid=14434 uid=10242 gid=10242 tid=14473
02-16 01:00:14.326 15247 15247 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-16 01:00:14.326 15247 15247 F DEBUG   : Build fingerprint: 'samsung/dreamqlteue/dreamqlteue:7.0/NRD90M/G950U1UES2AQL1:user/release-keys'
02-16 01:00:14.326 15247 15247 F DEBUG   : Revision: '12'
02-16 01:00:14.326 15247 15247 F DEBUG   : ABI: 'arm'
02-16 01:00:14.326 15247 15247 F DEBUG   : pid: 14434, tid: 14473, name: UnityMain  >>> com.j4th.MagicMarkersDemo <<<
02-16 01:00:14.327 15247 15247 F DEBUG   : signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0xcf6fcff8
02-16 01:00:14.327 15247 15247 F DEBUG   :     r0 00000000  r1 00000000  r2 00000001  r3 00000000
02-16 01:00:14.327 15247 15247 F DEBUG   :     r4 cae8d580  r5 00000000  r6 00000000  r7 00000000
02-16 01:00:14.327 15247 15247 F DEBUG   :     r8 cae8d580  r9 cc056af8  sl cae8fa00  fp cae8f824
02-16 01:00:14.327 15247 15247 F DEBUG   :     ip 80000000  sp cf6fcfe0  lr cb3b438f  pc cb39c99a  cpsr 480b0030

Note the messages on lines 2, 20, and 30. The camera identification is a Debug.Log() call at the top of my OnRenderObject() method implementation.

My scene has only two cameras, “Main Camera” and “MapCamera”. That “Preview Camera” is added somehow by Unity. This is a very important clue, because my procedural objects have a camera selection mask that allows a choice of which camera(s) to include. If I specifically choose the exact cameras in my scene, everything works, but if I choose “Everything” from the mask in the inspector, then it crashes every time. I couldn’t figure out how choosing “Everything” was different from choosing all the cameras as a list. Now I know. “Everything” includes that “Preview Camera”, and that’s the one that’s crashing.

Also relevant here is the boldfaced error message about a geometry shader. My custom shader does have a geometry component, but I have two sub-shaders, one with #pragma target 4.0 and the other with #pragma target 2.5 declarations. The second sub-shader does not define any geometry component because geometry shaders require SM 4.0, so if the PreviewCamera does not support geometry shaders, it shouldn’t be using the 4.0 target sub-shader.

Now, here is where things get really interesting: I found a workaround! At the beginning of OnRenderObject(), I simply check the name of the camera against the string “PreviewCamera”, and if it matches, I return immediately with no draw attempt. My scene renders perfectly on all the other cameras, and the geometry feature of my custom shader is fully functional.

What I can’t figure out is why this is behaving differently on Android than it does on desktop. Is the “PreviewCamera” somehow connected to the UI rendering on mobile devices?

3393328–266840–AndroidErrorLog.txt (936 KB)

Hmph, I can’t find any cameras named “PreviewCamera” in Unity code base, there is “Preview Camera”, but that’s only alive when in Editor, visible in scene view.

The other bad news, you’re crashing in a driver, there was a long stacktrace in libGLESv2_adreno.so… And those basically are almost never fixed by phone manufacturers, we usually workaround such cases if there’s a bug.

I am glad you have a workaround.

If you want to pursue this further, you would need to submit a bug report with small repro project attached if possible, I am curious where this “PreviewCamera” comes from, assuming your code doesn’t create it.

P.S You can also try to use managed debugger with Android, maybe it will give you more info. This might help https://docs.unity3d.com/Manual/AttachingMonoDevelopDebuggerToAnAndroidDevice.html

1 Like

Thanks so much for looking at the Unity code base. That’s one thing I absolutely couldn’t do myself, and I really appreciate your time on that!

I checked my scene carefully, object by object (it’s just a small test scene for my editor extension asset). I also checked the one prefab (the player) that my code instantiates at runtime. No cameras are created, preview or otherwise, and only the main camera and the map camera exist as GameObjects at start time.

When I was reading the Unity docs about CameraType, it appears to me the preview camera is the one that the editor shows overlaying a corner of the Scene View when a Camera object is the current selection. My theory, perhaps disproved by your code examination, is that a piece of the editor code is sneaking into the runtime, or that the runtime code thinks this has happened and is trying to talk to something that isn’t there. You have access to the source, I don’t, so perhaps I’m completely full of it. :slight_smile:

This makes a certain amount of sense to me, because as you may recall from one of my earlier posts, it happened that my phone got an Android update and a system drivers update from Samsung while I was creating the new version of my asset. It may be that the preview camera thing has been there all along and was harmlessly ignored until the phone software introduced a new driver bug that’s triggered by the preview camera thing.

Me, too! If I hadn’t already been bald before, I would have torn my hair out over this one. You get credit for pushing me to a dev build; I didn’t realize that would enable those Debug.Log() traces I had been wanting. Next time, I know. I think there was an editor extender that rerouted the console from an attached mobile device back to the main editor’s console, but I may be mistaken. If it exists, I’ll probably buy it and try it.

Let me ask you, from the Unity side (and acknowledging that you are just one very helpful employee and do not speak for the company as a whole), do you think it would be useful to the Unity team to help improve the engine? I had an issue recently in one of my larger projects (about 6 gigabytes) that I can’t easily repro in a test harness, but in this case I can easily send you a small project (about 100 meg) that repros the problem reliably. That being said, if you think this is a phone driver issue, or some subtle bug in my code and not in Unity, I don’t want to be “that guy” who clogs Unity’s bug queue with problems that are not within Unity’s sphere of control to fix. Recommendation welcome. :slight_smile:

I might give that a try. I’m not sure it would help here, because the crash was happening inside a call to Graphics.DrawMeshNow(), but it’s certainly a useful thing to know for the future.

P.S. I was proofreading my post before submitting, and I noticed my reference to a “small” project at “100 meg”. Remember the days when 100 meg was not a small ANYTHING? :slight_smile:

P.P.S. If nothing else, the debug log caused me to notice a small bug in one of my sub-shaders. I had changed a parameter from float to int in this version but was still comparing it as a float in one line of shader code. It was harmless, because the shader compiler just silently promoted it to a float, and comparing “1.0f >= 0.5f” (the old code) versus “1 == 1” gets the right answer either way, but it was still a bug, and now it’s squashed.

Of course,it would be useful :slight_smile: If this camera is really sneaking into runtime, that’s a serious regression… 100MB sounds like a perfect repro. As for driver bug, no promises.

Okay, I’ll commit to file the bug report, but I can’t do it today. I have a major project deadline early next week that has me working all weekend, and that has to take priority for a few days. I’ll update here when the bug report is done.

Thanks again for helping me find a workaround. I was really sweating bullets over this problem. :slight_smile: