Forum de la communauté SFML

Aide => Graphique => Discussion démarrée par: Eho le Juin 29, 2014, 02:16:58 pm

Titre: [Résolu] Créer une sf::Texture dans un std::thread
Posté par: Eho le Juin 29, 2014, 02:16:58 pm
Bonjour

En cherchant à faire de la sérialisation bête et méchante, j'ai voulu créer une sf::Texture dans un thread (std::thread).

J'obtiens l'erreur suivante (Debian GNU/Linux, SFML 2.1)
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
main_sfml: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Abandon

J'ai suivi ce que le message d'erreur suggére (cela corrige bien l'erreur) mais je ne souhaite pas avoir une solution pour X11 uniquement.

J'ai placé un mutex pour créer la texture et le rendu d'une frame :
// g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp -lsfml-window -lsfml-graphics -lsfml-system main_sfml.cpp -o main_sfml && ./main_sfml
// g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic -fopenmp -lsfml-window -lsfml-graphics -lsfml-system main_sfml.cpp -o main_sfml && ./main_sfml


#include <vector>
#include <thread>
#include <mutex>

#include <SFML/Graphics.hpp>

//#include <X11/Xlib.h>


int main()
{
        //XInitThreads();
       
        sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
       
        sf::Image image; image.create(200, 200, sf::Color::White);
       
        std::vector<sf::Sprite> sprites;
       
        std::mutex mutex;
       
        std::thread t
        (
                [&]() -> void
                {
                        std::this_thread::sleep_for(std::chrono::seconds(1));
                       
                        mutex.lock();
                        sf::Texture texture_thread;
                        mutex.unlock();
                       
                        texture_thread.loadFromImage(image);
                       
                        sprites.emplace_back(texture_thread);
                }
        );
       
        while (window.isOpen())
        {
                mutex.lock();
               
                {
                        sf::Event event;
                       
                        while (window.pollEvent(event))
                        {
                                if (event.type == sf::Event::Closed) { window.close(); }
                        }
                }
               
                window.clear();
               
                for (auto const & sprite : sprites)
                {
                        window.draw(sprite);
                }
               
                window.display();
               
                mutex.unlock();
        }
       
        t.join();
       
        return 0;
}
 

Est-ce une bonne solution (je n'ai pas encore testé sous Windows et OS X) ?
Qu'elles sont les autres solutions possibles (à part «ne pas utiliser de thread» et «créer les textures à l'avance») ?

Merci d'avance.
Titre: Re : Créer une sf::Texture dans un std::thread
Posté par: Laurent le Juin 29, 2014, 08:42:03 pm
Ton mutex ne sert strictement à rien. La seule bonne solution est d'appeler XInitThreads, puisque c'est un problème propre à X.
Titre: Re : Créer une sf::Texture dans un std::thread
Posté par: Eho le Juin 29, 2014, 10:28:42 pm
Pourtant avec le mutex, le problème n'apparaît pas, même si je mets ce code dans le thread (compilé en -O0)
while (1)
{
        mutex.lock();
        sf::Texture texture_thread;
        mutex.unlock();
}

Si c'est un problème uniquement lié à X11, je vais appeler la fonction XInitThreads(); sur cette plate-forme.

Merci :)
Titre: Re : [Résolu] Créer une sf::Texture dans un std::thread
Posté par: Laurent le Juin 30, 2014, 07:33:26 am
C'est normal. Puisque tu bloques tout ce qui se trouve dans le thread principal avec le mutex, tu annules la quasi totalité du parallèlisme et donc c'est comme si tu n'avais pas de thread.