How to cleanup shader?

Shader is one of the memory leak problem.

You can test it using code below.

When you press key '1', memory comes up.

But GC(key '2') can't release this.

Is there any way/method to release shader object?



modified test code to release object reference when hit '2'


import java.util.ArrayList;

import com.jme.app.SimpleGame;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.scene.state.GLSLShaderObjectsState;

public class TestDeleteShader extends SimpleGame {

   private static final String   GC   = "GC";
   private static final String   CREATE   = "Create";
   private static final String vert =
   " void main(void) { n" +
      "gl_Position = ftransform(); n"+
   "}";
   private static final String frag=
      "void main(void) { n"+
   "gl_FragColor = vec4(1); n"+
      "}";
   
   private ArrayList<GLSLShaderObjectsState> shaders = new ArrayList<GLSLShaderObjectsState>();
   
   @Override
   protected void simpleInitGame() {
      KeyBindingManager.getKeyBindingManager().add(CREATE, KeyInput.KEY_1);
      KeyBindingManager.getKeyBindingManager().add(GC, KeyInput.KEY_2);
   }

   @Override
   protected void simpleUpdate() {
      super.simpleUpdate();
      if (KeyBindingManager.getKeyBindingManager().isValidCommand(CREATE)) {
         createShader();
      } else if (KeyBindingManager.getKeyBindingManager().isValidCommand(GC)) {
         shaders.clear();
         System.gc();
      }
   }

   private void createShader() {
      GLSLShaderObjectsState shader = this.display.getRenderer().createGLSLShaderObjectsState();
      shader.load(vert, frag);
      shader.apply();
      shaders.add(shader);
   }
   
   public static void main(String[] args) {
      TestDeleteShader shader = new TestDeleteShader();
      shader.start();
   }
   
}

Where in your code are you deleting the objects, you are pushing into the ArrayList<GLSLShaderObjectsState> shaders?

Calling "System.gc();" doesn

Unforunately jME leaves most cleanup stuff for the user. You will be required to manually cleanup textures, fbos, shaders, vbo etc. However it is possible to integrate this cleaning automatically with the garbage collector…

Have you tried calling clearAttributes() and clearUniforms()?

JackNeil said:

I would suggest you call "shaders.clear();", when you hit 2 . This will delete all objects in your array list.
JackNeil

Thank you for the reply, JackNeil.
That was my mistake when uploading the test code.
(I modified the test code to post it and made a mistake. sorry.)
Actually my local version calls shaders.clear() when hit '3';
But It doesn't helps at all.

Momoko_Fan said:

Unforunately jME leaves most cleanup stuff for the user. You will be required to manually cleanup textures, fbos, shaders, vbo etc. However it is possible to integrate this cleaning automatically with the garbage collector..

I understand the need for the user to release resources.
(It would be inconvenient, but fast and optimized memory management is possible by that)
How could I release shader?
shader object isn't garbage collected as far as I know from the experience.
Because these data are natively allocated, explicit cleanup method call seems to be needed like GC(Graphics Context)
Do I have to use LWJGL/JOGL directly?
I think it would be very useful to have release method in jme.
Or are there already cleanup methods for the shader object?
JackNeil said:

Have you tried calling clearAttributes() and clearUniforms()?


What a quick reply!! I appreciate it.
But as you can see.
The shader code above is so simple and doesn't have any uniform, attributes.
And according to the inspection of GLSLShaderObjectState class,
it clears not native resources but just object references.
It means if there is no reference to the GLSLShaderObjectStates object,
it is garbage collected and no need to calll clearAttribtes(), clearUniforms().

I'm afraid I'm wrong,
but in my opinion it seems to be native resource management issue.
I modified jme and called LWJGLShaderObjectState.removeFragShader(), removeVertShader()
but it doesn't help either.

Is this problem only true to my case?

Is there anyone who experienced this kind of memory leak?

Please help me  :’(

My feeling is that resource handling and cleanup is jME's single biggest weakness - for most or all types not just shaders.

However I have not yet got to the stage of taking a really good look at it or trying to do anything about it. So maybe I'm wrong.

Thank you for the reply.

For two years' experience in jme engine,

Memory leak occurred in my project was generally not just by jme engine, but java related.

If I carefully code, most of the memory leak could be avoided.

JMEDesktop was substituted by BUI.

Custom Texture Managing code is applied.

But this shader memory leak doesn't have any substitution.

Because shader is one of the most important feature in current gaming environment

and it is frequently used, some fix is needed.

And for someone who knows GL, it would be simple problem. I think.

Alric said:

My feeling is that resource handling and cleanup is jME's single biggest weakness - for most or all types not just shaders.
However I have not yet got to the stage of taking a really good look at it or trying to do anything about it. So maybe I'm wrong.

Agreed. I have done some research about resource handling and have a rather good solution. jME3 will definitely have a universal resource management system.