diff --git a/changes.txt b/changes.txt index 17b26871..3a6690ab 100644 --- a/changes.txt +++ b/changes.txt @@ -11,6 +11,10 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point) -------------------------- Changes in 1.9 (not yet released) +- Bugfix: SMaterialLayer::operator!= no longer returns true when comparing a layer without texture matrix with one with a set identity texture matrix. Those are the same. +- SMaterialLayer no longer releases allocated texture memory before destructor unless explicitly requested. + This can avoid constantly allocation/releasing memory in the active driver material when setting materials. + Note that it does not copy texture memory when it's unused. This is still optimized. - Add IMeshSceneNode::setNodeRegistration to allow registering MeshSceneNodes to the SceneManager per buffer instead of per node - Add SMaterialLayer::hasSetTextureMatrix and SMaterialLayer::resetTextureMatrix - Add IShaderConstantSetCallBack::OnCreate to allow earlier access to IMaterialRendererServices diff --git a/include/IVideoDriver.h b/include/IVideoDriver.h index 1999a0df..ff21f797 100644 --- a/include/IVideoDriver.h +++ b/include/IVideoDriver.h @@ -13,12 +13,13 @@ #include "plane3d.h" #include "dimension2d.h" #include "position2d.h" -#include "IMeshBuffer.h" #include "triangle3d.h" #include "EDriverTypes.h" #include "EDriverFeatures.h" +#include "EPrimitiveTypes.h" #include "SExposedVideoData.h" -#include "SOverrideMaterial.h" +#include "S3DVertex.h" +#include "SVertexIndex.h" namespace irr { @@ -43,6 +44,8 @@ namespace video struct S3DVertex2TCoords; struct S3DVertexTangents; struct SLight; + struct SOverrideMaterial; + class SMaterial; class IImageLoader; class IImageWriter; class IMaterialRenderer; diff --git a/include/SMaterialLayer.h b/include/SMaterialLayer.h index 48698cd5..c8006d01 100644 --- a/include/SMaterialLayer.h +++ b/include/SMaterialLayer.h @@ -51,7 +51,8 @@ namespace video public: //! Default constructor SMaterialLayer() : Texture(0), TextureWrapU(ETC_REPEAT), TextureWrapV(ETC_REPEAT), TextureWrapW(ETC_REPEAT), - BilinearFilter(true), TrilinearFilter(false), AnisotropicFilter(0), LODBias(0), TextureMatrix(0) + BilinearFilter(true), TrilinearFilter(false), AnisotropicFilter(0), LODBias(0), + TextureMatrix(0), TextureMatrixUsed(false) { } @@ -84,26 +85,22 @@ namespace video return *this; Texture = other.Texture; - if (TextureMatrix) + if (other.TextureMatrixUsed) { - if (other.TextureMatrix) - *TextureMatrix = *other.TextureMatrix; - else + if (TextureMatrix) { - MatrixAllocator.destruct(TextureMatrix); - MatrixAllocator.deallocate(TextureMatrix); - TextureMatrix = 0; + *TextureMatrix = *other.TextureMatrix; } - } - else - { - if (other.TextureMatrix) + else { TextureMatrix = MatrixAllocator.allocate(1); MatrixAllocator.construct(TextureMatrix,*other.TextureMatrix); } - else - TextureMatrix = 0; + TextureMatrixUsed = true; + } + else + { + TextureMatrixUsed = false; } TextureWrapU = other.TextureWrapU; TextureWrapV = other.TextureWrapV; @@ -124,6 +121,12 @@ namespace video { TextureMatrix = MatrixAllocator.allocate(1); MatrixAllocator.construct(TextureMatrix,core::IdentityMatrix); + TextureMatrixUsed = true; + } + else if ( !TextureMatrixUsed ) + { + *TextureMatrix = core::IdentityMatrix; + TextureMatrixUsed = true; } return *TextureMatrix; } @@ -132,7 +135,7 @@ namespace video /** \return Texture matrix of this layer. */ const core::matrix4& getTextureMatrix() const { - if (TextureMatrix) + if (TextureMatrixUsed) return *TextureMatrix; else return core::IdentityMatrix; @@ -151,25 +154,27 @@ namespace video } else *TextureMatrix = mat; + TextureMatrixUsed = true; } //! Check if we have set a custom texture matrix //! Note that otherwise we get an IdentityMatrix as default inline bool hasSetTextureMatrix() const { - return TextureMatrix != 0; + return TextureMatrixUsed; } //! Reset texture matrix to identity matrix - //! Releases memory, which is expensive, but ver rarely useful for optimizations - void resetTextureMatrix() + /** \param releaseMemory Releases also texture memory. Otherwise done in destructor */ + void resetTextureMatrix(bool releaseMemory=true) { - if ( TextureMatrix ) + if ( TextureMatrix && releaseMemory) { MatrixAllocator.destruct(TextureMatrix); MatrixAllocator.deallocate(TextureMatrix); TextureMatrix = 0; } + TextureMatrixUsed = false; } //! Inequality operator @@ -189,8 +194,11 @@ namespace video if (different) return true; else - different |= (TextureMatrix != b.TextureMatrix) && - (!TextureMatrix || !b.TextureMatrix || (*TextureMatrix != *(b.TextureMatrix))); + { + different = (TextureMatrixUsed && b.TextureMatrixUsed && (*TextureMatrix != *b.TextureMatrix)) + || (TextureMatrixUsed && !b.TextureMatrixUsed && (*TextureMatrix != core::IdentityMatrix)) + || (!TextureMatrixUsed && b.TextureMatrixUsed && (core::IdentityMatrix != *b.TextureMatrix)); + } return different; } @@ -241,6 +249,7 @@ namespace video /** Do not access this element directly as the internal resource management has to cope with Null pointers etc. */ core::matrix4* TextureMatrix; + bool TextureMatrixUsed; // TextureMatrix memory stays until destructor even when unused to avoid unnecessary allocation/de-allocations }; } // end namespace video diff --git a/include/irrlicht.h b/include/irrlicht.h index 3c00a4b0..8d0f6968 100644 --- a/include/irrlicht.h +++ b/include/irrlicht.h @@ -179,6 +179,7 @@ #include "SKeyMap.h" #include "SLight.h" #include "SMaterial.h" +#include "SOverrideMaterial.h" #include "SMesh.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" diff --git a/source/Irrlicht/CBufferRenderNode.h b/source/Irrlicht/CBufferRenderNode.h index 923434fa..a309275b 100644 --- a/source/Irrlicht/CBufferRenderNode.h +++ b/source/Irrlicht/CBufferRenderNode.h @@ -76,6 +76,11 @@ public: driver->setMaterial(material); driver->drawMeshBuffer(mb); } + + // Resetting after each rendering so direct calls to render() for parent node continue to work + // Assuming each pass only runs once + RenderPass = ESNRP_NONE; + ParentDoesRender = true; } //! Renders the node. @@ -84,10 +89,6 @@ public: video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform(video::ETS_WORLD, MeshNodeParent.getAbsoluteTransformation()); renderBuffer(driver); - - // resetting each time so direct calls to render() for parent node continue to work - RenderPass = ESNRP_NONE; - ParentDoesRender = true; } virtual const core::aabbox3d& getBoundingBox() const IRR_OVERRIDE diff --git a/source/Irrlicht/CGUIMeshViewer.cpp b/source/Irrlicht/CGUIMeshViewer.cpp index fa310f84..f5132987 100644 --- a/source/Irrlicht/CGUIMeshViewer.cpp +++ b/source/Irrlicht/CGUIMeshViewer.cpp @@ -9,6 +9,7 @@ #include "IVideoDriver.h" #include "IAnimatedMesh.h" #include "IMesh.h" +#include "IMeshBuffer.h" #include "os.h" #include "IGUISkin.h" diff --git a/source/Irrlicht/CIrrMeshWriter.cpp b/source/Irrlicht/CIrrMeshWriter.cpp index cb33fe95..cc62a90b 100644 --- a/source/Irrlicht/CIrrMeshWriter.cpp +++ b/source/Irrlicht/CIrrMeshWriter.cpp @@ -11,6 +11,7 @@ #include "IWriteFile.h" #include "IXMLWriter.h" #include "IMesh.h" +#include "IMeshBuffer.h" #include "IAttributes.h" namespace irr diff --git a/source/Irrlicht/CMeshSceneNode.cpp b/source/Irrlicht/CMeshSceneNode.cpp index 7e3a6b9f..c3176048 100644 --- a/source/Irrlicht/CMeshSceneNode.cpp +++ b/source/Irrlicht/CMeshSceneNode.cpp @@ -219,7 +219,7 @@ void CMeshSceneNode::render() } } - if ( bufRenderNode->getRenderPass() == renderPass ) + if ( bufRenderNode->getRenderPass() == renderPass || renderPass == ESNRP_NONE) bufRenderNode->renderBuffer(driver); } } diff --git a/source/Irrlicht/CNullDriver.h b/source/Irrlicht/CNullDriver.h index 5c5eab77..98515ed8 100644 --- a/source/Irrlicht/CNullDriver.h +++ b/source/Irrlicht/CNullDriver.h @@ -21,6 +21,7 @@ #include "SVertexIndex.h" #include "SLight.h" #include "SExposedVideoData.h" +#include "SOverrideMaterial.h" #ifdef _MSC_VER #pragma warning( disable: 4996) diff --git a/source/Irrlicht/COpenGLSLMaterialRenderer.cpp b/source/Irrlicht/COpenGLSLMaterialRenderer.cpp index 9c4104e9..09a1925f 100644 --- a/source/Irrlicht/COpenGLSLMaterialRenderer.cpp +++ b/source/Irrlicht/COpenGLSLMaterialRenderer.cpp @@ -573,10 +573,14 @@ void COpenGLSLMaterialRenderer::startUseProgram() void COpenGLSLMaterialRenderer::stopUseProgram() { - // Not going to reset irrGlUseProgram/extGlUseProgramObject as it shouldn't really matter + // Necessary as fixed function pipeline breaks if programs are not reset to 0 + if (Program) + Driver->extGlUseProgramObject(0); + if (Program2) + Driver->irrGlUseProgram(0); // Force reset of material to ensure OnSetMaterial will be called or we can miss - // the next UseProgram call + // the next UseProgram call as stopUseProgram can be called from anywhere Driver->DoResetRenderStates(); } diff --git a/source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp b/source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp index c0549916..52f7dcdf 100644 --- a/source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp +++ b/source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp @@ -5,6 +5,7 @@ #include "CParticleAnimatedMeshSceneNodeEmitter.h" #include "IAnimatedMeshSceneNode.h" #include "IMesh.h" +#include "IMeshBuffer.h" #include "os.h" namespace irr diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 9084274e..6255cfe1 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -7,6 +7,7 @@ #include "IVideoDriver.h" #include "IFileSystem.h" #include "SAnimatedMesh.h" +#include "SOverrideMaterial.h" #include "CMeshCache.h" #include "IXMLWriter.h" #include "ISceneUserDataSerializer.h" diff --git a/tests/material.cpp b/tests/material.cpp index 2a6dc1ae..d5b7e3bf 100644 --- a/tests/material.cpp +++ b/tests/material.cpp @@ -71,9 +71,41 @@ static bool polygonOffset(video::E_DRIVER_TYPE type) return result; } +static bool testSMaterial() +{ + irr::video::SMaterial a; + irr::video::SMaterial b; + + // Same by default? + if ( !(a == b) ) + return false; + if ( a != b ) + return false; + + // getting (creating) one texture matrix shouldn't change things + b.TextureLayer[0].getTextureMatrix(); + if ( a != b ) + return false; + + // no longer same now + b.TextureLayer[0].getTextureMatrix().setTextureScale(5.f, 0.5f); + if ( a == b ) + return false; + + return true; +} + bool material() { bool result = true; + TestWithAllDrivers(polygonOffset); + + if ( !testSMaterial() ) + { + logTestString("testSMaterial failed\n\n"); + result = false; + } + return result; } diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index f7f59afa..2fc244f3 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 72 tests of 72 passed. Compiled as DEBUG -Test suite pass at GMT Fri May 05 18:39:44 2023 +Test suite pass at GMT Tue May 09 10:09:52 2023