GPU memory leak, Texture(M)

By the way thank you for the time spent trying to find my issue.

It s hard when you didnt code the game to find this kind of problem.

I could give a try to add back the direct call to the assetManager and see if it solve the problem.

I will try this for now

Alright,
I ve did the test and it s like i thought,

Direct call to the AssetManager is extremely slow.
Second it didn’t solve the problem, it made it worst :frowning:
It s generate twice as much texture in the graphic memory.

My code:

        mat = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
        mat.setBoolean("useTriPlanarMapping", false);
        mat.setFloat("Shininess", 0.0f);
        
        mat.setTexture("AlphaMap", tex1);
        mat.setTexture("AlphaMap_1", tex2);
        
        //Texture 1
        Texture textur0 = myTexture.getRock();
        Texture textur1 = myTexture.getGrass();
        Texture textur2 = myTexture.getDirt1();
        Texture textur3 = myTexture.getSwampGrass2();
        
        //Texture 2
        Texture textur4 = myTexture.getFlower(); //RED
        Texture textur5 = myTexture.getLakeRock();    // GREEN  
        Texture normal5 = myTexture.getLakeRockNormal(); 
        Texture textur6 = myTexture.getFarmSoil(); //BLEU
        Texture textur7 = myTexture.getDirt2();//ALPHA
        //Texture parallaxMap7 = myTexture.getVolcanicNormalParallax();


//        Texture 1
        textur0.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap", textur0);
        mat.setFloat("DiffuseMap_0_scale", 128);
        
        textur1.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_1", textur1);
        mat.setFloat("DiffuseMap_1_scale", 128);
        
        textur2.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_2", textur2);
        mat.setFloat("DiffuseMap_2_scale", 128);
        
        textur3.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_3", textur3);
        mat.setFloat("DiffuseMap_3_scale", 128);
        
        //Texture 2
        textur4.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_4", textur4);
        mat.setFloat("DiffuseMap_4_scale", 128);
        
        
        textur5.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_5", textur5);
        mat.setFloat("DiffuseMap_5_scale", 64);
        
        normal5.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("NormalMap_5", normal5);
        
        
        textur6.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_6", textur6);
        mat.setFloat("DiffuseMap_6_scale", 128);
        
        textur7.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_7", textur7);
        mat.setFloat("DiffuseMap_7_scale", 128);

Code with the Direct call to AssetManager:

        mat = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md");
        mat.setBoolean("useTriPlanarMapping", false);
        mat.setFloat("Shininess", 0.0f);
        
        mat.setTexture("AlphaMap", tex1);
        mat.setTexture("AlphaMap_1", tex2);
        
        //Texture 1
        Texture textur0 = assetManager.loadTexture("Textures/terrainHigh/Rock.jpg");
        Texture textur1 = assetManager.loadTexture("Textures/terrainHigh/HighQualityGrass3.jpg");
        Texture textur2 = assetManager.loadTexture("Textures/terrainHigh/Soil1.jpg");
        Texture textur3 = assetManager.loadTexture("Textures/terrainHigh/swamp_grass2.jpg");
        
        //Texture 2
        Texture textur4 = assetManager.loadTexture("Textures/terrainHigh/Flower.jpg"); //RED
        Texture textur5 = assetManager.loadTexture("Textures/terrainHigh/50text/188.JPG");   // GREEN  
        Texture normal5 = assetManager.loadTexture("Textures/terrainHigh/50text/188_norm.JPG");
        Texture textur6 = assetManager.loadTexture("Textures/terrainHigh/FarmSoil.jpg"); //BLEU
        Texture textur7 = assetManager.loadTexture("Textures/terrainHigh/Soil2.jpg");//ALPHA
//        Texture parallaxMap7 = myTexture.getVolcanicNormalParallax();


