Pages: 1
Bonjour,
Je dévellope un petit jeu utilisant irrlicht. J'utilisais la version 1.4 et tout fonctionnait très bien. J'ai voulu testé la version 1.4.1 mais j'obtient une erreur de segmentation. J'utilise pourtant le même code.
L'erreur a lieu lors de l'appel de
Après quelque tests j'ai remarque que cette fonction fonctionnait si la boucle d'affichage se trouvait dans le même thread que l'initialisation. Dans mon cas, la boucle d'affichage se trouve dans un second thread.
Voici mon initialisation :
GraphicsEngine::GraphicsEngine(Game *g):Engine(g) { #ifdef DEBUG std::cout<<"GraphicsEngine : new"<<std::endl; #endif sg = new SceneGraph(this); parent->GetWorld()->SetGraphicsWorld(sg); receiver = new EventReceiver(); //idevice = irr::createDevice(irr::video::EDT_OPENGL, irr::core::dimension2d<irr::s32>(800, 600), 32, false, false, false); idevice = irr::createDevice(irr::video::EDT_OPENGL, irr::core::dimension2d<irr::s32>(800, 600), 32, false, false, false,receiver); driver = idevice->getVideoDriver(); sg->smgr = idevice->getSceneManager(); … … … }
Voici le code de la frame appelé par un thread d'affichage :
void GraphicsEngine::frame(){ // on vérifie si l'utilisateur n'a pas fermé la fenêtre if (!driver || !idevice->run()){ parent->Stop(); } driver->beginScene(true, true, irr::video::SColor(0,00,00,00)); boost::mutex::scoped_lock l(parent->GetWorld()->lockWorld); parent->GetWorld()->Syncronize(); l.unlock(); // on dessine le graphe de scène sg->Render(); int fps = driver->getFPS(); irr::core::stringw str = L"ALT-ernative "; str += " FPS:"; str += fps; idevice->setWindowCaption(str.c_str()); // on appelle l'affichage de l'interface driver->endScene(); }
Voici la déclaration de la classe :
class GraphicsEngine : public Engine { public: GraphicsEngine(Game*); // objet contenant et mode passif ~GraphicsEngine(); //bool OnEvent(irr::SEvent); irr::video::IVideoDriver *GetDriver(); EventReceiver *GetEventReceiver(); //Gui_system *get_gui(); protected: // GuiSystem *gui; irr::video::IVideoDriver *driver; void frame(); irr::IrrlichtDevice *idevice; void processEvent(EngineEvent *); EventReceiver *receiver; SceneGraph *sg; //bool consoleVisible; // ... }; #else
Est-ce un bug de la version 1.4.1 ?
Merci
Hors ligne
Je trouve assez étrange de séparer l'initialisation et la boucle de rendu dans deux threads différents. Après, je sais pas ce que tu fais avec, donc c'est peut-être justifé.
Moi je pencherais plus pour un problème de synchro. Je pense que le thread qui effectue le rendu veut rendre une frame avant que l'autre thread n'ait initialisé le driver, d'où l'erreur de segmentation.
Si t'as vraiment besoin de les séparer, tu dois utiliser un mutex initialisé dans un état bloquant, afin d'être certains que le rendu ne s'effectuera pas avant que le driver ne soit prêt, et tu déverouilles le mutex juste après l'initialisation.
Tu l'as peut-être déjà fait, mais comme ça n'apparait pas dans le code posté, je préfère le dire quand même
Dernière modification par Perceval (02-07-2008 13:14:11)
Hors ligne
En fait, il ne peut pas avoir de désyncronisation : le processus mère initialise en créant un objet « GraphicsEngine » puis lance le thread qui va lancer la methode « frame.
Depuis j'ai fais quelque tests et il est possible que le problème viennent de la bibliothèque « boost » et non d'Irrlicht. Je poursuis mon investigation et je vous tiens au courant.
Hors ligne
Le problème vient bien d'irrlicht, ou en tout cas d'openGL.Le plantage a lien à l'apelle de certaines méthode comme « beginScene » ou «getTexture » dans un autre thread que celui qui a initialisé le « driver ». Par contre, des méthodes comme « getDriverType » fonctionnent très bien. L'ojet est donc bien créé.
Cependant, aucun plantage n'est constaté en mode « SOFTWARE » : seulement en OpenGL
Mystère…
Hors ligne
En fait, il ne peut pas avoir de désyncronisation : le processus mère initialise en créant un objet « GraphicsEngine » puis lance le thread qui va lancer la methode « frame.
Ben dans ce cas, je vois toujours pas l'intérêt de séparer l'initialisation du rendu.
Tu fais quoi après dans ton thread qui initialise le driver ? Si il ne fait plus rien, alors autant le mettre dans le thread de rendu, juste avant la boucle principale. Si tu utilises encore le driver, alors c'est une ressource critique, et dans ce cas, tu dois l'utiliser en exclusion mutuelle, ce qui ne semble pas être le cas dans le code que tu as fournit.
Hors ligne
Pour information générale, Irrlicht n'est pas Thread-safe (j'ai eu la confirmation de BlindSide). A manier donc avec prudence.
Hors ligne
Perceval :
Tu fais quoi après dans ton thread qui initialise le driver ?
Le processus mère lance d'autre moteurs dans des threads séparés : réseau, physique, son, jeu. Le moteur de jeu fais aussi des appels a des fonctions irrlicht qui plante en multi-thread.
Finalement j'ai utilisé mon système de message pour déporter certains appels de fonction dans le bon moteur afin qu'opengl ne soit solicité que dans 1 thread…
Hors ligne
Pages: 1