Welcome, Guest. Please login or register. Did you miss your activation email?

Poll

Do you prefer SFML to manage contexts implicitly, or explicitly? If you are about to vote for option 3 or 4, please do so before reading the post, thank you.

Explicitly, I want more control over how they are used.
Implicitly, I don't want to have to deal with them myself.
I've heard of them before, but what do they do and why do I need them? I want to learn.
I've never heard of these contexts before, but I am willing to learn about them.
Keep these context things away from me! I chose SFML for a reason...
I really don't care. (Please only select this option if you have read the post and given this a bit of thought.)

Author Topic: SFML Context Management  (Read 19909 times)

0 Members and 1 Guest are viewing this topic.

Hapax

  • Hero Member
  • *****
  • Posts: 3346
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: SFML Context Management
« Reply #15 on: October 03, 2014, 03:06:40 am »
The Q&A with Ixrec and Binary was massively informative. The whole thread is, really. I can't say that I understand it all though.
As Ixrec was saying, if it's more complicated that just adding an extra line or parameter to a constructor, it'll take newbies (like me) a while to grasp and the newer ones might not stay if it's too hard to get something going immediately.
Personally, I'd like to learn everything about it but I just don't think I'm that good and I know I, for one, would struggle if the interface got closer to raw OpenGL. That said, if we're hand-held through the process and the beginner tutorials are as good as they are now, anything's learnable.

Binary, I think you should transfer your brain to the internet. Come on; share it. Don't be selfish!
(you could clear out some space to learn new stuff...)
That said, I think you're on your way to doing that via this forum  ;D
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML Context Management
« Reply #16 on: October 03, 2014, 03:17:27 am »
In order to have a render target (Window or RenderTexture, for example) you must have a context bound to that target.
This is only partially true.

For GPUs that don't support framebuffer objects, SFML has to resort to emulation of offscreen framebuffers through a separate context. In that case, you would select which to render to via activation of the respective contexts.

For GPUs that do support framebuffer objects, as long as they are only used in the same thread as the window whose context was already created, they do not require their own context. Selection of where to draw to is done via the OpenGL function glBindFramebuffer. Since framebuffer objects cannot be shared between contexts, SFML would have to somehow see to it that the window's context is activated in the secondary thread in order to use the framebuffer object there. This would mean deactivating it in the main thread, and the whole issue becomes very very complex.

If the user could promise that they would not transfer sf::RenderTextures between threads, then the whole situation would become much simpler to implement, but SFML does not force this restriction on them, which is why we have the current implementation.

Every context is bound to a render target, even if to a "virtual" and useless one
If by that you mean "has a framebuffer", then yes... This is one of the things I mentioned in my original post.

Each context can only be used by one thread at a time, so you can't use multiple threads to draw to the same render target
You can use multiple threads to draw to the same render target. What people don't fully understand is that you have to manually call .setActive(false) in the previous thread before drawing from a secondary thread. There is currently no thread-to-thread communication to "inform the previous thread to relinquish its active context" automatically. This has to be done by the user. If this is not done, .setActive(true) (called internally by sfml-graphics as well) in the secondary thread would return false to notify of failure, and nothing will be drawn.

If those points are all true and if I understood the "context leaking" problem right, then the simplest and cleanest way to solve those problems would be to have an internal SFML graphical thread (like the internal audio thread) for each render target, and all drawing operations on said render targets would be performed by that thread. You can have a poll of drawing operations for the render target and have that thread go over it whenever a new operation pops up.
It's not as simple as you think, not to mention the overhead would be astronomical and simply kill performance.

Audio processing is very very different from graphics processing. What is a sample in audio processing can probably be compared to a frame in graphics processing. Since audio plays at a fixed sample rate, and you often have the data beforehand, it is common to pass a whole chunk of samples to the sound card to be played over a period of time. Since the idea behind graphics rendering is that the frame is constructed from the data you pass to the GPU, frame data isn't readily available in chunks beforehand, and even if it was, it would lag behind the true state of the application so bad that it can't even be considered real-time any longer. This is the case when you play movies, the frame data is already available beforehand, but it also isn't considered real-time rendering.

What you term as the "graphical thread" is in reality the driver. It runs in its own thread and queues operations from multiple contexts into a single command stream that is fed to the GPU. There is no reason to introduce another synchronization point that wouldn't even benefit that many people in the end. All people have to be aware of is that it really only makes sense doing graphics related stuff from a single thread. It isn't impossible to do, I do it all the time. It just takes a bit of getting used to and also requires that they acknowledge the fact that they indeed do not gain from multi-threading in this sense.

