Jump to content

Render Stall Optimization


photo

Recommended Posts

Proposal

 

Avoid frame render stalls for ObjectMesh (and maybe other mesh resources) when mesh resource is not already loaded by modifing ObjectMesh::getCollision(x/y/z)

 

....
int ObjectMesh::getCollision(const BoundFrustum &bf,Vector<int> &csurfaces) {
   csurfaces.clear();

   if( mesh_ptr.isLoaded() )   return mesh_ptr.get()->getCollision(bf,csurfaces);
   else                        { mesh_ptr.render(); return 0; }
}
....

 

 

Comment

 

ObjectMesh::getCollision() is called by RenderScene::getIntersection() -> RenderScene::addObject() when visible in the view frustum.

 

For ObjectMeshes where resources are not yet loaded (e.g. mesh newly visible) call of mesh_ptr.get() implicitly causes blocking forced file load. This easily kills frame rate of the render thread especially if file thread is busy or mesh resources are heavy.

 

This can be avoided by deferring collision surface access until resource has finished asynchron loading triggered by mesh_ptr.render();

Link to comment

Thanks, fixed via Object::isLoaded() virtual function for all objects.

 

great ! related to the mesh loading/unloading issue, what do you think about the following ideas for a general load/unload strategy for large/complex world resource management (not too elaborated, but maybe good enough for a discussion)

 

Optional resource load/unload distance for Node base class

 

From my understanding at the moment triggering of mesh/texture resource loading/delayed unloading is mainly based on view frustum visibility. In fast-paced games/simulations this leads to render frame drops/missing render resoures when player quickly turns around or moves forward.

 

Idea:

 

Node base class (see next point why not just Object base class) support for optional resource load/unload distance. This would allow the engine

 


  • 1) to pre-load resources in the surrounding of the active camera (with a load distance greater than render distance) smoothly in the background, so resources are already available when turning/moving
     
    2) to unload resources no longer in the area of player interesst (unload distance > load distance to avoid load/unload ping-pong).

 

Something like

class Node {
...
   void setLoadDistance  ( float distance );
   void setUnloadDistance( float distance );

   virtual void  load();
   virtual void  unload();

   virtual int   isLoaded();
...    
};

class World { 
...
   void setLoadDistance  ( float distance );
   void setUnloadDistance( float distance );
...
};

 

We have implement a prototype version of such distance-based loading/unloading for ObjectMesh as proof-of-concept and it works very nicely. CPU load/unload testing of objects is started after do_render() and runs in parallel to GPU-rendering "for free". By using a smaller file load priority for resources within load distance, but not within view frustum we can avoid file loading delays for visible resources.

 

 

Additional dynamic CPU-side image resource management

 

At the moment images used by certain Object/World nodes (e.g. ObjectGrass, ObjectTerrain, WorldClutter, WorldOccluderTerrain...) will be loaded on startup and will stay in memory.

 

In complex scenarios (e.g. a city scene with huge numbers of individual object grass/world occluder instances or large-scale tiled world with multiple ObjectTerrain instances due to float precision limitation of individual terrain objects) this quickly consumes large amounts of CPU memory even when far from player (and might also slow down world loading)

 

Idea:

 

Additional dynamic image resource management via some kind of ImageManager class similar to RenderManager with support for background image loading/caching/unloading. Access to images with something like ImageManagedPtr similar to meshes/textures

 

 

Does this make sense to you ? Shouldn't be too hard to implement as engine already provides most of the required functionality.

Link to comment

Optional resource load/unload distance for Node base class

 

Introducing node distance parameters can't solve the memory consumption problem because the node is a class with large memory imprint anyway. WorldCluster automatically places nodes around view frustum. But it can't help with background streaming.

I think a silver bullet solution is some kind of WorldCluster which handles node references with specified transformations. It should use octree with a fixed cell size and be able to enable/disable whole cells around the camera.

With such schema the background loading of node references is not a problem. OK, WorldCluster class would be refactored in future (I guess the next year).

 

Additional dynamic CPU-side image resource management

 

Big amount of grass or clutter objects with big mask images is really a problem. I will add such management system in a month or two.

Link to comment

With such schema the background loading of node references is not a problem.

 

I am a little bit surprised that node loading by background thread is not a problem. At least code sequence of World::loadNode() with internal updates of material/properties libraries, update of spatial structures, child recursion etc. doesn't seems to be be thread-safe at all.

 

What's the trick for something like World::loadNodeBackground() ?

Link to comment

We can parse node reference file and load meshes in background. After that filesystem stalls will be eliminated on creating stage.

 

Right, this together with double support would be a big step towards endless streaming worlds

Link to comment
  • 5 months later...

Additional dynamic CPU-side image resource management

 

Big amount of grass or clutter objects with big mask images is really a problem. I will add such management system in a month or two.

 

In current WorldManager image management there seems to be some issues and possibilities for render stalls. Details here

Link to comment
×
×
  • Create New...