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

Author Topic: Rendering in multithread cause crash. (On linux)  (Read 10104 times)

0 Members and 1 Guest are viewing this topic.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Rendering in multithread cause crash. (On linux)
« on: January 14, 2015, 05:56:11 pm »
Hi, I've a very low FPS (15 FPS) in my project because the CPU is waiting after the GPU. :/

So, I want to render the scene in another thread because my scene is very complex.

The main purpose is to make my games more realistic. (Shadow, light, disfraction and refraction, etc...)

Most of all I've to apply the shaders in a specific ordre to handle the opacity.

So, I can't draw everything with a single draw call.

I've seen on your tutorials that it's possible to use a thread with SFML to draw the scene.

So, I've tried this with a minimal code. (No need to draw anything to repoduce the crash)
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
void renderingThread(sf::RenderWindow* window)
{
    // the rendering loop
    while (window->isOpen())
    {
        window->clear();
        window->display();
    }
}

int main (int argv, char* argc[]) {
    //XInitThreads();
     // create the window (remember: it's safer to create it in the main thread due to OS limitations)
    sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL");

    // deactivate its OpenGL context
    window.setActive(false);

    // launch the rendering thread
    sf::Thread thread(&renderingThread, &window);
    thread.launch();
    // the event/logic/whatever loop
    while (window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }
    }
    return 0;
}
 

Here is what it shows in the terminal :

Code: [Select]
[xcb] Unknow request in queue while dequeuing
[xcb]Most likely this is a multi-threaded client and XInitThreads has not been
called.
[xcb]Abording, sorry about that.
ODFAEG-DEMO: ../../src/xcb_io.c;179: dequeue_pending_request: Assertion '!xcb_xlib_unknown_req_in_deq' failed.
Aborded (core dumped)
Process returned 134 (0x86) execution time : 0.293 s
Press ENTER to continue.

I've tried to make what it says : calling XInitThreads at the frist line in the main but it doesn't solve the problem.

Is there another library than Xlib which support multi-threading with GUI on linux ?

I've heard about xcb but, I don't know it very well.

PS : I've also tried to use std::thread instead of sf::Thread but it still doesn't solve the problem.

Thanks for your help.
« Last Edit: January 14, 2015, 06:01:14 pm by Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Rendering in multithread cause crash. (On linux)
« Reply #1 on: January 14, 2015, 07:30:18 pm »
Quote
I've tried to make what it says : calling XInitThreads at the frist line in the main but it doesn't solve the problem.
The error message must be different if you call XInitThreads. So it most likely solves this particular problem, but you may have another one.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #2 on: January 14, 2015, 08:11:54 pm »
I've found the problem with the tutorial, so, I've corrected it.

#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
sf::Mutex globalMutex;
void renderingThread(sf::RenderWindow* window)
{

    // the rendering loop
    while (window->isOpen())
    {
        globalMutex.lock();
        window->clear();
        window->display();
        globalMutex.unlock();
    }

}

int main (int argv, char* argc[]) {    
    sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL");
    // deactivate its OpenGL context
    window.setActive(false);

    // launch the rendering thread
    sf::Thread thread(&renderingThread, &window);
    thread.launch();
    // the event/logic/whatever loop
    while (window.isOpen())
    {
        sf::Event event;
        globalMutex.lock();
        while(window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }
        globalMutex.unlock();
    }
    thread.wait();
    return 0;  
}
 

Just a mutex was forgotten.

But Mutexes are slow so I'll have to use a lock-free container instead.

« Last Edit: January 14, 2015, 08:16:02 pm by Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Rendering in multithread cause crash. (On linux)
« Reply #3 on: January 14, 2015, 08:29:55 pm »
By using a mutex this way, you're canceling the parallelism and end up with something similar to a single threaded application... so of course there's no problem anymore.

Please show your call stack / error output with the call to XInitThreads added to your code.

Quote
But Mutexes are slow so I'll have to use a lock-free container instead.
You have no idea what you're talking about, right?
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #4 on: January 14, 2015, 09:33:16 pm »
Hi!

Here is the callstack :