You said it yourself that multithreading is useless to gain performance on the context operations, so this would keep contexts hidden and only create contexts when neccessary. That is, assuming I understood these contexts right. If the drawing operations have useful returning values, it is always possible to block the calling thread untill the drawing thread finishes the task, and get the result back afterwards.
I don't understand much of what you said there. What I have said time and again is that multi-threading doesn't provide the benefits many people think they are getting when offloading graphics operations to separate threads. This has nothing to do with "context operations" whatever you meant by that. As soon as SFML has to go to OpenGL to get stuff done, if that is happening in a thread other than the main one, you are doing something wrong.

And if you think drawing "takes time", that is another misconception that beginners seem to have. When you tell OpenGL to "draw" stuff, what you are doing is queuing a command for it to render that stuff at a later point in time. It doesn't happen immediately. Obviously if you have multiple threads all issuing draw commands, whoever issues first will get their command executed first by the GPU, followed by the second command that got issued, all according to an absolute time scale. This is why multi-threaded OpenGL makes almost no sense in almost all cases and only serves to confuse beginners even more than necessary. Also, drawing doesn't "produce results" in terms of return values, if that's how you understand it. The only results that it produces are what you end up seeing on your monitor. OpenGL doesn't care whether it is what you expected or not. It just does what you tell it to do, and if that was successful it will not return any error which implies success. Garbage In Garbage Out.

Also, trying to reduce the number of times contexts have to be created and destroyed is beneficial for performance. Creating contexts on my machine takes something on the order of milliseconds, and if you imagine doing that 10s of times per frame, it will surely kill performance. The key is not to make sure a context exists by creating and destroying them just for single use, it is about reusing contexts that were already created prior in an intelligent manner.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Re: SFML Context Management
« Reply #17 on: October 03, 2014, 03:45:49 am »
Ok, but everything you said just confirmed that my suggestion would be great. Since graphical operations are "returnless", you can just put them on the poll, wake the drawing thread up if it is sleeping and return. It wouldn't have any delay whatsoever for the user's code, and since the operations are going to be done sequentialy anyway, you won't lose any performance (by having only one thread doing all the drawing sequentialy for each render target). You've said that it would be so slow it would cease to be realtime, but why?
« Last Edit: October 03, 2014, 03:49:38 am by Tex Killer »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: SFML Context Management
« Reply #18 on: October 03, 2014, 04:04:22 am »
@Tex Killer: just stop painting yourself into another hole (like on the OpenAL thread). If you don't believe us - then fine, but if you want to do stuff so wrong you can, we won't stop you. Having internal threads won't help performance and it also has absolutely nothing to do with this thread.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML Context Management
« Reply #19 on: October 03, 2014, 04:21:51 am »
Ok, but everything you said just confirmed that my suggestion would be great.
I would like to see a statement by statement reasoning for why you think this. It seems you didn't fully understand what I said.

Since graphical operations are "returnless", you can just put them on the poll, wake the drawing thread up if it is sleeping and return. It wouldn't have any delay whatsoever for the user's code, and since the operations are going to be done sequentialy anyway, you won't lose any performance (by having only one thread doing all the drawing sequentialy for each render target).
It is ludicrous to think that dedicating another thread just to synchronize access to the driver would help solve this problem. I don't know how much multi-threading you have done, but you do understand that you would have to take care of data synchronization yourself in this case right? Not to mention that there are also functions that don't draw stuff but query the driver for data as well. What would you do in that case? Copy the OpenGL function signatures so you can relay these data structures back and forth as well? What about selecting the right context to draw to in multi-window applications? Would you really have to pass the context to activate along with each function that you call? What benefit does that provide over merely activating the contexts in the main thread and doing all the work there? And the part that I really don't understand is: How would this solve the problem that we are already currently having?

You've said that it would be so slow it would cease to be realtime, but why?
You've taken this statement out of context. Please reread that post again if you don't understand.

SFML, and other middleware has done this a lot. They are so desperate to appeal to developers with bad practices or little understanding of the subject matter, that they end up having to hide the real problems from them. Instead of saying "don't worry, you can do what you have always been doing although it is a bad idea" why not say "you know... that is not such a good idea, why not try it like this instead"? Sure some will always complain and threaten to go to another library that keeps pampering them. But trying to keep a hold of those with objectively very very bad practices to the detriment of others willing to improve is not something I feel good about either.

