Blender Git Commit Log

Git Commits -> Revision c5eba46

Revision c5eba46 by Clément Foucault (master)
February 21, 2018, 14:28 (GMT)
Gawain: Refactor: VAOs caching AND use new VAOs manager.

A major bottleneck of current implementation is the call to create_bindings() for basically every drawcalls.
This is due to the VAO being tagged dirty when assigning a new shader to the Batch, defeating the purpose of the Batch (reuse it for drawing).

Since managing hundreds of batches in DrawManager and DrawCache seems not fun enough to me, I prefered rewritting the batches itself.

--- Batch changes ---
For this to happen I needed to change the Instancing to be part of the Batch rather than being another batch supplied at drawtime.
The Gwn_VertBuffers are copied from the batch to be instanciated and a new Gwn_VertBuffer is supplied for instancing attribs.
This mean a VAO can be generated and cached for this instancing case.

A Batch can be rendered with instancing, without instancing attribs and without the need for a new VAO using the GWN_batch_draw_range_ex with the force_instance parameter set to true.

--- Draw manager changes ---
The downside with this approach is that we must track the validity of the instanced batch (the original one). For this the only way (I could think of) is to set a callback for when the batch is getting free.
This means a bit of refactor in the DrawManager with the separation of batching and instancing Batches.

--- VAO cache ---
Each VAO is generated for a given ShaderInterface. This means we can keep it alive as long as the shader interface lives.
If a ShaderInterface is discarded, it needs to destroy every VAO associated to it. Otherwise, a new ShaderInterface with the same adress could be generated and reuse the same VAO with incorrect bindings.
The VAO cache itself is using a mix between a static array of VAO and a dynamic array if the is not enough space in the static.
Using this hybrid approach is a bit more performant than the dynamic array alone.
The array will not resize down but empty entries will be filled up again. It's unlikely we get a buffer overflow from this. Resizing could be done on next allocation if needed.

--- Results ---
Using Cached VAOs means that we are not querying each vertex attrib for each vbo for each drawcall, every redraw!
In a CPU limited test scene (10000 cubes in Clay engine) I get a reduction of CPU drawing time from ~20ms to 13ms.

The only area that is not caching VAOs is the instancing from particles (see comment DRW_shgroup_instance_batch).

Commit Details:

Full Hash: c5eba46d7f4ddfcdf372a3f4968e4d170ee0a002
Parent Commit: 1b3f9ec
Lines Changed: +644, -353

15 Modified Paths:

/intern/gawain/CMakeLists.txt (+2, -0) (Diff)
/intern/gawain/gawain/gwn_batch.h (+47, -10) (Diff)
/intern/gawain/gawain/gwn_buffer_id.h (+0, -4) (Diff)
/intern/gawain/gawain/gwn_shader_interface.h (+7, -0) (Diff)
/intern/gawain/gawain/gwn_vertex_array_id.h (+2, -2) (Diff)
/intern/gawain/src/gwn_batch.c (+291, -173) (Diff)
/intern/gawain/src/gwn_buffer_id.cpp (+0, -45) (Diff)
/intern/gawain/src/gwn_immediate.c (+4, -3) (Diff)
/intern/gawain/src/gwn_shader_interface.c (+42, -0) (Diff)
/intern/gawain/src/gwn_vertex_array_id.cpp (+2, -2) (Diff)
/source/blender/draw/intern/draw_instance_data.c (+177, -61) (Diff)
/source/blender/draw/intern/draw_instance_data.h (+6, -3) (Diff)
/source/blender/draw/intern/draw_manager.c (+52, -46) (Diff)
/source/blender/draw/intern/DRW_render.h (+1, -1) (Diff)
/source/blender/draw/modes/object_mode.c (+11, -3) (Diff)
By: Miika HämäläinenLast update: Nov-07-2014 14:18MiikaHweb | 2003-2021