Rapid Texture loading/unloading

Started by aZen, February 10, 2014, 12:14:51 PM

Previous topic - Next topic

aZen

So, I have a problem when rapidly loading and unloading textures in a multithreaded environment with several viewports, worlds, etc

In particular the problem occurs when unloading a texture, then immediately loading it again (same image and name) and creating an object that uses the texture (all without redraw). The texture then appears without the texture and is colored in the setAdditionalColor(...) color. I suspect that the texture doesn't get unloaded from the FrameBuffer. However when I add another object with the same texture "a little bit later" (after redraw), it is textured fine.

I tried to create a simple test case, but no luck. The workaround I have now is that I use

        if (textureManager.containsTexture(name)) {
            textureManager.replaceTexture(name, texture);
        } else {
            textureManager.addTexture(name, texture);
            textureManager.replaceTexture(name, texture);
        }


Will this cause a lot of extra load? How bad practice is this?

Thank you!

EgonOlsen

jPCT isn't thread safe. Fiddling around with textures from outside the rendering thread can lead to all kinds of funny race conditions. While your solution might improve this, i doubt that it will work in all cases. I would rather put that code into the rendering thread or synchronize both operations (i.e. rendering and texture updates).

aZen

#2
They are already synchronized. Also the behavior is very consistent and my approach always stops the problem from occurring (in my tests anyway).

The only thing that was multithreaded w.r.t. rendering, world or texture modification is JPCT itself. I just disabled that and the problem still occurs. Will try to get you that test case... (or maybe find my own stupidity while doing so =)

EgonOlsen


aZen

God... I was finally able to create a test case that reproduces the bug. Cleaning it up now, but will post soon!

aZen

Here you go.

http://blackflux.com/software/vs/download/?file=BugTestCase.zip

I wanted to simplify it more, but it behalves.. very strange. So I decided to leave it as it is. The non-java files are the textures that are loaded (png images).


Screenshot of the bug: Texture is available but not displayed.

EgonOlsen

That test case is confusing...what does it do?

EgonOlsen

...i think that this test case either doesn't reproduce your actual problem or it's not a bug. If you comment out these two lines:


//removeTexture("f0e482dac89c9456011090337316d7c1");
        removeObjectById(15);
        obj.build();
        world.addObject(obj);
        trackObjectId(obj, 26);
        obj = new Object3D(2);
//loadTexture("f0e482dac89c9456011090337316d7c1");


it works fine. And that's to be expected, because, like the docs for removeTexture say:

Quote
Please note that you can't expect an object that uses this texture to get a new texture that you might add with the same name after removing this one. If you want to replace textures on objects, use replaceTexture() instead.


aZen

#8
No, that is exactly the problem that I found. I read the doc, but thought that it doesn't apply. Let me explain:

So basically what happens is

addTexture("a", img1);
addObjectWithTexture(obj1, "a");
removeObject(obj1);
removeTexture("a");
addTexture("a", img1);
addObjectWithTexture(obj2, "a");

Note that the texture (when it exists) always contains the same image.

I'm not expecting an object to update, just expecting that it shows any texture (old or new version doesn't matter, they're the same anyway) when I create it and the texture exists in the TextureManager. Instead the object doesn't show a texture.

If you say it's expected I'm happy to add an replaceTexture after the addTexture (as described in the first post) and forget about it.

EgonOlsen

I see...no that's not to be expected. This version should fix it: http://jpct.de/download/beta/jpct.jar

However, due to the internal structure of the TextureManager, it's always better to replace a texture with the same name instead of doing a remove/add combination regardless of the texture being used by some object or not.

aZen

Great, thank you. That fixes it!

Yes, that was what I figured. Unfortunately because of how I have organized things it's very tricky to do that in the particular case.

aZen

After spending so much time tracking this down I have to ask: What was causing it?

EgonOlsen

A simple cache that should have been cleared when you remove a texture but wasn't.

aZen

Hehe, always the simple things causing the biggest issues.

Thank you for fixing this so fast!