I'm not saying that we need to change the way SFML does context management overnight. I'm pretty sure it is possible to keep it the way it is while dealing with some, but not all of the problems that arise. Going out of our way by introducing an additional thread just for rendering, is unheard of, and I've seen a lot over the last years.

Also, what Ixrec said should be universally true. The amount of effort required to get something done should always be proportional to the complexity of what you want done. Reducing the effort by a flat amount regardless of the complexity leads to situations like the one we have now. If the user wants to multi-thread sfml-graphics, I will tell them that I do not recommend doing it, but it is up to them what their code looks like, and if they are that desperate to do it, they can read a bit more about multi-threaded context management. If you ask me, the effort required to multi-thread properly is much much larger than the effort required to understand how contexts are used in different threads. Most of the time, unfortunately, people fail to do the former already, and we are trying to help hide the latter from them.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Re: SFML Context Management
« Reply #20 on: October 03, 2014, 07:14:03 am »
Ok, but everything you said just confirmed that my suggestion would be great.
I would like to see a statement by statement reasoning for why you think this. It seems you didn't fully understand what I said.
Ok, I'll quote your post and answer it part by part. I didn't do that before because the topic had too much text for that, and because I wasn't sure how contexts work, even after reading everything. I don't remember ever hearing anything about OpenGL contexts before reading this topic, so I am taking all of my information from here.

Since graphical operations are "returnless", you can just put them on the poll, wake the drawing thread up if it is sleeping and return. It wouldn't have any delay whatsoever for the user's code, and since the operations are going to be done sequentialy anyway, you won't lose any performance (by having only one thread doing all the drawing sequentialy for each render target).
It is ludicrous to think that dedicating another thread just to synchronize access to the driver would help solve this problem. I don't know how much multi-threading you have done, but you do understand that you would have to take care of data synchronization yourself in this case right?
What I understood from previous posts is this: OpenGL uses contexts to manage render targets, and those contexts are not "safe" for multithreading, so they have restricted each context to a single active thread. You can deactivate one thread and activate another, but you can't have two active threads on the same context, so in other words it just forces the user to do the synchronization. My suggestion is that the synchronization is done hidden inside SFML, so that the API can stay the same. The back-end particularities shouldn't have effect on SFML's public API, in my opinion (specially when we consider possible future DirectX support, for example, but lets not diverge from the topic at hand).

Not to mention that there are also functions that don't draw stuff but query the driver for data as well. What would you do in that case? Copy the OpenGL function signatures so you can relay these data structures back and forth as well?
I didn't know we had to synchronize data retrival functions as well. As I've said before, I only know this issue from what I've read here, so if I don't know all of the problems my suggestions will be flawed from the start. How does data retrieval work on OpenGL? Is it thread-safe? Does it support parallel data retrival on multiple threads? Does it use the contexts for that? In what way? I am realy clueless to this point.

What about selecting the right context to draw to in multi-window applications? Would you really have to pass the context to activate along with each function that you call? What benefit does that provide over merely activating the contexts in the main thread and doing all the work there? And the part that I really don't understand is: How would this solve the problem that we are already currently having?
You wouldn't have to pass the context, since the Window object would have its context internaly. The benefit of my suggestion would be that you wouldn't have to worry about the synchronization at all when drawing stuff, the Window's internal thread will do the "talking" with OpenGL and everything will just work. Also, we wouldn't need more contexts than the number of render targets, if my understanding of contexts is correct, but I might be wrong.

You've said that it would be so slow it would cease to be realtime, but why?
You've taken this statement out of context. Please reread that post again if you don't understand.

SFML, and other middleware has done this a lot. They are so desperate to appeal to developers with bad practices or little understanding of the subject matter, that they end up having to hide the real problems from them. Instead of saying "don't worry, you can do what you have always been doing although it is a bad idea" why not say "you know... that is not such a good idea, why not try it like this instead"? Sure some will always complain and threaten to go to another library that keeps pampering them. But trying to keep a hold of those with objectively very very bad practices to the detriment of others willing to improve is not something I feel good about either.
You say that drawing stuff on multiple threads is bad practice, but it is only bad practice if it creates unsolveable issues or if it affects resource usage significantly. Sure, you shouldn't draw from multiple threads on the same context in parallel in OpenGL, but we are talking about SFML, and as long as we can solve OpenGL's issues ourselves without affecting the performance significantly, we can choose our own way of presenting features to the user. In my opinion, the interface should only show an issue to the user if it can't be solved internaly.

