Salut personne
bon voila l'autre jours j'ai poster un topic sur le chargement des scenes en thread séparé
mais bon on n'a pas vraiement regarder de prêt a ce que j'avais fait comme code d'example !
du coup j'ai fait un petit patch pour faire ça
Index: include/IVideoDriver.h =================================================================== --- include/IVideoDriver.h (revision 5114) +++ include/IVideoDriver.h (working copy) @@ -19,6 +19,7 @@ #include "EDriverTypes.h" #include "EDriverFeatures.h" #include "SExposedVideoData.h" +#include "IImage.h" namespace irr { @@ -467,7 +468,7 @@ The value is a safe approximation, i.e. can be larger than the actual value of pixels. */ virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const =0; - + //! Create render target. virtual IRenderTarget* addRenderTarget() = 0; @@ -1449,6 +1450,19 @@ */ virtual void convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF) const =0; + + /** + Change who texture is loaded, if "DefferedTextureLoader" is used + @getTexture(...) return a FakeTexture type and then cached + when DefferedTextureLoader is returned to false, the cache is cleanup + and all texture is reloaded at the same address by a driver dependent texture + */ + virtual void setDeferredTextureLoader(bool) = 0; + + /** + return the current state of "DefferedTextureLoader" + */ + virtual bool useDeferredTextureLoader() const = 0; }; } // end namespace video Index: source/Irrlicht/CNullDriver.cpp =================================================================== --- source/Irrlicht/CNullDriver.cpp (revision 5114) +++ source/Irrlicht/CNullDriver.cpp (working copy) @@ -23,6 +23,60 @@ namespace video { + FakeTexture::FakeTexture(irr::video::IVideoDriver *driver, IImage* surface, + const io::path& name, void* mipmapData) : + ITexture(name), Image(surface), MipData(mipmapData), Driver(driver) + { + Image->grab(); + } + FakeTexture::~FakeTexture() + { + // Image droped when this object is transformed to a driver dependent texture + } + void* FakeTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) _IRR_OVERRIDE_ + { + return Image->lock(); + } + void FakeTexture::unlock() _IRR_OVERRIDE_ + { + return Image->unlock(); + } + void FakeTexture::regenerateMipMapLevels(void* mipmapData) + { + } + const core::dimension2d<u32>& FakeTexture::getOriginalSize() const + { + return Image->getDimension(); + } + const core::dimension2d<u32>& FakeTexture::getSize() const + { + return Image->getDimension(); + } + E_DRIVER_TYPE FakeTexture::getDriverType() const + { + return Driver->getDriverType(); + }; + ECOLOR_FORMAT FakeTexture::getColorFormat() const + { + return Image->getColorFormat(); + } + u32 FakeTexture::getPitch() const + { + return Image->getPitch(); + } + bool FakeTexture::hasMipMaps() const + { + return MipData; + } + bool FakeTexture::hasAlpha() const + { + return true; /* ??? */ + } + bool FakeTexture::isRenderTarget() const + { + return false; + } + //! creates a loader which is able to load windows bitmaps IImageLoader* createImageLoaderBMP(); @@ -85,7 +139,7 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& screenSize) : SharedRenderTarget(0), CurrentRenderTarget(0), CurrentRenderTargetSize(0, 0), FileSystem(io), MeshManipulator(0), ViewPort(0, 0, 0, 0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500), - TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false) + TextureCreationFlags(0), OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false), DeferredLoader(false) { #ifdef _DEBUG setDebugName("CNullDriver"); @@ -626,6 +680,25 @@ } +/** +Change who texture is loaded, if "DefferedTextureLoader" is used +@getTexture(...) return a FakeTexture type and then cached +when DefferedTextureLoader is returned to false, the cache is cleanup +and all texture is reloaded at the same address by a driver dependent texture +*/ +void CNullDriver::setDeferredTextureLoader(bool i) +{ + DeferredLoader = i; +} + +/** +return the current state of "DefferedTextureLoader" +*/ +bool CNullDriver::useDeferredTextureLoader() const +{ + return DeferredLoader; +} + //! set a render target bool CNullDriver::setRenderTarget(IRenderTarget* target, const core::array<u32>& activeTextureID, bool clearBackBuffer, bool clearDepthBuffer, bool clearStencilBuffer, SColor clearColor) Index: source/Irrlicht/CNullDriver.h =================================================================== --- source/Irrlicht/CNullDriver.h (revision 5114) +++ source/Irrlicht/CNullDriver.h (working copy) @@ -38,6 +38,44 @@ class IImageLoader; class IImageWriter; + + class IVideoDriver; + + class FakeTexture : public ITexture + { + public: + FakeTexture(irr::video::IVideoDriver *driver, IImage* surface, + const io::path& name, void* mipmapData); + + virtual ~FakeTexture(); + + virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) _IRR_OVERRIDE_; + + virtual void unlock() _IRR_OVERRIDE_; + + virtual void regenerateMipMapLevels(void* mipmapData = 0); + + virtual const core::dimension2d<u32>& getOriginalSize() const; + + virtual const core::dimension2d<u32>& getSize() const; + + virtual E_DRIVER_TYPE getDriverType() const; + + virtual ECOLOR_FORMAT getColorFormat() const; + + virtual u32 getPitch() const; + + virtual bool hasMipMaps() const; + + virtual bool hasAlpha() const; + + virtual bool isRenderTarget() const; + public: + IImage* Image; + void* MipData; + IVideoDriver* Driver; + }; + class CNullDriver : public IVideoDriver, public IGPUProgrammingServices { public: @@ -678,6 +716,19 @@ const c8* name=0); virtual bool checkDriverReset() _IRR_OVERRIDE_ {return false;} + + /** + Change who texture is loaded, if "DefferedTextureLoader" is used + @getTexture(...) return a FakeTexture type and then cached + when DefferedTextureLoader is returned to false, the cache is cleanup + and all texture is reloaded at the same address by a driver dependent texture + */ + virtual void setDeferredTextureLoader(bool); + + /** + return the current state of "DefferedTextureLoader" + */ + virtual bool useDeferredTextureLoader() const; protected: //! deletes all textures @@ -880,6 +931,9 @@ bool AllowZWriteOnTransparent; bool FeatureEnabled[video::EVDF_COUNT]; + bool DeferredLoader; + + core::list<FakeTexture*> CachedDefferedLoader; }; } // end namespace video Index: source/Irrlicht/COpenGLDriver.cpp =================================================================== --- source/Irrlicht/COpenGLDriver.cpp (revision 5114) +++ source/Irrlicht/COpenGLDriver.cpp (working copy) @@ -2492,7 +2492,7 @@ else if (texture->getDriverType() != EDT_OPENGL) { CurrentTexture.set(stage, 0); - os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); + //os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); return false; } @@ -2549,10 +2549,49 @@ //! returns a device dependent texture from a software surface (IImage) video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { - return new COpenGLTexture(surface, name, mipmapData, this); + if(DeferredLoader) + { + //! sizeof(FakeTexture) < sizeof(COpenGLTexture) + video::FakeTexture *tmp = (FakeTexture*) ::operator new (sizeof(COpenGLTexture)); + new ((void*)tmp) FakeTexture(this, surface, name, mipmapData); + CachedDefferedLoader.push_back(tmp); + return tmp; + } + return new COpenGLTexture(surface, name, mipmapData, this); } +/** +Change who texture is loaded, if "DefferedTextureLoader" is used +@getTexture(...) return a FakeTexture type and then cached +when DefferedTextureLoader is returned to false, the cache is cleanup +and all texture is reloaded at the same address by a driver dependent texture +*/ +void COpenGLDriver::setDeferredTextureLoader(bool i) +{ + CNullDriver::setDeferredTextureLoader(i); + if(!i) + { + os::Printer::log("load deferred texture", ELL_WARNING); + for(core::list<FakeTexture*>::Iterator it = CachedDefferedLoader.begin(); + it != CachedDefferedLoader.end(); ++it) + { + video::FakeTexture *tmp = *it; + + IImage* Image = tmp->Image; + void* MipData = tmp->MipData; + const io::SNamedPath& name = tmp->getName(); + + tmp->~FakeTexture(); + + new ((void*)tmp) COpenGLTexture(Image, name, MipData, this); + Image->drop(); + } + CachedDefferedLoader.clear(); + } +} + + //! Sets a material. All 3d drawing functions draw geometry now using this material. void COpenGLDriver::setMaterial(const SMaterial& material) { Index: source/Irrlicht/COpenGLDriver.h =================================================================== --- source/Irrlicht/COpenGLDriver.h (revision 5114) +++ source/Irrlicht/COpenGLDriver.h (working copy) @@ -425,6 +425,13 @@ //! Get bridge calls. COpenGLCallBridge* getBridgeCalls() const; + /** + Change who texture is loaded, if "DefferedTextureLoader" is used + @getTexture(...) return a FakeTexture type and then cached + when DefferedTextureLoader is returned to false, the cache is cleanup + and all texture is reloaded at the same address by a driver dependent texture + */ + virtual void setDeferredTextureLoader(bool); private: bool updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer);
et est donc utiliser de cette façon
Hors ligne
Qu'est-ce que tu veux dire par chargement différé? Quelle est la différence par rapport au chargement normal?
Hors ligne
la différence c'est que, quand tu charge une scene en multi-threading
les textures sont crée en même temps or le context graphique est lier au processus principal ce qui fait echéouer la création de la texture et sont upload dans le gpu du coup t'a pas de texture afficher même si elle sont charger
de cette façon la, une "fausse" texture est crée (un genre de warper avec la même taille en mémoire que la vrai) et l'or de la fin du chargement (tu apelle setDeferredTextureLoader(false)) elle sont alors transformer à la même adresse en "vrais" texture dans le thread principal et donc uploader correctement sur le gpu
ça permet de faire des écrans de chargement animer en gros, ou charger 2 scene en même temps
ça reste performant puisque irrlicht charge une IImage avans de crée la texture, donc c'est vraiment que l'upload vers le gpu qui est réalisé
Hors ligne
Ah ok. C'est super utile, parce que c'est vrai que les écrans de chargement fixes sont embêtants. On se demande toujours si le jeu est planté, si il fait quelque chose... Il faudra que je teste ça dès que je passerai à l'implémentation des écrans de chargement. Merci de continuer à participer sur ce forum malgré le déclin d'intérêt . J'espère que l'on verra ce forum remonter la pente parce qu'Irrlicht est vraiment un moteur simple pour faire des petites appli ou jeu sympa.
Hors ligne
ouaip !
j'ai un code qui traine pour faire des barres de chargement en cercle ça donne pas mal sur mon éditeur
irrlicht n'aime pas trop les rotations de texture ça fait un rendu pourris (ou alors j'ai oublier l'antialiasing ...)
j'ai une autre version qui fonctionne comme un "pie chart" et j'ai changer la méthode de rotation
je passerais faire un poste d'ici "qeulques" semaine
Hors ligne
petite mise à jours avec les changements de la revision 5189.
Hors ligne