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.