I'm not saying that we need to change the way SFML does context management overnight. I'm pretty sure it is possible to keep it the way it is while dealing with some, but not all of the problems that arise. Going out of our way by introducing an additional thread just for rendering, is unheard of, and I've seen a lot over the last years.
Ok, it is unheard of, but would it work? What are the possible drawbacks? Is the number of threads limited to less than the number of possible contexts on an application? Would multiple sleeping threads (since the threads will be mostly sleeping, except when waken to draw stuff and sleep again) affect the performance of the user's thread? Would those sleeping threads compromise memory in any significant way? You have also mentioned data retrieval, and I would like to know how that is done on OpenGL (to try and adapt the "internal thread solution", if it passes the previous questions).

Also, what Ixrec said should be universally true. The amount of effort required to get something done should always be proportional to the complexity of what you want done. Reducing the effort by a flat amount regardless of the complexity leads to situations like the one we have now. If the user wants to multi-thread sfml-graphics, I will tell them that I do not recommend doing it, but it is up to them what their code looks like, and if they are that desperate to do it, they can read a bit more about multi-threaded context management. If you ask me, the effort required to multi-thread properly is much much larger than the effort required to understand how contexts are used in different threads. Most of the time, unfortunately, people fail to do the former already, and we are trying to help hide the latter from them.
So, you are suggesting that since multithreading OpenGL contexts efficiently is hard, you should just force SFML users to do it themselves and give the "OpenGL context" problem to them? I might well be underestimating the problems here (and I probably am), but until I understand the problem I won't assume it is unsolveable, so I am sorry if I am talking nonsense.
« Last Edit: October 03, 2014, 07:20:22 am by Tex Killer »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML Context Management
« Reply #21 on: October 03, 2014, 11:40:00 am »
What I understood from previous posts is this: OpenGL uses contexts to manage render targets, and those contexts are not "safe" for multithreading, so they have restricted each context to a single active thread. You can deactivate one thread and activate another, but you can't have two active threads on the same context, so in other words it just forces the user to do the synchronization.
All that is important to know, I already mentioned in the list in the original post. You can multi-thread with contexts safely, you just have to keep those constraints in mind. Instead of activating and deactivating threads, which I never talked anywhere about, you activate and deactivate contexts. Even if a thread is "inactive" whatever that means, if a context is still active on that thread, it won't be able to be activated anywhere else. You have to consider things from the context's point of view and not the thread's point of view.

And when you say that "it forces the user to do the synchronization", I have to add: It only forces them to do the synchronization if they already made the bad decision of trying to multi-thread OpenGL in the first place. Maybe this is the key. SFML users don't know how ugly the internals are that they take for granted and everything works. You don't find many OpenGL applications, either written using platform code or other libraries that end up multi-threading. The reason for this is simple: It is very very ugly. If it was hard for SFML users to do it from the beginning, I am sure they would consider better alternatives sooner in their development cycle.

My suggestion is that the synchronization is done hidden inside SFML, so that the API can stay the same.
This is the way it currently is, and if you've read what has already been posted in this thread again, you will see that this leads to problems. And before you say anything else, no, your solution will not solve any of these problems. It will merely create more of them.

The back-end particularities shouldn't have effect on SFML's public API, in my opinion (specially when we consider possible future DirectX support, for example, but lets not diverge from the topic at hand).
The aim of this discussion is to try and find a solution for the current situation. Simply saying "hide all the ugly stuff for me so that alternate renderers will look just as simple" still doesn't change the fact that that "stuff" that is hidden is problematic. And, in case people didn't know yet, SFML was designed with OpenGL in mind. I have not made many thoughts on how it would have to change to support multiple renderers, but I am pretty sure that you won't be able to recognize similarities between the new and old implementation when it gets done one day.

Please, for future posters, do not mention DirectX any more. It shouldn't even be a factor in this discussion. We are trying to fix a system that was not designed for it, and all things DirectX related can have its place in a separate thread.

