Massive switching between TextureStates - renderdropout - custom memory cleanup?

Hi all,

still workin on the TextureState issue of an animated texture I recognized the following behaviour. To save bandwith I am not setting up a new texture each frame. I am switching between TextureStates containing exactly one animation frame, instead.



The memory usage goes up and is cutted down (starting at 140mb going up to 220mb) Each time the memory is cutted down there is one render drop out.



Is there a chance to avoid this rendering drop out?



thanks

cheers

I believe the memory usage drop is because of garbage collection and obviously that's going to be necessary for your application to continue to run. :slight_smile:



darkfrog

:slight_smile: yes - that was what I thought. But do you have an idea how to "help" the garbage collector to avoid this intense dropping?



deviation

There are some tweaks you can do, but I wouldn't be able to point you to anything concrete without looking at the code.  The best thing I could suggest is searching the web for some good GC tutorials and best practices when dealing with memory intensive applications.



darkfrog

k, having a look at the code again I just recognized that even if there is nothing more than an updateRenderState(); without doing anything with the Texture/TextureState the memory usage is still the same. Ok, in my testing scenario I have 10 TextureStates attached to 100 geos but as I said after commenting all changing stuff it remains the same.



Could it be possible, that some impovements to updateRenderState(); could change that behaviour  :expressionless: - just guessing



deviation

Hi again,

I just uploaded the src of a testing scenario to www.deviation.de/anitest.zip - there is also a short 10 frame dds image sequence included. It is a Eclipse project. I tested it using the latest nightly build.



cheers

Sorry buddy, I wasn't trying to imply that I could take a look at it.  Under normal circumstances I would be happy to, but at the moment I'm quite bogged down as I'm trying to complete my ODENetworking API, trying to finish Force of Fire, and attempted to help out with the jME-Physics project.



If you want to post the relevent code on here I'd be happy to see if I can see anything that you might be able to optimize.



darkfrog

Sounds like something is going bad hereā€¦ We should try and find out if this is something in your code, specific to your code, or something that happens each time you apply a renderstate to multiple objects. Hopefully I can write a test in 1 or 2 weeks, however if you can write a simplified test yourself we might be able to diagnose the problem sooner.

k, I will try to write one tomorrow - to late now in europe :slight_smile:

well, I did some further testings and finally wrote a test. During testing I noticed that everything worked fine as long I was using a texture with a resolution of 512x512 pixel - memory usage remains stable after a while. Switching to 1024x1024 results in growing memory usage.

Though the source of the application I posted yesterday uses 256x256 pixel resolution maps but a sequence of them.



I am not sure but it seems that the texture resolution has a big impact on the applications memory usage - even if there is just one texture applied to multiple geos.



package ultrageist.test;

import java.net.URL;

import com.jme.app.FixedLogicrateGame;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;

public class TestMassiveTextureStates extends FixedLogicrateGame {

Thanks for saving me some work there :slight_smile:



Texturing is not really my thing yet in jME, but your example here is simple enough so I gave it a look and I did some profiling with it.



Practically all allocations came from the creation of many new texture states every update. This happens because if the texture combine mode is anything other then REPLACE (even OFF :D) a new Texture State is made (in the LWJGL code) to "combine" all the texture states. This happens every frame because you call updateRenderState() every frame.



The default texture combine mode is COMBINE_CLOSEST (Combine texture states starting from the given Spatial and working towards the root. Ignore disabled states). I think your animatations will still work with REPLACE so that should work for now. The "proper" way of doing this however, is by only calling updateRenderState on a spatial (or it's parent node for that matter!) if you've actually changed something in de RenderState. updateRenderState doesn't actually check if the render states are "dirty" (this is left to the programmer) and can be quite heavy on CPU/Memory because optimizations can be done here that will lessen the burden on render() that is called every frame. (The same in a way, goes for updateWorldData(), even though simpleGame calls it every frame as well)



So the quick fix for this example is by adding this in initGame():



items.setTextureCombineMode(TextureState.REPLACE);



The proper (in this case also quick) fix is putting updateRenderState where it belongs. That's only in init in this case, and only after actually changing the frame in the animation in the case of your real work. Of course, you can (and should) still use TextureState.REPLACE when you're not combining textures, since it makes updateRenderState faster in any case.

yes it works :slight_smile: - thanks a lot. I guess I will have to look deeper in RenderStates. Thanks for pointing this out

cheers

Only a note: this is fixed in jme 0.9 - renderstates get created only if states have to be combined. So one does not need to use REPLACE to save memory in the case discussed here.