Code: [Select]
#0 0x7ffff6233cc9 __GI_raise(sig=sig@entry=6) (../nptl/sysdeps/unix/sysv/linux/raise.c:56)
#1 0x7ffff62370d8 __GI_abort() (abort.c:89)
#2 0x7ffff622cb86 __assert_fail_base(fmt=0x7ffff637e3d0 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x7ffff5596390 "!xcb_xlib_threads_sequence_lost", file=file@entry=0x7ffff55961db "../../src/xcb_io.c", line=line@entry=274, function=function@entry=0x7ffff5596696 "poll_for_event") (assert.c:92)
#3 0x7ffff622cc32 __GI___assert_fail(assertion=0x7ffff5596390 "!xcb_xlib_threads_sequence_lost", file=0x7ffff55961db "../../src/xcb_io.c", line=274, function=0x7ffff5596696 "poll_for_event") (assert.c:101)
#4 0x7ffff5526c69 ??() (/usr/lib/x86_64-linux-gnu/libX11.so.6:??)
#5 0x7ffff5526cfc ??() (/usr/lib/x86_64-linux-gnu/libX11.so.6:??)
#6 0x7ffff5526fcd _XEventsQueued() (/usr/lib/x86_64-linux-gnu/libX11.so.6:??)
#7 0x7ffff55046bd XCheckIfEvent() (/usr/lib/x86_64-linux-gnu/libX11.so.6:??)
#8 0x7ffff773ba6a sf::priv::WindowImplX11::processEvents() () (/usr/lib/x86_64-linux-gnu/libsfml-window.so.2.2.0:??)
#9 0x7ffff773725e sf::priv::WindowImpl::popEvent(sf::Event&, bool) () (/usr/lib/x86_64-linux-gnu/libsfml-window.so.2.2.0:??)
#10 0x7ffff7736733 sf::Window::pollEvent(sf::Event&) () (/usr/lib/x86_64-linux-gnu/libsfml-window.so.2.2.0:??)
#11 0x431c86 main () (??:??)

Even if I call XInitThread the message remains the same.

With mutexes this is very slow, for processing events, the window is closing one year after I click on the button. :/

It's still worth than a single threaded appli.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Rendering in multithread cause crash. (On linux)
« Reply #5 on: January 14, 2015, 10:21:31 pm »
Quote
Even if I call XInitThread the message remains the same.
The message that XInitThread is not called? Doesn't make sense, since it is called now.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #6 on: January 14, 2015, 10:29:40 pm »
Quote
The message that XInitThread is not called? Doesn't make sense, since it is called now.

Yes, I really don't understand. :/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Rendering in multithread cause crash. (On linux)
« Reply #7 on: January 14, 2015, 10:37:02 pm »
Can you show the exact code that produces the error (with the call to XInitThreads), and give as much details as possible about your environment and version of SFML?
Laurent Gomila - SFML developer

Suslik

  • Newbie
  • *
  • Posts: 33
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #8 on: January 15, 2015, 01:29:08 am »
With mutexes this is very slow, for processing events, the window is closing one year after I click on the button. :/
Rofl when they say something like "mutexes and other syncronization primitives are generally slow" it should be read as "every operation may take up to a hundred microseconds" and it may become a problem if there's millions of syncronizations like that are occuring every second. Apparently what you see is some kind of a deadlock, not mutexes being slow.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #9 on: January 15, 2015, 09:25:15 am »
This is really strange :

I've created another window to manage events, preventing that both threads have access to the same adress into the memory at the same time. (The adress of the render window)
Because if I don't protect the window with mutexes (this is the case here) it can happen.

But it doesn't solve the problem, the problem seems to be in the pollEvent function, here is what it's displaying :
Code: [Select]
[xcb]../../src/xcb_io.x:274 : poll_for_event: Assertion failed 'xcb_xlib_threads_sequence_lost' failed.

Here is the code (with XInitThread) :

#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
void renderingThread(sf::RenderWindow* window)
{

    // the rendering loop
    while (window->isOpen())
    {        
        window->clear();
        //I want to make my draw calls here so the cpu is not waiting after the GPU.
        window->display();      
    }

}

int main (int argv, char* argc[]) {
    XInitThreads();
    // create the window (remember: it's safer to create it in the main thread due to OS limitations)
    sf::RenderWindow window(sf::VideoMode(800, 600), "OpenGL");
    sf::RenderWindow glassPane(sf::VideoMode(800, 600), "Glass Pain");
    glassPane.setVisible(false);
    // deactivate its OpenGL context
    window.setActive(false);

    // launch the rendering thread
    sf::Thread thread(&renderingThread, &window);
    thread.launch();
    // the event/logic/whatever loop
    while (glassPane.isOpen())
    {
        sf::Event event;        
        while(glassPane.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                glassPane.close();
                window.close();
            }
        }        
    }
    thread.wait();
    return 0;
}
 

