Selectively preloading textures in the background

Hello,

what’s the recommended workflow for selectively loading textures in the background?
While I don’t feel as if the FileTexture was blocking, I experience some (more or less slightly) noticeable framedrops when loading a lot of textures at the same time. Also I’m pretty sure it’s no other operation consuming those textures and creating the lag, because those operations aren’t even called at the time of preloading.

I have a nested layout of contents, while one content is is always considered active and is drawing.
While it is drawing, I call “Preload” on all its child contents, which basically is just putting all textures every child might display at some point into a FileTexture, so it’s ready for display.

The problem definitely isn’t in the scope of loading the textures itself I feel, because that would be way more noticeable. It feels more like micro stutters. I notice it most at a level when a couple slideshows are preloaded at once …

Even though FileTexture isn’t labeled Async, I felt it was, but just to make sure I replaced all of them with TextureReader (Async) and it more or less felt the same/the stutters didn’t go away.
(Edit: TextureReader feels better actually (probably because it’s just way faster), just tried the other version again. But not unnoticeable as in “fully in background”).

Any idea what I could be doing wrong?
As of now I don’t have a patch and its assets ready to share publicly, but I could share in private.
But maybe that’s not even necessary, just hoping someone had to deal with a similar case before (assuming it’s really not something my patch is doing and the problem is limited to loading the textures only).

Thanks

I think this is a slight misconception, “in background” doesn’t mean that it cannot influence the main loop. It just means that the main loop doesn’t have to wait until everything is finished and that the operations can share the available CPU resources. So you should rather think of it as “in parallel”, where each of the parallel operations gets some time from the CPU, which feels like more CPU load, hence some stutters.

there are also “sync points” where information flows from one task to another, these points can block the main loop for a brief moment.

So if you want total separation, you could load textures in another instance and share them via a shared handle or spout.

1 Like

I see, thanks. Yes, misconception it was. Will consider your suggestion and play around a bit to see if a secondary application is viable for my use case, or check if I can incorporate obvious loading times into the ux somehow …

Guess I got confused by the TextureReader’s Async category, also as this is what should allow fast image stack playback without stutters?

here is one more idea, try loading the textures one by one with some time in between, loading one at a time should not hit the main loop that much, as seen in the ImagePlayer.

1 Like

What format do your texutres have, PNG, JPG? Especially PNGs can be hard on the CPU if they use maximum compression. If you haven’t already try converting them to DDS and check if it makes a difference.

2 Likes

Mostly exclusively png, coming from a cms, but I’ll look into converting them on startup to have a dds ready for each, thanks!

Also I’ll register every texture requested by the Preload operations in a single manager style class which will, if needed, throttle the loading as suggested by tebjan.

Reporting back, I have converted all files to dds (with TextureWriter though, not TexConvGui, as it would need to be an automated process in the end and this was faster for a quick test), but that didn’t seem to give me much of a boost.

Sampling some FileTexture.IsLoading timings in a stopwatch + queue gave me this comparison for the first few textures. While it might pile up to something noticeable and I might make use of it in the end, I would like to focus on other things first.

imageimage

Careful, wall of text ahead - just taking notes on my findings here so it can help others or I can be corrected/educated ;)

