IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Moteurs 3D Discussion :

[OSG] Multithreading pour le chargement d'images


Sujet :

Moteurs 3D

  1. #1
    Membre habitué Avatar de Kromagg
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2008
    Messages : 275
    Points : 198
    Points
    198
    Par défaut [OSG] Multithreading pour le chargement d'images
    Bonjour à tous

    Je dois réaliser un mur d'images avec OpenSceneGraph pour un laboratoire de Réalité Virtuelle. Le truc c'est que je dois pouvoir charger un dossier entier d'images sans pour autant altérer la navigation à travers les images déjà afficher. J'ai donc décider de créer un thread en plus du thread principal, qui devra charger les images depuis le disque dur et les soumettre à OpenSceneGraph.

    Voici en comment s'organise mon main de test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    #include <OpenMC.hpp>
     
    #include <osgGA/TrackballManipulator>
     
    class AreaImagesLoader : public openMC::Job
    {
    public:
    	/** Constructeur - destructeur. */
    	AreaImagesLoader(openMC::Area* area, const std::string& path):
    	mArea(area),
    	mPath(path)
    	{}
     
    	virtual ~AreaImagesLoader(void) {}
     
    	virtual void run(void)
    	{
    		mArea->loadContent(mPath);
    	}
     
    private:
    	openMC::Area* mArea;
    	std::string mPath;
    };
     
    int main(int argc, char** argv)
    {
    	try
    	{
    		openMC::SystemController* controller = new openMC::SystemController("RenderingConfig.xml");
    		openMC::ThreadsPool* pool = controller->getThreadsPool();
    		openMC::SceneManager* smgr = controller->getSceneManager();	
    		osg::ref_ptr<osgViewer::Viewer> viewer = controller->getViewer();
     
    		openMC::Area* images = smgr->createArea("images");
     
    		boost::shared_ptr<AreaImagesLoader> loaderImagesSolo(new AreaImagesLoader(images, "../../Data/ImagesSolo"));
    		pool->pushJob(loaderImagesSolo);
     
    		viewer->realize();
    		viewer->setCameraManipulator(new osgGA::TrackballManipulator);
     
    		bool first = true;
    		while (!viewer->done())
    		{
    			if (first)
    			{
    				boost::shared_ptr<AreaImagesLoader> loaderImagesPerso(new AreaImagesLoader(images, "../../Data/ImagesPerso"));
    				pool->pushJob(loaderImagesPerso);	
    				first = false;
    			}
     
    			smgr->renderAllAreas();
    			viewer->frame();			
    		}
     
    		delete controller;
    	}
    	catch (openMC::Exception e)
    	{
    		MessageBox(0, e.getFullDescription().c_str(), "An error has occured", MB_OK | MB_ICONERROR);
    		return 1;
    	}
     
    	return 0;
    }
    De mon côté l'application est bien thread-safe (mutex et thread boost).
    Le problème c'est que ça plante du côté d'OSG (sur un std::vector) et je n'ai pas le moyen de voir ou ça plante ni pourquoi (>osg55-osgd.dll!576c2809())



    Comment puis-je rendre OSG thread-safe ?

    Kromagg
    C'est dans ses rêves que l'homme trouve la liberté cela fut, est et restera la vérité! (John Keating - Le cercle des poètes disparus)

  2. #2
    Membre habitué Avatar de Kromagg
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2008
    Messages : 275
    Points : 198
    Points
    198
    Par défaut
    Je viens de comprendre pourquoi ça plante.

    Osg utilise des std::vector pour stocker les noeuds fils d'un noeud. Or dans mes threads, une fois l'image chargée, je fais appel à Area::osg:ositionAttributeTransform::addChild() (donc appel à std::vector pour l'ajout du noeud), et dans la boucle de rendu je fais aussi appel au même std::vector (pour le parcours du graphe de scène), donc conflit d'accès, d'où le plantage.

    Je ne sais pas du tout comment régler ce problème, car ma contrainte et de pouvoir charger les images en même temps que naviguer dans celles déjà présente.

    Y'a-t'il un moyen de contourner ce problème avec un osg::NodeVisitor ou autre ?

    Kromagg
    C'est dans ses rêves que l'homme trouve la liberté cela fut, est et restera la vérité! (John Keating - Le cercle des poètes disparus)

  3. #3
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Points : 1 630
    Points
    1 630
    Par défaut
    Dans ton thread qui charge les images tu ne dois en aucun cas modifier osg. Il faut que tu envoies tes images chargees au cours d'une boucle de rendu dans une classe de communication qui est elle thread-safe et qui va s'occuper de mettre a jour le graphe de scene OSG a la fin de chaque ta boucle de rendu.
    Je ne réponds à aucune question par MP, posez vos questions sur le forum adéquat.
    Profils : G+ - LinkedIn

  4. #4
    Membre habitué Avatar de Kromagg
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2008
    Messages : 275
    Points : 198
    Points
    198
    Par défaut
    Merci pour ta réponse TanEk, j'ai bien compris le concept, cependant une question subsiste.
    Comment puis-je mettre à jour le graphe de scène OSG juste à la fin de la boucle de rendu ?
    Est-ce que je peux utiliser un osg::NodeCallback, ou j'update juste après un appel à osgViewer::Viewer::frame() ?

    Kromagg
    C'est dans ses rêves que l'homme trouve la liberté cela fut, est et restera la vérité! (John Keating - Le cercle des poètes disparus)

  5. #5
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Points : 1 630
    Points
    1 630
    Par défaut
    Je ne connais pas du tout OSG donc je ne peux pas t'aider sur ce point desole.

    Le seul truc que je peux te dire (et encore il faudrait que quelqu'un d'autre confirme...) c'est qu'il faudrait que tu saches quand OSG fait un appel a la fonction de swap des buffers graphiques (a la fin de la boucle de rendu en general). Une fois que tu as identifie cette fonction, tu dois t'assures qu'elle n'accede pas au graphe OSG et dans ce cas tu peux lancer dans un thread separe la modification du graphe OSG car cet appel de swap est bloquant (le GPU finalise son calcul et effectue le swap) donc tu perds enormement de temps, temps pendant lequel le CPU ne fait rien si ce n'est attendre le GPU et ne modifie pas le graphe OSG. Donc tu pourrais prendre cette situation a ton avantage en lancant en parallele la modification du graphe OSG par ta classe de communication qui connait quelles nouvelles images sont maintenant accessibles.
    Je ne réponds à aucune question par MP, posez vos questions sur le forum adéquat.
    Profils : G+ - LinkedIn

  6. #6
    Membre éprouvé
    Avatar de Ange_blond
    Homme Profil pro
    Ingénieur développement en 3D temps réel
    Inscrit en
    Mars 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement en 3D temps réel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 902
    Points : 1 179
    Points
    1 179
    Par défaut
    Hello,

    J'ai pas suivit toute la discution mais je peux tout de meme aider :


    Citation Envoyé par Kromagg Voir le message
    Comment puis-je mettre à jour le graphe de scène OSG juste à la fin de la boucle de rendu ?
    Est-ce que je peux utiliser un osg::NodeCallback, ou j'update juste après un appel à osgViewer::Viewer::frame() ?
    Les 2 méthodes sont correctes.

    La seule différence, c'est que le nodeCallback sera donc automatiquement apellé par OSG pendant la boucle de rendu à un moment où tu peux agir sur le graph de maniere sécurisée, alors qu'apres le frame() c'est completement en dehors de la boucle.

    Selon ta structure de projet et ce que tu veux faire, à toi de choisir la maniere que tu prefere.
    "le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

  7. #7
    Membre habitué Avatar de Kromagg
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2008
    Messages : 275
    Points : 198
    Points
    198
    Par défaut
    Merci à vous deux mon problème est résolu, j'ai donc une classe ImageManager qui reçoit les images nouvellement créées, puis à la fin de ma boucle de rendu je fais un appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while (!viewer->done())
    {
         viewer->frame();
         imgr->updateGraph();
    }
    Maintenant j'ai créé un thread pour charger un dossier entier d'image et c'est la que vient une autre question. Pour le moment ça lague un peu entre le chargement d'un dossier et la navigation dans l'application.
    Est ce que je dois créé un thread par chargement d'image, ou un thread pour le chargement d'un dossier complet ? Quelle pourrait être la meilleure solution ?

    Kromagg
    C'est dans ses rêves que l'homme trouve la liberté cela fut, est et restera la vérité! (John Keating - Le cercle des poètes disparus)

  8. #8
    Membre éprouvé
    Avatar de Ange_blond
    Homme Profil pro
    Ingénieur développement en 3D temps réel
    Inscrit en
    Mars 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement en 3D temps réel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 902
    Points : 1 179
    Points
    1 179
    Par défaut
    Je dirais que tu dois evaluer en fonction de ce que ça donne quand tu charge une image... si ça prend bcp de temps alors un thread par image peut faire l'affaire, sinon un pour tous... à voir...

    Limite la priorité du thread pour ne pas faire lagger ton application...
    "le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

  9. #9
    Membre éprouvé
    Avatar de Ange_blond
    Homme Profil pro
    Ingénieur développement en 3D temps réel
    Inscrit en
    Mars 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement en 3D temps réel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2007
    Messages : 902
    Points : 1 179
    Points
    1 179
    Par défaut
    tant que j'y pense, osg implémente déjà des threads pr le telechargement de données pendant la boucle de rendu avec osgDB::databasePager.

    Je l'utilise pour les PagedLOD et ça marche plutot bien...

    regarde de ce coté là, tu peux peut etre l'exploiter sans avoir à le réécrire
    "le langage C permet de tout faire, y compris se tirer dans le pied. Le langage C++ permet de tout faire, y compris se tirer dans le pied - et réutiliser la balle"

Discussions similaires

  1. Réponses: 0
    Dernier message: 20/06/2015, 22h58
  2. [Débutant] Multithread pour chargement de fichiers
    Par JediMaster dans le forum Windows Presentation Foundation
    Réponses: 9
    Dernier message: 24/12/2013, 03h45
  3. Une image de chargement pour un lot d'image en chargement.
    Par Niki59 dans le forum Général JavaScript
    Réponses: 20
    Dernier message: 06/06/2009, 14h05
  4. Chargement d'image pour créer une texture
    Par sir_gcc dans le forum OpenGL
    Réponses: 2
    Dernier message: 29/12/2008, 22h49
  5. Containeur pour un assemblage d'images
    Par Amenofis dans le forum Composants VCL
    Réponses: 3
    Dernier message: 28/02/2003, 15h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo