Improve Performance in Scenes With Many Lights #14

Merged
SeanOMik merged 8 commits from bugfix/many-lights-poor-performance into main 2024-04-24 19:55:16 -04:00
Owner

In #5, when tiled forward rendering was first implemented, I wrote a stress test example that spawned 500 point lights in Sponza. This example had poor performance. This pr aimed at fixing it.

The large slow down was not actually the forward+ renderer, but updating the transform buffer and interpolating the transforms of entities! The example originally got around 180fps in release mode. After I improved the performance of updating the transform buffers, it got around 430fps! Improving the transform interpolation improved performance by another 100fps with the example now running around 530fps.

Transform Buffer

Originally the buffer of entity transforms was updated by adding buffer writes to the wgpu::Queue. Each transform caused a write to be queued. This is understandably pretty slow when queuing everything up. The improved version writes the transforms to a large Vec in memory, then after all entities are processed, it sends this buffer to the GPU.

Some improvements that can be made:

  • Currently the transform buffer in memory is completely refilled on every frame. Instead, this buffer can keep its data every frame and certain indexes only be updated if the entity that corresponds to that index is updated. The full buffer would likely have to be sent to the GPU every frame, but this would still likely slightly improve performance.

Transform Interpolation

Interpolating transforms was very slow. I believe it was because all the interpolated transforms were stored in a HashMap and retrieved and updated every frame.

This was improved by creating an InterpTransform component that stored the last transform, and a blending alpha on the entities. These components would be created on newly discovered entities, and updated on entities that already have the components. This solution caused no noticeable impact in performance and worked great. The solution was partially discovered in bevy_mod_interp, with some modifications.

In #5, when tiled forward rendering was first implemented, I wrote a stress test example that spawned 500 point lights in Sponza. This [example had poor performance](https://git.seanomik.net/SeanOMik/lyra-engine/pulls/5#issuecomment-1107). This pr aimed at fixing it. The large slow down was not actually the forward+ renderer, but updating the transform buffer and interpolating the transforms of entities! The example originally got around 180fps in release mode. After I improved the performance of updating the transform buffers, it got around 430fps! Improving the transform interpolation improved performance by another 100fps with the example now running around 530fps. ## Transform Buffer Originally the buffer of entity transforms was updated by adding buffer writes to the `wgpu::Queue`. Each transform caused a write to be queued. This is understandably pretty slow when queuing everything up. The improved version writes the transforms to a large `Vec` in memory, then after all entities are processed, it sends this buffer to the GPU. ### Some improvements that can be made: * Currently the transform buffer in memory is completely refilled on every frame. Instead, this buffer can keep its data every frame and certain indexes only be updated if the entity that corresponds to that index is updated. The full buffer would likely have to be sent to the GPU every frame, but this would still likely slightly improve performance. ## Transform Interpolation Interpolating transforms was very slow. I believe it was because all the interpolated transforms were stored in a [`HashMap` and retrieved and updated every frame.](https://git.seanomik.net/SeanOMik/lyra-engine/src/commit/25aa902e0247bda0ce67e55bd1df6753eb270dac/lyra-game/src/render/renderer.rs#L397-L429) This was improved by creating an [`InterpTransform`](https://git.seanomik.net/SeanOMik/lyra-engine/src/branch/bugfix/many-lights-poor-performance/lyra-game/src/render/renderer.rs#L71) component that stored the last transform, and a blending alpha on the entities. These components would be created on newly discovered entities, and updated on entities that already have the components. This solution caused no noticeable impact in performance and worked great. The solution was partially discovered in [bevy_mod_interp](https://github.com/helvieq499/bevy_mod_interp/blob/master/src/system.rs), with some modifications.
SeanOMik added 8 commits 2024-04-24 18:54:45 -04:00
SeanOMik changed title from Fix for poor performance with many lights. to Improve Performance in Scenes With Many Lights 2024-04-24 18:55:11 -04:00
SeanOMik merged commit 6a11f7cbb7 into main 2024-04-24 19:55:16 -04:00
SeanOMik deleted branch bugfix/many-lights-poor-performance 2024-04-24 19:55:16 -04:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: SeanOMik/lyra-engine#14
No description provided.