Multi-threading in OpenGL ES from Cocos2D iOS App

test… I just spent 10 minutes writing a post and when i submitted it, it said I used URLS or words that were not allowed and I lost everything!!! So I am testing to make sure I can write anything at all before I try again.

ARRGH!!!

Ouch. Sorry you lost your post. So the forum didn’t give you an option to copy/paste your text off into a file? If so, that’s annoying.

That said, I haven’t heard anyone else reporting that they couldn’t post but didn’t use any URLs. So could it be that your post matched some disallowed words?

Hope you decide to rewrite your post. This time though, you might be sure to save a copy of your text into a file before you hit post, just in case something goes wrong.

[QUOTE=Dark Photon;1284088]Ouch. Sorry you lost your post. So the forum didn’t give you an option to copy/paste your text off into a file? If so, that’s annoying.

That said, I haven’t heard anyone else reporting that they couldn’t post but didn’t use any URLs. So could it be that your post matched some disallowed words?

Hope you decide to rewrite your post. This time though, you might be sure to save a copy of your text into a file before you hit post, just in case something goes wrong.[/QUOTE]

Hi. Yeah I re-wrote it (in a text editor this time), but wasn’t able to post it either. I didn’t realize I could attach a file… So, ok I am attaching my question here as a text file. Perhaps someone here can use it as a means to debug why the site wouldn’t accept it. It has code snippets in it, that’s the only thing I can imagine it got confused that some code was a url or something, despite it being within the CODE tags…

Anyway my question is about multi-threading/multi-contexts in OpenGL ES from within the framework of a Cocos2D iOS application.

Thank you for any help.

0x0502 is GL_INVALID_OPERATION, which typically means that all of the parameters are valid in themselves (invalid parameters result in GL_INVALID_ENUM or GL_INVALID_VALUE) but some aspect of the state isn’t valid for the current operation.

First, check that you aren’t inadvertently using the same context in more than one thread.

Try adding CHECK_GL_ERROR_DEBUG() in more places, so that you can determine exactly which function is generating the error.

I can’t really help much beyond that, as I’m not familiar with either iOS or ObjectiveC.

Gah!! This forum did it again where it rejected my reply and I am having to retype it all over again!!! … I need to get in the habit of always writing in a text editor.

Anyway— What I said was, I did more debug calls and I found that the errors are all getting thrown in the three calls to glVertexAttribPointer()

I don’t know off the top of my head any way to really know if two threads are accidentally using the same context. My code certainly is not… And from looking through Cocos2d’s codebase, I see that there is only one place where an auxiliary context is created and that is a method for asynchronously loading textures, which I made certain my code is not making use of as that seemed like potentially a way to end up with the wrong context.

I also noticed that when Cocos2d sets itself up, it has an option to allocate the EAGLContext object with a share group, but when I inspected this, there is no share group. Could that be a solution to my problem? Should I have a share group?

Hmm, well I guess that’s not the problem… I tried newing up a sharegroup and passing it in, those errors still happen.

For OpenGL ES 3.0 (and desktop OpenGL), the error can be generated if no buffer is bound to the GL_ARRAY_BUFFER target, or if the type parameter is one of the packed formats but the number of fields doesn’t much the size parameter.

For OpenGL ES 2.0, glVertexAttribPointer() shouldn’t generate GL_INVALID_OPERATION for any reason. Client-side vertex arrays are supported (i.e. it’s not necessary to have an array buffer bound) and packed formats don’t exist.

[QUOTE=patrick99e99;1284092]
I also noticed that when Cocos2d sets itself up, it has an option to allocate the EAGLContext object with a share group, but when I inspected this, there is no share group. Could that be a solution to my problem? Should I have a share group?[/QUOTE]
If your contexts don’t share data, any textures, buffers, programs, etc are specific to the context which was current when they were created, so any objects which are common to multiple contexts need to be created separately for each context.

[QUOTE=GClements;1284095]For OpenGL ES 3.0 (and desktop OpenGL), the error can be generated if no buffer is bound to the GL_ARRAY_BUFFER target, or if the type parameter is one of the packed formats but the number of fields doesn’t much the size parameter.

For OpenGL ES 2.0, glVertexAttribPointer() shouldn’t generate GL_INVALID_OPERATION for any reason. Client-side vertex arrays are supported (i.e. it’s not necessary to have an array buffer bound) and packed formats don’t exist.[/QUOTE]

Hmm… Well my version of Cocos2d is using 2.0…

I’m a little confused by what you’re saying here. Cocos2d has a texture cache singleton object which holds all the textures in memory (just with a basic key value store)— so anytime you create a sprite, it will automatically store that texture in the cache, and access it from there the next to you attempt to create that same sprite. That said, both of my threads / contexts are using textures from there (and I can think of at least two textures that are being used on the screen at the same time from both contexts). That is the problem?

To be honest, I think that you should be asking in a Cocos2D forum. It sounds like Cocos2D does some kind of context management itself (there’s no way to have a shared texture cache otherwise, as textures which are created using one context only exist in that context and in contexts which share data with it).

Sigh… Yeah I did that already. No one was able to help me. I just got a response saying cocos isn’t meant to be multi-threaded, which to me is an unacceptable answer.

You can consider it unacceptable all you like, but if it is true, then it is true. If Cocos2D really isn’t meant to be threaded, then there is nothing you can do about that. It certainly would not be the first or the last layered graphics system that couldn’t handle being accessed from multiple threads simultaneously. Indeed, that singleton object you mentioned is a pretty good indicator that the API was not designed around being multi-threading capable.

You shouldn’t turn away from an answer just because you don’t like it. Your choices now are to abandon your threading approach or abandon Cocos2D. It simply is not the right tool for what you’re trying to do.

It doesn’t matter whether it’s “acceptable”. If cocos does its own context management and it isn’t compatible with multi-threading, then you’ll need to choose one or the other.

just a short question:

why dont you use only the main thread to render stuff, for everything else (loading textures, physics, etc.) you can use multi-threading
you dont need multi-threading for rendering (thats my opinion)
if memory is not much limited, you dont even need multi-threading for resource loading, you could just preload everything

[QUOTE=Alfonse Reinheart;1284113]You can consider it unacceptable all you like, but if it is true, then it is true. If Cocos2D really isn’t meant to be threaded, then there is nothing you can do about that. It certainly would not be the first or the last layered graphics system that couldn’t handle being accessed from multiple threads simultaneously. Indeed, that singleton object you mentioned is a pretty good indicator that the API was not designed around being multi-threading capable.

You shouldn’t turn away from an answer just because you don’t like it. Your choices now are to abandon your threading approach or abandon Cocos2D. It simply is not the right tool for what you’re trying to do.[/QUOTE]

Argh… I took some time to think about all this, and yeah you’re right. So, I changed it so that my spinner is spinning while new textures are loading (thus nothing is drawing so no errors happen), then prior to object instantiation hiding the spinner so it doesn’t freeze and look dumb. Theres about a 1/2 delay before the level preview actually appears, and I also disabled touches on the menu during this time so it’s not interactable / scrollable while loading/instantiating. That was something else that caused the user experience to feel like things are choppy lagging… So, it now has the illusion of no real performance hiccups, which I think is better than a bunch of openGL errors and weird flickering on the screen.

Thank you for the advice / guidance.