I didn't know we had to synchronize data retrival functions as well. As I've said before, I only know this issue from what I've read here, so if I don't know all of the problems my suggestions will be flawed from the start. How does data retrieval work on OpenGL? Is it thread-safe? Does it support parallel data retrival on multiple threads? Does it use the contexts for that? In what way? I am realy clueless to this point.
Data retrieval isn't as complicated as you think, but that still doesn't mean you don't have to give it a bit of thought. It can have many manifestations. The most common and simple one is getting a single state value from the driver. This can be different depending on which context is active when you call the respective function. For things like taking screenshots, it is a bit more complicated. You will have to pass in a correctly sized array so that the GL can write the data you request from it into the array. This is also context dependent, and is a rather slow operation since we are reading data directly from the GPU.

If you heed what I said in the original post in regards to contexts and threads, then yes, it is thread-safe. Yes it supports parallel retrieval on multiple threads, also constrained by the same requirements. Yes it uses contexts, everything in OpenGL uses contexts, didn't you read the original post? Really... just read the original post, and especially the list, over and over again until you understand it. From what you have said so far, I highly doubt you understood even a bit of it, and it is necessary for continuing this discussion in a meaningful way.

You wouldn't have to pass the context, since the Window object would have its context internaly. The benefit of my suggestion would be that you wouldn't have to worry about the synchronization at all when drawing stuff, the Window's internal thread will do the "talking" with OpenGL and everything will just work. Also, we wouldn't need more contexts than the number of render targets, if my understanding of contexts is correct, but I might be wrong.
This is worse than I expected... Now I understand that you were aiming to have a separate "rendering thread" for each context that can be used in some way... just so you can omit having to constantly select which one to activate? There are beginners on this forum... that just start out with game development, and after not too long, even they understand that having more threads than necessary is not a good thing. I don't know where you are coming from, but if you think that resorting to creating an excessive number of threads to get anything done is a good idea, I am sorry to have to tell you that you are mistaken. The same is said to beginners as well as advanced developers: Avoid threads while you can. Unless you know exactly why they provide a benefit, you won't gain much from them.

You say that drawing stuff on multiple threads is bad practice, but it is only bad practice if it creates unsolveable issues or if it affects resource usage significantly.
If that is the case, then you must also oppose usage of smart pointers over raw pointers too right? Raw pointers don't create unsolvable issues and have better resource usage than smart pointers, and yet the universal opinion from any established C++ programmer is that you should rarely ever use raw pointers (and certainly not owning ones) in modern C++ code.

Bad practice doesn't always have to result in catastrophic results. This is the reason why it is bad practice.

A customary action, habit, or behavior; a manner or routine.

While it is legitimate, it is something the general majority recommend against, because there are known issues tied to it. In the case of context management, these issues might not be of interest to you or anyone else, but they are still there. Letting people know that there are difficulties with the way they planned to do things (even if not within their code) is the first step in helping them consider an alternative, and often superior, solution. If this has to be done through the API, then so be it. The last thing I want to hear is people blaming the API for their misinformed decisions, and "had they known earlier..." etc.

Sure, you shouldn't draw from multiple threads on the same context in parallel in OpenGL, but we are talking about SFML, and as long as we can solve OpenGL's issues ourselves without affecting the performance significantly, we can choose our own way of presenting features to the user. In my opinion, the interface should only show an issue to the user if it can't be solved internaly.
Sure... here at SFML, we like to create our own concepts that users have to embrace to use SFML efficiently. But that still doesn't change the fact that those concepts have to map to "real-world" implementations. There are still connections between the two. And as uncomfortable as it is, it is not possible to hide every single implementation detail from seeping through the API to the user. Maybe SFML users are merely using SFML as a stepping stone on their way towards more advanced graphics programming? You never know. But twisting reality just because we can isn't something we do. We simplify it, where we can. Where we can't, we have to pass it on to the user. And the whole point of this discussion is that initially, SFML thought that it could hide the complexities of multi-threaded OpenGL without causing too many problems, but over time that assumption has lost more and more weight, which is why we are in our current situation.

Ok, it is unheard of, but would it work?
You tell me... I am not going to go ahead and spend 10s maybe even 100s of hours implementing something I find problematic from the start. From reading what you have proposed, I would say, yeah, it can work, but have fun with your 2 FPS applications. Ultimately, most ideas in software development, no matter how crazy they are, can be implemented. You just have to spend a varying amount of time dealing with the effects you did not anticipate during brainstorming.