//        Texture 1
        textur0.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap", textur0);
        mat.setFloat("DiffuseMap_0_scale", 128);
        
        textur1.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_1", textur1);
        mat.setFloat("DiffuseMap_1_scale", 128);
        
        textur2.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_2", textur2);
        mat.setFloat("DiffuseMap_2_scale", 128);
        
        textur3.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_3", textur3);
        mat.setFloat("DiffuseMap_3_scale", 128);
        
        //Texture 2
        textur4.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_4", textur4);
        mat.setFloat("DiffuseMap_4_scale", 128);
        
        
        textur5.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_5", textur5);
        mat.setFloat("DiffuseMap_5_scale", 64);
        
        normal5.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("NormalMap_5", normal5);
        
        
        textur6.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_6", textur6);
        mat.setFloat("DiffuseMap_6_scale", 128);
        
        textur7.setWrap(Texture.WrapMode.Repeat);
        mat.setTexture("DiffuseMap_7", textur7);
        mat.setFloat("DiffuseMap_7_scale", 128);

If you run in the debugger then you might trace into the loadTexture() call to see where it’s going wrong. A particular file should only be loaded once.

It’s possible that changing the wrap mode messes with the cache but it seems unlikely.

I can’t remember… does running System.gc() fix your memory problems?

Do you eventually get errors or are you just looking at some stat somewhere and getting worried?

I run into intense lag after a while(while running in a direction), when i reload i get the same lag.

I get the stats from an application reading the gpu stats and directly from the game stats like this

We could read 75 texture here

We could read 320 texture here, sorry for the bad spelling, You should read The memory increase to 2.6g ram

You know i was looking for anwser and I found some one talking about it here in 2012.

Is it possible the texture manager is broken if some one make something he shouldn’t have done somewhere?

Alright i think i ve found the leak…

Take a look at this picture, I dont think it s normal that every generated Terrain are keeping a thread alive even after I’ve removed them.( I detach them and remove the physic and remove reference)
Am I right? or it s part of the system?

And are those thread part of the physic engine or something else, and if you know how to close the process it would be awesome!

What version of JME are you running?

Latest Stable i think 3.0.10

If i generate all the map using concurrency, is it possible the executor is the one keeping all the reference?

update: never mind, It s always 1 to 3 active count while loading 3 maps

That’s odd, I thought the terrain system used a single executor service … If not, it probably should.

This might have been fixed in 3.1 which is why I asked about version. I do remember a conversation about something like this a while back and I sort of remember something being fixed. Since I have no personal interest in the built in terrain system I only half paid attention.

…either way, to OP, upgrading might be worth a try at some point.

Is the actual 3.1 version enought stable to upgrade, i heard i would have migrating job to do?

I generate multiple map in parallel using concurrency, would it be the reason it start multiple instance of the jme3 Terrain?

@BigBob wasn’t this the one with thre refelction hack as a workaround?

Here is a link to a topic in which I was having the same issue.

The link in the topic is outdated to the solution but here it is

    private void clearTerrainLod() {
    
        SceneGraphVisitor sgv = new SceneGraphVisitor() {
            
            public void visit(Spatial spatial) {
            
                if (spatial instanceof Terrain) {
                    
                    TerrainLodControl tlc = spatial.getControl(TerrainLodControl.class);
                    Field f;
                    
                    try {
                        f = tlc.getClass().getDeclaredField("executor");
                        f.setAccessible(true);
                        ExecutorService ex = (ExecutorService) f.get(tlc);
                        ex.shutdown();
                    }
                    
                    catch (NoSuchFieldException nsf) {
                    }
                    
                    catch (IllegalAccessException e) {
                    }
                    
                    catch (Exception a) {
                    
                    }
            
                }
            }
        
        };
        
        app.getRootNode().depthFirstTraversal(sgv);
        
    }

Basically uses reflection to set it to accessible and then shuts down the thread directly.

Good luck.

There’s a method in TerrainLodControl called detachAndCleanUpControl() which does exactly what the above does. Also you can set your own executor with TerrainLodControl.setExecutor() and handle it yourself, which is probably what you should be doing if your application has other background tasks besides terrain updates.

The TerrainLodControl.setExecutor() does not exist, i presume i have to copy and remake the whole classe to make one? Or is it part of the nightly build?
Same thing for the detachAndCleanUpControl().

Looks like those two methods were added in 3.1 … Sorry about that.

It s alright but i can’t find a way to update my IDE to the nightly build, it just doesnt pop up the update when i check the nightly build update. If you know how i can upgrade i would do this immediatly!

Sorry … the nighties are not available at the moment. You can keep track of the progress here: