Bug 2139 - Support opengl context sharing across threads
Summary: Support opengl context sharing across threads
Status: VERIFIED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 2.0
Hardware: PC Windows
: Normal enhancement
Target Milestone: 4.16.0
Assignee: dean.ellis
URL:
Depends on:
Blocks:
 
Reported: 2011-11-21 17:38 UTC by Jonathan Pobst
Modified: 2014-09-17 09:23 UTC (History)
9 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Description Jonathan Pobst 2011-11-21 17:38:56 UTC
From https://bugzilla.novell.com/show_bug.cgi?id=638017.

---

I noticed that AndroidGameView has a context property, but does this actually
map to an EGLContext? 
If it doesn't then some of us will have issues loading textures on a background
thread as we need the ability to store the current OpenGL rendering context and
also its associated ShareGroup, so that it we can switch contexts when on the
Main thread and also a background thread 

Currently on MonoTouch I can do the following, where _view is a pointer to the
currently running iPhoneOSGameView...

_view.MainContext/*local variable*/ = _view.EAGLContext;
_view.ShareGroup/*local variable*/ = _view.MainContext.ShareGroup;
_view.BackgroundContext/*local variable*/ = new
MonoTouch.OpenGLES.EAGLContext(_view.ContextRenderingApi, _view.ShareGroup);

then in the thread where you are loading the textures you need to do something
like this...

// Switch to our shared Context
EAGLContext.SetCurrentContext(_view.BackgroundContext);

// Load your textures here....

// Switch to our main Context
EAGLContext.SetCurrentContext(_view.MainContext);

Anyway worth keeping in mind if adding the MonoTouch compatibility.
Comment 2 Miguel de Icaza [MSFT] 2013-05-13 15:46:01 UTC
Dean, can you review this OpenGL case?
Comment 4 David Ávila Membrives 2014-07-15 05:59:13 UTC
Hi, 

We are using Xamarin.Android 4.12 and we have the same problem. We are unable to share OpenGL Context between two threads (to load a texture in background for example). I don't know if it is a Xamarin.Android limitation or an Android platform related issue.

Best regards,

David Ávila Membrives
Software Developer at WaveEngine
http://waveengine.net
Comment 6 dean.ellis 2014-07-18 08:39:44 UTC
I have managed to make some changes to our master build of the AndroidGameView which will allow shared contexts to work. However using test cloud I have proven that shared contexts do NOT work on all GPU's. So far I have confirmed that if you try to use a shared context on a NVIDIA chip or a GC1000 chip your application will lockup. The problem is both of these chips report that they support PBuffer's which are used as a dummy surface for the second context, but lockup when you try to use it. I'm still trying to see if there is a setting/attrib that will tell us if its supported. 

The VideoCore IV chip sometimes works but sometimes doesn't.

So out of 133 devices tested only 9 failed. all of which ran a NVIDIA, GC1000 or VideoCore chip. Chips that do work are PowerVR , Adreno, Mali and sometimes the VideoCore IV. There may be other chipsets but I don't have access to them at the moment.

One other thing to note is that having 2 contexts active at the same time WILL NOT WORK on these devices. In order to get this to work you need to clear the current context, and make the new one active. If you try to make the new one active without clearing it first it will fail. So when using this you need to make sure you are synchronising your render thread and the background thread (which is probably being used to load assets).

These results are for GLES 1.1. On GLES 2.0 it gets worse, it seems only the Mali drivers support shared context's on android and some of the VideoCore ones. All the others fail, but at least they fail with an error rather than a lockup so we can fallback to other methods. I have not tested this on GLES 3.0 yet. 

So basically I will put in support for this, but its not going to work everywhere, in fact its more than likely that it won't work until the hardware vendors fix the OpenGL ES drivers.
Comment 7 dean.ellis 2014-07-18 08:40:11 UTC
I will post up details of the way this is going to be implemented shortly
Comment 8 dean.ellis 2014-07-18 09:43:16 UTC
Correction, there was a bug in the shared context code. Looks like GLES 2.0 might be better now :) Retesting.
Comment 9 dean.ellis 2014-07-18 09:58:25 UTC
OK my earlier statement regarding GLES 2.0 was not correct. It seems that we get similar results. About 9 devices fail, but different GPU's the Adreno chips mostly work but some do not display the test texture which was loaded on the background context. I'll need to look at the logs to figure out why that might be. 

The good news is that for GLES 2.0 the NVIDIA chips seems work work as do PowerVR,Mali and VideoCore
Comment 10 David Ávila Membrives 2014-07-18 11:49:14 UTC
Thanks for your effort,

In earlier posts I was afraid because our target is OpenGL ES 2.0 devices with API Level 14 (ICS 4.0), but now we hope that the shared context support will be available. We are waiting for more news :)

Best regards,

David Ávila Membrives
Software Developer at WaveEngine
http://waveengine.net
Comment 11 dean.ellis 2014-07-18 12:02:03 UTC
David

The way I'm working this is that you will be able to create a secondary context using

var backgroundContext = new AndroidGraphicsContext (GraphicsMode, WindowInfo, GraphicsContext, this.ContextRenderingApi, GraphicsContextFlags.Embedded);

within the your AndoridGameView class.  If this throws an exception then its not supported on that device. You will then be able to do the following on a background thread

backgroundContext.MakeCurrent (null);
backgroundContext.MakeCurrent (WindowInfo);
// Open GL Calls here 
backgroundContext.MakeCurrent (null);

NOTE, you will need a lock (lock object) statement or some kind of synchronisation around the rendering code otherwise you get weird results (MakeCurrent errors or textures just don't show).  Also the MakeCurrent(null) is really important, if you don't clear out the current context first, it will error on most of the devices. 

you will need a backup way of invoking those OpenGL calls on the main context thread though, I think an Action queue is probably the simplest way.

I'm putting a Shared Context Sample together for GLES 2.0 which will include all that stuff, I'll put up in the monodroid-samples as soon as I've cleaned it up a bit and got the main AndrdoidGameView changes into our master branch.

Dean
Comment 12 Pete 2014-07-18 14:14:18 UTC
Dean,

Thanks for your efforts! 

I was the one that reported the issue in WaveEngine's forums. Maybe these helps (or not): 

1) http://stackoverflow.com/questions/11726650/egl-can-context-be-shared-between-threads

2) http://www.khronos.org/message_boards/showthread.php/9029-Loading-textures-in-a-background-thread-on-Android

Hope it helps.
Comment 13 David Ávila Membrives 2014-07-22 06:15:23 UTC
Hi Dean,

I tried your guidelines you said above and always the app crash on the same point:
backgroundContext.MakeCurrent (WindowInfo) // <-- Throws a make current exception EGL_BAD_ACCESS
Comment 14 dean.ellis 2014-07-22 06:19:42 UTC
There are fixes for the AndroidGraphicsContext that have not been released yet which will allow this to work. the PR is currently pending a review you can view it here

https://github.com/mono/opentk/pull/9

It should be out in the 4.16 release. 

With the current release you will get the BAD_ACCESS exception.
Comment 15 dean.ellis 2014-07-28 16:16:58 UTC
Fixed in opentk/master/d138925ec2

Sample added to https://github.com/xamarin/monodroid-samples/tree/master/GLSharedContext20
Comment 16 Pete 2014-07-29 16:33:43 UTC
Thanks a lot! Eta for 4.16? (or is it 4.14?)
Comment 17 dean.ellis 2014-07-29 16:42:16 UTC
This will be in 4.16.
Comment 18 Ram Chandra 2014-08-13 08:50:15 UTC
I have checked this issue with following builds:

Windows 6.2.9200.0
XVS: 3.5.25
Xamarin Studio: 5.3 (build 423)
Xamarin.Android: 4.16.0 
Build Information
Release ID: 503000423
Git revision: f4bb573b38a18c9f5400d8734eada2d5610deae4
Build date: 2014-08-12 17:31:43-04
Xamarin addins: 0961e1860cd1dcb4e47062f25c40d224979a02fb

I have checked this issue with "GLSharedContext20" android sample and observed that when I deploy the sample on device (Samsung Note 3{Android 4.4.2}) , I am not getting any error and exception.

This issue has been fixed. Hence. I am closing this issue.
Comment 19 Pete 2014-08-13 13:34:43 UTC
Is 4.16 out?
Comment 20 Radek Doulik 2014-08-13 15:33:11 UTC
I think it is now in Beta channel. (and 4.17 in Alpha)
Comment 21 Radek Doulik 2014-09-02 08:41:07 UTC
Also note that the bug has been fixed in the OpenTK-1.0.dll, the original sample uses OpenTK.dll.
Comment 22 renan jegouzo 2014-09-04 09:29:43 UTC
alternatively you can use Android.Opengl.GLSurfaceView that works well too, and maybe simpler than the openTK gameview.
Comment 23 David Ávila Membrives 2014-09-17 09:23:09 UTC
I've tested the 4.16 version and I can confirm that the problem is fixed :)

Thanks a lot!