What are the possible drawbacks? Is the number of threads limited to less than the number of possible contexts on an application? Would multiple sleeping threads (since the threads will be mostly sleeping, except when waken to draw stuff and sleep again) affect the performance of the user's thread? Would those sleeping threads compromise memory in any significant way?
I've already reiterated over the drawbacks enough times in the last posts and this one. If you still don't understand them, please read them again. I assume that you are somewhat familiar with threading (and more importantly efficient multi-threading), since you often propose "solutions" to problems that involve them in some way. So can't you just draw your own conclusions? If this is not the case, i.e. you are not experienced in threading, then I highly recommend you refrain from using them in any future solutions you propose anywhere. I don't mean to be offensive, but these solutions don't necessarily make you look good...

You have also mentioned data retrieval, and I would like to know how that is done on OpenGL (to try and adapt the "internal thread solution", if it passes the previous questions).
I already mentioned this above. And instead of relying on my spending well over an hour typing a reply for you, why don't you do a bit of research on your own? ;) OpenGL isn't that hard to understand, especially if you concentrate on specific parts of the API.

So, you are suggesting that since multithreading OpenGL contexts efficiently is hard, you should just force SFML users to do it themselves and give the "OpenGL context" problem to them? I might well be underestimating the problems here (and I probably am), but until I understand the problem I won't assume it is unsolveable, so I am sorry if I am talking nonsense.
What you misunderstand, is that the majority of users probably won't be affected code-wise by any changes. They already assume that performing all OpenGL related stuff within the main thread is the way to go, and like I said, there is no reason to annoy these users. It is the ones who already resort to bad practice that will have to potentially make small adjustments to their code. Maybe this is a signal to them that what they are doing is not a good idea. If this motivates them to change the way they think of using sfml-graphics to single threaded, then I am nothing but happy.

Merely dismissing this discussion as "passing the OpenGL problem on to the user" is not correct in any way. We strive to keep it as simple to write code as it currently is, but if we notice that some parts of the API allow or even motivate people to engage in bad practices, then that is something we should consider changing for the better.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Tex Killer

  • Full Member
  • ***
  • Posts: 242
    • View Profile
Re: SFML Context Management
« Reply #22 on: October 03, 2014, 09:08:49 pm »
What I understood from previous posts is this: OpenGL uses contexts to manage render targets, and those contexts are not "safe" for multithreading, so they have restricted each context to a single active thread. You can deactivate one thread and activate another, but you can't have two active threads on the same context, so in other words it just forces the user to do the synchronization.
All that is important to know, I already mentioned in the list in the original post. You can multi-thread with contexts safely, you just have to keep those constraints in mind. Instead of activating and deactivating threads, which I never talked anywhere about, you activate and deactivate contexts. Even if a thread is "inactive" whatever that means, if a context is still active on that thread, it won't be able to be activated anywhere else. You have to consider things from the context's point of view and not the thread's point of view.
I meant to say that you can deactivate a context on a thread and activate it on another thread, but you can't activate it on multiple threads at the same time. I though it was obvious, but sorry for the bad wording.

My suggestion is that the synchronization is done hidden inside SFML, so that the API can stay the same.
This is the way it currently is, and if you've read what has already been posted in this thread again, you will see that this leads to problems. And before you say anything else, no, your solution will not solve any of these problems. It will merely create more of them.
I know it is already like this, that is why I've said that the API would stay the same. What I am discussing here is possible implementation changes that could solve the said problems without affecting the API.

I didn't know we had to synchronize data retrival functions as well. As I've said before, I only know this issue from what I've read here, so if I don't know all of the problems my suggestions will be flawed from the start. How does data retrieval work on OpenGL? Is it thread-safe? Does it support parallel data retrival on multiple threads? Does it use the contexts for that? In what way? I am realy clueless to this point.
Data retrieval isn't as complicated as you think, but that still doesn't mean you don't have to give it a bit of thought. It can have many manifestations. The most common and simple one is getting a single state value from the driver. This can be different depending on which context is active when you call the respective function. For things like taking screenshots, it is a bit more complicated. You will have to pass in a correctly sized array so that the GL can write the data you request from it into the array. This is also context dependent, and is a rather slow operation since we are reading data directly from the GPU.
Ok, the data depends on the active context, so we have to synchronize data retrieval as well. That could be done by blocking the calling thread until the "drawing thread" retrieves the data, and sharing the return value between threads, but I agree that it is not as clean as it could be.

If you heed what I said in the original post in regards to contexts and threads, then yes, it is thread-safe. Yes it supports parallel retrieval on multiple threads, also constrained by the same requirements. Yes it uses contexts, everything in OpenGL uses contexts, didn't you read the original post?
If it uses the active context, it can't be used in parallel. Or am I missunderstanding something? If you can't have two different threads retrieving data from the same context at the same time, I wouldn't consider it thread-safe, but that might be bad wording, so I am sorry for the missunderstanding. In the end, we have to synchronize drawing and data retrieval functions to the same context ourselves.

