Ok, here's the minimal code:
#include <SFML/Graphics.hpp>
sf::RenderWindow *window1, *window2;
bool isRunning = 1;
void ThreadFunc1()
{
while(isRunning)
{
window1->clear();
window1->display();
}
}
void ThreadFunc2()
{
while(isRunning)
{
window2->clear();
window2->display();
}
}
int main()
{
window1 = new sf::RenderWindow(sf::VideoMode(800, 600), "Awesome window");
window1->setActive(false);
sf::Thread thread1(ThreadFunc1);
thread1.launch();
window2 = new sf::RenderWindow(sf::VideoMode(800, 600), "Not as awesome window as the first one but still great");
window2->setActive(false);
sf::Thread thread2(ThreadFunc2);
thread2.launch();
while(isRunning)
{
sf::Event event;
while(window1->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
isRunning = 0;
}
}
while(window2->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
isRunning = 0;
}
}
printf("we're alive\n");
}
}
It creates 2 windows and a separate rendering thread for each of them while processing window events in the main thread. It works just fine if you compile and run it. However if you have some kind of recording software that captures OpenGL or D3D context running in your system, after running this test program for a few secods you get this:
(https://dl.dropboxusercontent.com/u/25635148/Error1.png)
or this:
(https://dl.dropboxusercontent.com/u/25635148/Error3.png)
but most often this:
(https://dl.dropboxusercontent.com/u/25635148/Error2.png)
When the crash happens, stack pointer always points either to window1->display() or window2->display().
The crash happens with different kinds of recording software like Bandicam, Action! and a few others when they're in OpenGL/D3D recording mode. It happens when these programs are just running and not even recording anything. The test program may run for a few seconds, sometimes it may semi-freeze for a second or two and reliably crashes after 3-10 seconds of running.
Any ideas how to work this around or reason why this happens?
I'm not sure if you know how capture software work, but what they usually do is injecting themselves into your application and grabbing back buffer directly from your application.
Now if you use multiple threads and multiple windows chances are pretty high that their injection code isn't made for this kind of scenario, I mean which game does use multiple windows to rendering from different threads? ;)
And don't forget that you're using global RenderWindows which itself can in certain cases already create issues. Plus you're not deleting the windows at the end.
Anyways I tried it with Open Broadcaster Software and yes, as soon as I start the preview the application will crash. Since I ran it in debug mode, I got some glCheck error:
An internal OpenGL call failed in Texture.cpp (526) (https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/Texture.cpp#L526) : GL_INVALID_FRAMEBUFFER_OPERATION, the object bound to FRAMEBUFFER_BINDING is not "framebuffer complete"
No idea if that is of any help.
I went ahead and made everything single threaded. This at least didn't lead to any crashes, but OBS still couldn't get an image from it and the capture instead stayed black.
#include <SFML/Graphics.hpp>
bool isRunning = 1;
int main()
{
sf::RenderWindow *window1, *window2;
window1 = new sf::RenderWindow(sf::VideoMode(800, 600), "Awesome window");
window2 = new sf::RenderWindow(sf::VideoMode(800, 600), "Not as awesome window as the first one but still great");
while(isRunning)
{
sf::Event event;
while(window1->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
isRunning = 0;
}
}
window1->clear(sf::Color::Red);
window1->display();
while(window2->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
isRunning = 0;
}
}
window2->clear(sf::Color::Blue);
window2->display();
printf("we're alive\n");
}
delete window1;
delete window2;
}
And if I render just one window, either with the multi-threaded or the single threaded code, i.e. just calling clear() and display() on one window, the OBS can capture the rendering and nothing crashes.
My conclusion: Capturing software is not made for this kind of scenario, i.e. multiple window with multiple rendering "loops".
If you really need to windows, you might want to think about splitting up the windows in two applications, maybe then the capture software will again be able to differentiate the rendering.