Crystal Hammer wrote: ↑Sun Jun 18, 2023 5:58 pmOkay thank you for help with there. I'll address them later.
I made a video with a faster way to leak v1 meshes GPU RAM.
So, as on video:
- load a track with pipes e.g. that jungle Jng5-Pipes one
- go to road detail, set high subdivision counts (steps and multipliers) (but not too high, it overflows 16bit index buffers), and lowest length dimension.
- press B to rebuild road and F4 to save track (just check on Settings - Settings on bottom, to allow saving originals), so you won't need to do previous step any more.
- now select a pipe road point in middle (its close 4 segments have a lot of vertices now).
- shift left right for a couple seconds for me already show GPU RAM increasing (last value bottom right on Fps bar). And it won't go down on track reload or otherwise.
I got something better: taking a look at your code I reproduced the problem in a much smaller sample:
Code: Select all
//-----------------------------------------------------------------------------------
void V2MeshGameState::destroy()
{
if( !mMesh )
return;
using namespace Ogre;
SceneManager *sceneManager = mGraphicsSystem->getSceneManager();
sceneManager->destroySceneNode( mSceneNode );
sceneManager->destroyItem( mItem );
MeshManager::getSingleton().remove( mMesh );
mMesh.reset();
v1::MeshManager::getSingleton().remove( mMesh1 );
mMesh1.reset();
}
//-----------------------------------------------------------------------------------
void V2MeshGameState::import()
{
destroy();
using namespace Ogre;
// clang-format off
const float cubeVertex[4*(3 + 3 + 3 + 2)] = {
-1, -1, 0, 0, 1, 0, 0, 0 ,//
1, -1, 0, 0, 1, 0, 1, 0 ,//
1, 1, 0, 0, 1, 0, 1, 1 ,//
-1, 1, 0, 0, 1, 0, 0, 1 ,//
};
// clang-format on
const uint16 cubeIndices[6] = { //
0, 1, 2, //
2, 3, 0
};
VertexElement2Vec vertexElements;
vertexElements.push_back( VertexElement2( VET_FLOAT3, VES_POSITION ) );
vertexElements.push_back( VertexElement2( VET_FLOAT3, VES_NORMAL ) );
vertexElements.push_back( VertexElement2( VET_FLOAT2, VES_TEXTURE_COORDINATES ) );
const size_t bytesPerVertex = VaoManager::calculateVertexSize( vertexElements );
const size_t iterations = 5000;
uint8 *vertexData = reinterpret_cast<uint8 *>( // vertices
OGRE_MALLOC_SIMD( bytesPerVertex * 4u * iterations, MEMCATEGORY_GEOMETRY ) );
uint16 *indexData = reinterpret_cast<uint16 *>( // vertices
OGRE_MALLOC_SIMD( sizeof( uint16 ) * 6u * iterations, MEMCATEGORY_GEOMETRY ) );
for( size_t i = 0u; i < iterations; ++i )
{
memcpy( vertexData + ( bytesPerVertex * 4u ) * i, cubeVertex, bytesPerVertex * 4u );
memcpy( indexData + 6u * i, cubeIndices, sizeof( uint16 ) * 6u );
}
SceneManager *sceneManager = mGraphicsSystem->getSceneManager();
VaoManager *vaoManager = sceneManager->getDestinationRenderSystem()->getVaoManager();
VertexBufferPacked *vertexBuffer = vaoManager->createVertexBuffer(
vertexElements, iterations * 4u, BT_DEFAULT, vertexData, true );
IndexBufferPacked *indexBuffer = vaoManager->createIndexBuffer(
IndexBufferPacked::IT_16BIT, iterations * 6u, BT_IMMUTABLE, indexData, true );
VertexBufferPackedVec vertexBuffers;
vertexBuffers.push_back( vertexBuffer );
VertexArrayObject *vao =
vaoManager->createVertexArrayObject( vertexBuffers, indexBuffer, OT_TRIANGLE_LIST );
Ogre::MeshPtr mesh =
MeshManager::getSingleton().createManual( "v2 Mesh without Tangents", "General" );
SubMesh *subMesh = mesh->createSubMesh();
subMesh->mVao[VpNormal].push_back( vao );
subMesh->mVao[VpShadow].push_back( vao );
Aabb aabox( Vector3::ZERO, Vector3( 2.0f ) );
mesh->_setBounds( aabox, false ); //?
mesh->_setBoundingSphereRadius( ( aabox.getMaximum() - aabox.getMinimum() ).length() / 2.0 );
mMesh1 = v1::MeshManager::getSingleton().create( "V1 TANGENT MESH", "General" );
mMesh1->setVertexBufferPolicy( v1::HardwareBuffer::HBU_STATIC, false );
mMesh1->setIndexBufferPolicy( v1::HardwareBuffer::HBU_STATIC, false );
mMesh1->importV2( mesh.get() );
MeshManager::getSingleton().remove( mesh ); // not needed
mesh.reset();
mMesh1->buildTangentVectors();
mMesh = MeshManager::getSingleton().createManual( "v2 final mesh", "General", 0 );
mMesh->importV1( mMesh1.get(), false, false, false );
mSceneNode =
sceneManager->getRootSceneNode( SCENE_STATIC )->createChildSceneNode( SCENE_STATIC );
mItem = sceneManager->createItem( "v2 final mesh", "General", SCENE_STATIC );
// it->setVisible( false );
// it->setCastShadows( false );
mItem->setVisibilityFlags( 0x01 );
mSceneNode->attachObject( mItem );
}
It basically does everything you're doing every frame, by calling import() every frame. It should make things much easier to debug for me.