Asset manager pre-caching method. Any interest?

I was thinking of pre-caching textures at the start of Disenthral because I’ve noticed a slowdown that lasts about 2-3 seconds at launch, once the game was loaded, but certain areas of the scene were not in the frustum.



To do this I’d have to load each and every textures individually without using them. Then it came to me that it would be good to have a method to pre-cache files automatically in asset manager. I’m thinking of something similar to this:



[java]

/**

  • Caches images (png, jpg, etc) found in paths ArrayList
  • @param assetPaths String pointing to a directory in the asset pack.
  • @param recurse Directories found inside provided paths will be parsed
  • if set to true. If false, children directories will be ignored.

    *

    */

    public void precache(ArrayList<String> assetPaths, boolean recurse) {

    // parse directory(ies) and load images found there.

    }

    [/java]



    I personally think this would be good to have in AssetManager, but I can easily make it a single class if there isn’t enough interest. To make it worthwhile to everyone the method would load every file type supported (have a loader) found in the paths.
2 Likes

oh yes, i already made it in UGLY way.



idea is nice,



it will need to be other thread or fps based to be able to make Loading GUI showing progress.



also assetManager is cashing after first load?(or am i wrong) so it only need to load, so assetmanager would cashe it.

As far as the asset manager is concerned, your texture is cached as soon as you load it… but you will still get a slow down in the scene when the texture is sent to the GPU for the first time. That’s a different kind of caching.

Yes.



Considering the hard drive is the slowest component of a computer (even SSD drives), having those textures read beforehand is an advantage.

@madjack said:
Yes.

Considering the hard drive is the slowest component of a computer (even SSD drives), having those textures read beforehand is an advantage.


In your example, it sounded like they were already loaded from asset manager and it was just the GPU dispatch that was causing the slow down.

@madjack said:
I was thinking of pre-caching textures at the start of Disenthral because I've noticed a slowdown that lasts about 2-3 seconds at launch, once the game was loaded, but certain areas of the scene were not in the frustum.


Caching them in the asset manager would not fix that problem because they are already fully loaded as far as the asset manager is concerned.

Also, the "recurse directories" part... the asset manager has no concept of directories since it is generally impossible to get this information from the standard locators. So you'd have to provide the list of all assets specifically. And in that case, you might as well just iterate over them and load them... two lines instead of one line.

Recursivity can be removed then.



One way or the other, it’s much simpler to pass an asset path string to every directory you want cached than manually load each texture. Although I’m wondering, after what you said about directories in the asset pack, if a directory can be parsed to get the files in there.

does it not already exist? unless im missing something

[java]renderManager.preload(spatial); //for spatials



material.preload(renderManager); //for materials[/java]

@wezrule said:
does it not already exist? unless im missing something
[java]renderManager.preload(spatial); //for spatials

material.preload(renderManager); //for materials[/java]

This does what Paul talked about, it send the assets to the GPU.
@nehon said:
This does what Paul talked about, it send the assets to the GPU.


Interesting, did not know about that. Is this operation bound to the renderthread?

Count ForgingLife team interested :slight_smile:

Count me intrested as well since current terrain loading times are up to 20 seconds on slower systems.

Ok then. It seems there’s some interest.



I can’t promise anything, but I’ll try to come up with something in a reasonable time frame. I’m unsure yet how I’ll tackle this, but I’ll find something that, hopefully, will satisfy most of you.

1 Like

mhh wait.

Let’s lay down exactly what this should do, the use of it and the opportunity of getting it into the core. (to avoid the get/setPixel situation)



There are 2 things to consider :

1- loading assets from a drive into the heap memory of your app and caching. That’s what the asset manager does. each time you load a model, the assetmanager gives you a clone and keep the original one in the cache, so that next time you load it you will be served with another clone.



2- Sending the assets to the GPU (mesh buffers and material textures). This is done by the renderManager the first time a geometry is rendered. But it can be forced using the RenderManager.preload(scene).



Operation 1 usually take more time than operation 2.



What @madjack is suggesting is that we make a system that loads all assets placed in an asset folder.

If you think of implementing caching or something like that, there is no need as it’s already handled by the assetManager.



The only advantage i see IMO is that you would have one folder where you could just drag some models and that’ll be automatically loaded by the app.



Not sure this is very useful though…usually you know what you want to load, so if you want a pre-loading just make an appstate or something that loads all the models you need upon application init…

Also I usually have during dev time some myModelBackup.j3o along with myModel.j3o (usually previous working version of the model) that i don’t want to load.

Of course I can be wrong, that’s just my feeling about it…

Now convince me I’m wrong.

The only advantage i see IMO is that you would have one folder where you could just drag some models and that’ll be automatically loaded by the app.

"one folder" -> choosed folders

hmm, for me this is a good advantage. it's better to see "cashing procedure with percentage or something" than just a black screen or loading screen with no information how long it will take.
and it is easy to choose what to cashe, via selecting folders.

ofc, you are right that it can be done without it, but it is just easier to choose folders and create cashing view or something.

but it's just my opinion. If you say its wrong, then it propably is.
@oxplay2 said:
"one folder" -> choosed folders

hmm, for me this is a good advantage. it's better to see "cashing procedure with percentage or something" than just a black screen or loading screen with no information how long it will take.
and it is easy to choose what to cashe, via selecting folders.

ofc, you are right that it can be done without it, but it is just easier to choose folders and create cashing view or something.

but it's just my opinion. If you say its wrong, then it propably is.


Only your own caching code could hope to have a progress indicator. Any core method would just block for 20 seconds loading. Assets that take 20 seconds to load will always take 20 seconds to load... we're only talking about moving it around.

The problem with the "look in a directory" approach is that there is just no way to do this. Assets are loaded as class resources and class loaders do not provide a way to search directories.

You could move these assets somewhere else so that they aren't part of the assets.jar and then you could add your own AssetLocator for that directory and use File.listFiles to find them. But I really think a small utility method that replaces two lines of code then is the small part... as the changes to your build to make all of that happen is the most work.

What i would like to see is the ability to specify a bunch of models ect. (this part i can do already, however also upload it to the gpu)



What I would suggest some kind of assetManager snapshot. So i load my level manually can use a special utility function that generates a file with all currently used models ect.



Now next time I display a loading screen and give those file t the precacher and just wait till it is done.





Something like this.

You cannot decide when it gets uploaded to the gpu really except by using it directly in a shader somewhere. As the data is there in OpenGL already as native buffers I was thinking about opening another context in jME3 to use that for preloading (or generally loading) assets to the GPU. Multiple contexts is what the OpenGL spec suggests for multithreading on the GPU anyway and we’ll get in contact with that if we start to use OpenCL as well so it might be an easy start for such stuff ^^

@EmpirePhoenix said:
What i would like to see is the ability to specify a bunch of models ect. (this part i can do already, however also upload it to the gpu)

What I would suggest some kind of assetManager snapshot. So i load my level manually can use a special utility function that generates a file with all currently used models ect.

Now next time I display a loading screen and give those file t the precacher and just wait till it is done.

Something like this.


The part I'm unclear about is how those assets got loaded if you didn't load them. Wouldn't the "snapshot" just be all of the assets you yourself loaded? Why not just load them?

I'm not trying to be obtuse but I genuinely don't understand.

I loaded them at the time I needed them for the logic. Now I want to make a snapshot and preload them all the next time, so I have no loading lags midgame

1 Like
@EmpirePhoenix said:
I loaded them at the time I needed them for the logic. Now I want to make a snapshot and preload them all the next time, so I have no loading lags midgame


You will still have loading lags, I think. It is likely that not all of it would fit in the GPU or whatever. This is why this sort of preloading is usually managed by the application and not done blindly.

...would be easy enough to test, I guess.