FileTexture
Is there a way to force the stride asset pipeline to unload textures once seen?
Stepping through a directory with all files one by one will eventually fill up my 12GB as it holds on to them, making a second loading time super fast - which is a nice thing in general.
But now I’m wondering if this can be prevented or if I can target specific assets to be cleared from the cache if I want to (something like AssetItem.Unload())?
Maybe that’s also not even needed, I don’t care if too many stay in memory … but here I would have more questions:

  1. Will a full gpu memory be ok in this case as the memory is managed by Stride and I can rely on it to free up ressources when needed? (When loading textures manually from a Directory per Bang IOBox, looking at GPU-Z, around 11640MB it stop increasing in memory but the FileTexture loading times of new textures remain within the same range as before the memory wasn’t full)
  2. Will a full gpu memory also not impair performance somewhere else?
  3. If the above are both fine, will that also remain true if not another Stride asset is requesting to be loaded into memory, but some other process (maybe even outside of vvvv) needs more memory, will I not run into errors then or even run into exceptions related to the full memory?
  4. As the above things to some degree only revolve around the fact that Stride just keeps using up memory, can this be limited?
  5. Not sure if it’s the same as 4, but is this currently making use of Streaming | Stride (stride3d.net)? If so, one could probably lower the available streaming memory pool. But looking at the TextureAssetFromFile inside of the FileTexture, it has IsStreamable hardcoded to false … so probably the memory is not managed somehow. I can keep loading textures though (see 1) and it will remain around the same level when it’s nearly full.
  6. Once the memory is full but textures get loaded without any issues, I can only assume that Stride unloads previously seen textures. By which logic would that happen? Any random texture not on display at the time? I would have expected ListAssets to report on that, but both “Loaded Asset Items” and “Requested Assets” keep increasing whenever I load the next texture.

Edit: Just found ContentManager.Unload(), but haven’t looked at it yet. Also, before making use of that, I would need to understand if it’s actually necessary or everything just works fine as is …

TextureReader
Not really questions here, just documenting my thoughts.
As I don’t understand everything that is happening in Stride when making use of the FileTexture, I wanted to also explore this option. As I don’t have a 3D scene, I don’t need MipMaps anyway … right now everything is just slightly off its display size, but that could be optimized if really needed.
This seems to work as expected, there are only the things in memory I want and it’s easier to keep track of what is happening.

One thing noteworthy is though (and now that I know it also makes sense), that in order to free up ressources the TextureReader will need to remain updated with just the filenames you want to keep. When having the TextureReader as part of an operation and just not calling that operation anymore, it will not work:

But on the upside this will also only load everything just once, even from different places in the patch, as the internal NewPooled region will return the handle to the very same ressource as long as the filepaths remain the same.

Conclusion
Wondering if the FileTexture also just works and the gpu memory being on the edge wouldn’t turn out to be an issue, but I somehow don’t trust it being so close to the device limit …
Is there any way to make the FileTexture also work around the Stride asset pipeline, so it behaves more like the TextureReader / FileTexture in Beta? This way we could keep some of its features without running into the other “issues” (if they even are issues to begin with …).

For my use case, I guess the TextureReader will be fine.

(Edit: loading all filetextures at once seems to be fine, even if it exceeds the vram … I have quite a lot of more followup questions, trying to figure out whether what I’m observing is something the drivers understand, or Stride does for you, or Stride does for you but needs you to keep the FileTextures around for the intelligent management (or if I’d have the same seamless experience when storing all textures in a dictionary at once, omitting all FileTextures across the patch … I guess I just have a limited understanding of what’s going on here.)

2 Likes

Now that I think about it, that’s probably because I have a 27GB data folder living in my vvvv folder …
So maybe, if I get this right, the best practice of converting to dds is outdated these days (and only applies for image stacks + texture reader)

Two comments on this folder:

  1. It used to live in vvvv\lib\data and is now in packs\dependencies\data because it’s probably just next to the Stride dlls. Can this configured to be somewhere else? Is it compatible across vvvv versions as long as there’s no breaking Stride update? If so, it would be nice to have it in the project folder instead, because when working on a project like this and I’m using previews, I install different preview versions quite often and now find myself with a couple of rather large data-folders in different preview folders …

  2. Because of what can happen, this folder should have its own entry somewhere in the vvvv menu(s) … there’s already this (Shader Cache) in the About-tab in the burger menu, but placing it there would also keep people from finding it:
    image
    Ideally it would be a button to clear it, maybe even with an info on the folder’s current size

  3. Deleting the entire data folder or all its content breaks vvvv, some content needs to remain, making it an extra bit tedious to clear it manually.

1 Like

also see here: Lib/data/db

1 Like