The other strange thing is that the second window remains visible. :/ (setVisible doesn't work)

My environment is ubuntu 14.04 LTS 64 bits.

My SFML version is 2.2.

The lasted ones.

SFML doesn't seems to be made for more complexe appli, maybe should I test this with SDL ?

I know that SDL doesn't manage events throught the window but..., I'm still not sure if it'll work, most of all I've to encapsulate everything into classes. :/
« Last Edit: January 15, 2015, 09:28:22 am by Lolilolight »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Rendering in multithread cause crash. (On linux)
« Reply #10 on: January 15, 2015, 10:16:00 am »
Is that really the whole code? Because XInitThreads() requires to include <X11/Xlib.h>.

You can also try the latest sources, where XLib has been replaced by XCB.
Laurent Gomila - SFML developer

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #11 on: January 15, 2015, 10:16:34 am »
Re,
Sorry I've forgotten to include X11.
I've tested with SDL and, it works perfectly :

#include <SDL2/SDL.h>
bool end = false;
void renderingThread(SDL_Window* mainWindow)
{
    SDL_GLContext mainGlContext = SDL_GL_CreateContext(mainWindow);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
    // Double Buffer
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_MakeCurrent(mainWindow, mainGlContext);
    SDL_Renderer* renderer = SDL_CreateRenderer(mainWindow, -1, 0);
    // Select the color for drawing. It is set to red here.
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
    // the rendering loop
    while (!end)
    {

        // Clear the entire screen to our selected color.
        SDL_RenderClear(renderer);
        // Up until now everything was drawn behind the scenes.
        // This will show the new, red contents of the window.
        SDL_RenderPresent(renderer);
    }
    SDL_GL_DeleteContext(mainGlContext);
}

int main (int argv, char* argc[]) {
    if (SDL_Init(SDL_INIT_VIDEO) != 0 )
    {
        fprintf(stdout,"Échec de l'initialisation de la SDL (%s)\n",SDL_GetError());
        return -1;
    }
    SDL_Window* mainWindow = SDL_CreateWindow("Ma première application SDL2",SDL_WINDOWPOS_UNDEFINED,
                                                                  SDL_WINDOWPOS_UNDEFINED,
                                                                  640,
                                                                  480,
                                                                  SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    SDL_GL_SwapWindow(mainWindow);
    std::thread thethread(&renderingThread, mainWindow);
    SDL_Event event;
    while(!end) {
        SDL_PollEvent(&event);
        if(event.window.event == SDL_WINDOWEVENT_CLOSE) {
          end = true;
        }
    }
    thethread.join();
    SDL_DestroyWindow(mainWindow);
    SDL_Quit();
    return 0;
 

So I guess the problem is in your implementation. (SDL2 is using xlib)
And I guess that I should also use SDL2 in my project, this library seems to be very interesting, this is exactly the same than SFML but in C, I guess I'll just have to encapsulate everything into classes. (I hope)

Ok I'll try the last sources.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #12 on: January 15, 2015, 10:21:51 am »
Quote
Rendering does not get faster just because you move stuff into another thread. Only one thread can own the context at a time for writing to, so there's zero benefit.

And only one thread own the context here. (the rendering thread)

Because I create the context in the rendering thread, and than I update the game logic in another thread, so, the CPU is not waiting after the GPU to update its logic.

I'm really doubtfull about the knowledge of the SFML users. :/

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: Rendering in multithread cause crash. (On linux)
« Reply #13 on: January 15, 2015, 10:27:27 am »
Rendering has to wait for the updated world's state anyway. It's not like you have 2 completely isolated running threads.. In the end, the time you save is the event polling, that's it.

Lolilolight

  • Hero Member
  • *****
  • Posts: 1232
    • View Profile
Re: Rendering in multithread cause crash. (On linux)
« Reply #14 on: January 15, 2015, 10:49:31 am »
Quote
Rendering has to wait for the updated world's state anyway.

No, not if you are using doule buffering, the main thread'll display the previous updated frame, and when the next frame is updated in the rendering thread, it calls the display method of the render texture of the render component and it'll also be updated in the main thread which display the render component on the render window.

I use an entity-component based design to handle this.
« Last Edit: January 15, 2015, 10:51:28 am by Lolilolight »