January 23, 2013 at 10:25 pm #17607
I’ve been developing with Syphon and something I’ve never seen before (on a Mac) keeps happening — my entire system reboots. It happens when I have the Simple Server running, and a client (which I developed) running in my own app, and then I drag the Simple Server window to resize it. Bam. Computer restarts. Has anyone else seen this?
While looking into this, I noticed that there doesn’t seem to be a way to lock the server’s context from the client. Which means that, couldn’t the SyphonImage that I request with newFrameImageForContext become invalid immediately after I request it? I.e., if the Server is resized? So now, my SyphonImage could be referring to a texture that’s no longer relevant.
It seems like there should be a way to tell the server that the texture is being used in the client right now, and that the server shouldn’t destroy it, even if it’s resizing.
Making sense at all? Any help appreciated.January 24, 2013 at 6:04 am #17628
Syphon takes care of synchronisation (well, the underlying IOSurface does). As long as you retain a SyponImage in the client app, the surface remains valid even if the server is no longer using it.
Can you recreate the problem using only Simple Server and Simple Client? If not, can you provide an Xcode project for a minimal client app which does recreate the problem?
Also what hardware and OS version are you on?January 24, 2013 at 7:26 am #17629
No, I can’t recreate it with only the Simple Server and Simple Client. So it’s definitely something I’m doing in my app. Unfortunately my app is too big to share here, and I’m not sure I could whittle it down easily.
I have a MacBook Pro 9,2 with 10.8.2. After the computer restarts, and I view the error report, it definitely seems to be an issue with the graphics driver. Strange. I’m really not understanding why the entire system would reboot instead of just crashing the app. It makes it really difficult to debug!
I’ll have to do some more investigating and get back to you I guess. Thanks.January 24, 2013 at 8:21 am #17630
Welcome to the world of GPU-driver induced kernel panics… They shouldn’t happen, but they are easily triggered by abusing the GL.
Creating a reduction is my usual strategy when faced with kernel panics – often it’s the quickest way to identify the bad code, even though it can be a pain. Also, if you haven’t already, run your app in OpenGL Profiler, breaking on errors, and see if it throws any GL errors prior to causing the KP.January 24, 2013 at 11:13 am #17637
Commenting out this line in my code prevents the problem:
Strange, right? Any ideas?
Also, is there some reason why you don’t just support GL_TEXTURE_2D?January 24, 2013 at 12:17 pm #17638
Impossible to know without knowing what myTexName refers to and what you have done and are doing with it.
We do support GL_TEXTURE_2D for serving. The underlying IOSurface only supports GL_TEXTURE_RECTANGLE. Is it a problem to you?January 24, 2013 at 1:08 pm #17639
Sorry, I should have given more detail. Basically I am doing this:
SyphonImage *myFrame = [myClient newFrameImageForContext:myContext];
GLuint myTexName = [myFrame textureName];
NSSize myTexSize = [myFrame textureSize];
… etc. My code is virtually identical to that of the Simple Client.
Keep in mind that this works perfectly fine most of the time. It’s only when the Simple Server is resized that the problem occurs.
I was just thinking that maybe GL_TEXTURE_2D would be less problematic, but maybe not.January 24, 2013 at 3:04 pm #17655
Sounds like a problem with your code. If you can share a reduction which reproduces the issue we can take a look at that.January 24, 2013 at 4:20 pm #17656
Try to use GL Profiler and break on error, and introspect your GL State, or see if you can reproduce on another GPU, you might be hitting an edge case.August 17, 2013 at 8:31 am #29285
In viewing your issue list in response to my other post, it seems that the following issue may be relevant to the problem I have described above:
https://github.com/Syphon/Syphon-Framework/issues/2August 17, 2013 at 10:07 am #29286
Try cloning, building and linking against the mt-issue branch from GitHub and see if that solves it (and let us know).April 17, 2015 at 5:40 pm #58967
After a long time without solving this issue (and thus having occasional crashes), I think I finally have some insight. Can you give me your opinion? Hopefully it will help someone else if it’s the right answer.
I’m running Syphon in a plugin, which doesn’t have much access to the host app’s state. So, I never thought twice about using the static function [NSOpenGLContext currentContext]. But now I realize there’s a chance that this function might not return the right context. And if it’s the wrong one, and Syphon tries to use it, things go south pretty quickly.
Am I thinking about it correctly? The proper solution would require I have direct access to the variable which represents the actual context for the window, right?April 18, 2015 at 11:13 am #58968
Ok, actually I don’t think that’s the problem. But I think this is:
Apparently all GL functions need to be locked when rendering isn’t in the main thread. NSOpenGLView will call GL functions from the main thread when the window is resized, etc. So not only does the secondary thread have to be locked, but all functions in NSOpenGLView have to be overriden and locked as well.April 19, 2015 at 8:11 am #58969
Thats not quite correct –
OpenGL access has to be *serialized* – meaning you cannot make concurrent requests to OpenGL from multiple threads, as you will corrupt the command stream submitted to the GPU, and cause issues.
OpenGL is a state machine, you twiddle state on and off and submit objects, and then render at the current configuration. Changes you make persist, and order of operations matter.
So in terms of multithreading OpenGL, you have to serialize access to a OpenGL Context.
Lock for OpenGL
Draw / Resize Viewport
Render/ Flush the screen
Unlock for OpenGL
Do something to prepare expensive calculations for OpenGL
Lock for OpenGL
Submit OpenGL Commands
Continue on your way
Hope that helps.April 19, 2015 at 10:17 am #58970
To be clear, you can use OpenGL on a secondary thread without locks, if you never touch it from another thread (i.e., its guaranteed to be serial on that thread and that thread only).April 19, 2015 at 1:38 pm #58971
I understand what you are saying. But I found this link (apologies that it’s a book and was written in 2007): https://books.google.com/books?id=Ryb-k7jrPnIC&pg=PT74&lpg=PT74&dq=what+commands+does+nsopenglview+issue&source=bl&ots=ql64KJbQ2q&sig=fugHPEgKub7RoiT668Fq_w1AIvM&hl=en&sa=X&ei=3MIyVYWPLZbhoASd_YHgBQ&ved=0CDIQ6AEwAw#v=onepage&q=what%20commands%20does%20nsopenglview%20issue&f=false
According to that, and assuming it’s still relevant, the NSOpenGLView class makes implicit OpenGL calls when the window is resized. Thus, from a programming perspective, you can’t control when GL commands will be issued on the main thread. Hence, when using a second thread to do rendering, locking the context is required to ensure the main thread doesn’t interrupt the command stream. And vice versa.
See what I’m saying?April 20, 2015 at 2:34 am #58972
Aren’t you both saying the same thing?
In a plugin the situation is complicated by the actions of the host app. Usually the plugin interface will define the behaviour in its documentation, and you needn’t worry about locking at all as long as you adhere to its policies. If it doesn’t, then it’s possible the host may be using some locking mechanism outside your control, and then you have a real problem. If it suits your purposes then you can create a new shared GL context and use that with your own protection to ensure serial access.
If this is the same problem as you were having in January, then it would definitely be worth producing a reduction which exhibits the behaviour which you can share with us. Also knowing a little more about the host app and its plugin interface might help us to help you.April 23, 2015 at 12:18 pm #58978
All I was saying is that you actually can’t use OpenGL on a secondary thread without locks.
Direct quote from Apple’s documentation: “When you use an NSOpenGLView object with OpenGL calls that are issued from a thread other than the main one, you must set up mutex locking. ”
I’ve gone ahead and implemented these locks in the code I’m working on, so I’ll report back in a bit if I’m still getting crashes.
- You must be logged in to reply to this topic.