AlpineMapsOrg / renderer

Rendering system for alpine maps.
GNU General Public License v3.0
4 stars 10 forks source link

Scheduler prioritization when exceeding tile limit #101

Open pkomon-tgm opened 3 months ago

pkomon-tgm commented 3 months ago

Limiting the number of GPU quads (each quad has 4 tiles) that should be requested and rendered in total is possible by using nucleus::tile_scheduler::Scheduler::set_quad_limit, but it sometimes leads to coarser zoom levels being used for close-up tiles, especially when many tiles are visible at once. For a brief moment, the foreground tile is displayed in the correct resolution, but when the farther away tiles are replaced by higher resolution ones, the foreground tile is replaced by a lower resolution one.

After tile-loading, nucleus::tile_scheduler::Scheduler::update_gpu_quads is called, which first inserts the new tiles into m_gpu_cached of type Cache<T>, and then calls Cache<T>::purge(unsigned remaining_capacity) on it (Scheduler.cpp, L143), where the tiles to delete are determined. The current implementation ranks the tiles based on zoom level and deletes all those, that have a higher zoom level than the first tile exceeding the capacity.

If not all tiles fit in GPU memory, I think it would be reasonable to also incorporate distance to camera (or maybe projected bounding box area?) to select which tiles to keep, rather than just zoom level. I think, we might want to have some sort of trade-off between zoom-level and how well the structure is visible, to avoid extreme cases.

One possible solution could be to add a functor argument to Cache<T>::purge for calculating the per-tile scores that are used for the ranking. Maybe then we would also need to do a full sort (rather than using std::nth_element, which basically does a single quick-sort iteration), but I think we can afford to do this.

I'm not exactly sure about what heuristic to choose for a good trade-off 😅 Might need to experiment a bit here.