This is worse than I expected... Now I understand that you were aiming to have a separate "rendering thread" for each context that can be used in some way... just so you can omit having to constantly select which one to activate? There are beginners on this forum... that just start out with game development, and after not too long, even they understand that having more threads than necessary is not a good thing. I don't know where you are coming from, but if you think that resorting to creating an excessive number of threads to get anything done is a good idea, I am sorry to have to tell you that you are mistaken. The same is said to beginners as well as advanced developers: Avoid threads while you can. Unless you know exactly why they provide a benefit, you won't gain much from them.
Ok then, lets avoid multiple meaningless threads. I'll suggest another solution at the end of the post that doesn't create any aditional thread.

If that is the case, then you must also oppose usage of smart pointers over raw pointers too right? Raw pointers don't create unsolvable issues and have better resource usage than smart pointers, and yet the universal opinion from any established C++ programmer is that you should rarely ever use raw pointers (and certainly not owning ones) in modern C++ code.
Using raw pointers directly is much harder than using smart pointer. It is bad practice because unless you pay attention to all of the allocation and freeing of memory, you will create serious problems. Sure, if you don't pay attention to the synchronization of OpenGL operations it will create serious problems, but as long as we manage to take care of those problems internally, it will cease to be bad practice to the final user. If SFML used raw pointers on some internal sections of code, for example, but used them correctly, the user code wouldn't be affected by it in the least. The user wouldn't even see the pointers.

Ok, it is unheard of, but would it work?
You tell me... I am not going to go ahead and spend 10s maybe even 100s of hours implementing something I find problematic from the start. From reading what you have proposed, I would say, yeah, it can work, but have fun with your 2 FPS applications. Ultimately, most ideas in software development, no matter how crazy they are, can be implemented. You just have to spend a varying amount of time dealing with the effects you did not anticipate during brainstorming.
I still fail to see the reason for the drop in performance. Sleeping threads shouldn't affect the performance of the active threads. Anyway, I'll suggest another solution at the end of this post, please take a look.

What are the possible drawbacks? Is the number of threads limited to less than the number of possible contexts on an application? Would multiple sleeping threads (since the threads will be mostly sleeping, except when waken to draw stuff and sleep again) affect the performance of the user's thread? Would those sleeping threads compromise memory in any significant way?
I've already reiterated over the drawbacks enough times in the last posts and this one. If you still don't understand them, please read them again. I assume that you are somewhat familiar with threading (and more importantly efficient multi-threading), since you often propose "solutions" to problems that involve them in some way. So can't you just draw your own conclusions? If this is not the case, i.e. you are not experienced in threading, then I highly recommend you refrain from using them in any future solutions you propose anywhere. I don't mean to be offensive, but these solutions don't necessarily make you look good...
From what I did understand from your previous posts, the main drawback was that SFML created a lot of useless contexts so that every operation performs on a different context and we don't have to synchronize anything. I might have missunderstood the issues, but my suggestion was made considering this scenario. Please elucidate me if I am mistaken, but after reading the first post of the thread again this is still what I understood.



Ok, so I agree that creating a dedicated thread for each render target and having the context active on that thread might not be a very clean solution. An alternative solution would be to always deactivate contexts after each OpenGL operation, and block threads that want to do OpenGL operations until the previous one stops.
I am not very familiar to C++ mutexes and synchronization, but on Java the code would be something like this for every OpenGL operation:

synchronize (context) {
    // activate context
    // perform OpenGL operation
    // deactivate context
}
 

I assume it would be similar on C++. That way the context will only be active during the operation, and multiple threads trying to use the same context in parallel would be executed one at a time. What I don't know is: does activation and deactivation of contexts take much time, or is it instantaneous? This solution would be bad if activating and deactivating contexts multiple times would lead to performance issues, but if it is as trivial as changing one state, it won't matter much.



