Load only mip levels up to a specific size
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What problem does this solve or what need does it fill?
It is common for games to offer multiple levels of graphics settings, like: "Low", "High", "Ultra". When it comes to Texture Quality, this typically means the size of textures used. For example, a 2048x2048 texture will use 4x the GPU memory than a 1024x1024 texture and add more overhead during rendering, but look a lot crisper.
In 3D games, mipmaps are essentially required for high quality and performant rendering. If the game's assets are stored as KTX2 or DDS files with mipmaps, the smaller texture sizes are already available on-disk (and will, in fact, be loaded by Bevy and into GPU memory) anyway. In order to limit the max texture size at lower graphics settings, it could be implemented simply by just skipping the first mip level or two.
For example, if we have a 2048x2048 texture as a KTX2 file with a full set of mipmaps down to 1x1 (12 levels total), our hypothetical game could behave as follows:
- At the "Ultra Graphics" setting: load the whole thing
- At the "High Graphics" setting: skip the first mip level, effectively loading it as a 1024x1024 texture
- At the "Low Graphics" setting: skip the first two mip levels, effectively loading it as a 512x512 texture
## What solution would you like?
If Bevy supports specifying which mip levels to load, this could be done trivially, and reduce loading times by loading less data from disk.
## What alternative(s) have you considered?
1) Load everything anyway, and then simply not use it. The range of mip levels used by the GPU can be restricted using the `lod_min_clamp` and `lod_max_clamp` fields in the `SamplerDescriptor`. Disadvantage: we don't get any savings in GPU memory or loading times, so it kinda defeats the point.
2) Implement a two-step process, by discarding the unwanted data from the `Image` asset after it is loaded. We get GPU memory savings, but no loading time savings. Also, the full resolution data is stored intermittently in CPU memory, before we get a chance to delete it. Inefficient: loading data only to immediately drop it.
3) Create separate asset files with a lower base resolution. Works, but is redundant, wastes disk space. The lower resolution images are already available as mip levels in the larger asset.
## Additional context
This, of course, only applies to assets stored in file formats that have mipmaps (KTX2 and DDS). When loading images from, say, PNGs, this is irrelevant. In that case, if you want multiple different sizes, you need multiple files, or to downscale the image at runtime.
Contributor guide
Assessment
This issue has not been assessed yet.