Another possible variant of the dedicated internal threads suggestion would be to have only one internal thread, and have it doing the OpenGL operations for all of the contexts. If I understood what you've said on the first post, we might gain some performance if driver operations are issued in parallel to different contexts, so this suggestion would remove this possible performance gain, but you make it sound like driver operations are so fast that the gain is trivial. If that is the case, then this solution will be viable.
« Last Edit: October 03, 2014, 11:07:30 pm by Tex Killer »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML Context Management
« Reply #23 on: October 04, 2014, 02:18:54 am »
That way the context will only be active during the operation, and multiple threads trying to use the same context in parallel would be executed one at a time. What I don't know is: does activation and deactivation of contexts take much time, or is it instantaneous? This solution would be bad if activating and deactivating contexts multiple times would lead to performance issues, but if it is as trivial as changing one state, it won't matter much.
This was also a solution I presented to the other team members a while ago. At first glance, it seems like something that might actually work and isn't too complex to implement, but the devil is in the details. I was already working on a prototype of such an implementation, but switched to solving other issues a while ago before it was finished. I guess I could finish it off now and see what it performs like. The performance of these things, and if the drivers play along, is always hard to estimate solely based on the initial design. Often, reality isn't as clean as what the API documentation has you believe. Even when it is finished and seems to work, extensive tests have to be conducted on multiple systems before even considering it for inclusion into SFML.

Another possible variant of the dedicated internal threads suggestion would be to have only one internal thread, and have it doing the OpenGL operations for all of the contexts. If I understood what you've said on the first post, we might gain some performance if driver operations are issued in parallel to different contexts, so this suggestion would remove this possible performance gain, but you make it sound like driver operations are so fast that the gain is trivial. If that is the case, then this solution will be viable.
Any time a worker thread does nothing but execute stuff that could have been done in the invoker thread while blocking the invoker thread, you end up with serial execution. This defeats the whole purpose of multi-threading. The fact that contexts can't arbitrarily be passed between threads without some non-trivial synchronization routines does not mean that we keep it in a worker thread just so we don't have to perform those routines.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: SFML Context Management
« Reply #24 on: October 04, 2014, 06:24:11 pm »
Personnaly I've choosen SFML to go faster, if I had to manage those contexts explicitly, it would take a lot of time.

And this is the real strength of SFML.

Moreover, the context creation is different depending on the plateform and the number of plateforms are dangerously increasing, the drivers too and now we even have opengl and gles which use differents functions.

I really don't want to have to deal with that.

I know I'm probably not the better one to discuss about this, I've never used context explicitly so..., but, What'll happen for beginners like me ?

Even for a rendertexture I was not able to deal with multiple contexts with the others multi media librairies, this is why I've choosen SFML for my projects, and it's also because SFML is written in c++ and not in C.  (It's easier for enum when handling events with the automatic typedef)

You should use RAII, you have a bunch of memory leaks, if you don't want to use c++14 you can at least make your own classes for resource management like I does : http://lolilolightdevblog.wordpress.com/le-module-core-partie-3/
The article is in French.

PS : One day I've also tried to display something on an embedded system by creating render context explicitly with EGL and GLES, it was a nightmare. :X

PS 2 : Thread management is not

« Last Edit: October 04, 2014, 06:42:08 pm by Lolilolight »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: SFML Context Management
« Reply #25 on: October 04, 2014, 07:45:28 pm »
Lolilolight, if you don't read the thread then don't bother posting. This has nothing to do with requiring users to write platform specific code or do anything complex. On top of that, why are you mentioning RAII and memory leaks? Once again it has nothing to do with the thread. If you have nothing constructive to say it is best to say nothing at all.
« Last Edit: October 04, 2014, 07:51:57 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Juhani

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: SFML Context Management
« Reply #26 on: October 07, 2014, 01:48:24 pm »
Personally I don't care how chaotic context management gets with threads, for multithreading isn't for beginners anyway. IMHO context management should be simplest for a single thread.

With these opinions, which option should I vote?

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML Context Management
« Reply #27 on: October 07, 2014, 01:54:52 pm »
Personally I don't care how chaotic context management gets with threads, for multithreading isn't for beginners anyway. IMHO context management should be simplest for a single thread.

With these opinions, which option should I vote?
Since you seem to value the simplicity of single threaded context management more, implicit context management.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Juhani

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: SFML Context Management
« Reply #28 on: October 07, 2014, 02:52:58 pm »
Ok so I voted it, but for a clarification, it doesn't mean that I would like to keep the current system where SFML creates extraneous contexts even for a simple single-threaded app, just to pamper multithreaders, wherefore I also said that I don't care how painful context management becomes to them. SFML shouldn't create more contexts than what is needed in a single-threaded app, and multithreaders can handle contexts manually.