Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batched Rendering #1023

Merged
merged 7 commits into from
Jul 16, 2024
Merged

Batched Rendering #1023

merged 7 commits into from
Jul 16, 2024

Conversation

HunterBarclay
Copy link
Member

@HunterBarclay HunterBarclay commented Jul 10, 2024

Description

WebGL attempts to give JavaScript native speeds when it comes to rendering; however, it tends to fall short due to translation and overhead with every WebGL to OpenGL call it makes. A significant gain in performance can be achieved by reducing the number of calls you make to the GPU. Enter: Batch Rendering

Batch Rendering

Normally you have buffers on your GPU when all the necessary rendering data, then you call draw on a set buffer (or buffers if you're using indexing) and it draws it to the screen. Without batching, you must make a draw call, separately, for every mesh you want to rendering. With batch rendering, you can merge multiple meshes that all use the same shader program into a single buffer, then make one draw call for multiple meshes.

If you're interesting in learning more about how batch rendering works, I strongly suggest taking a minute to watch this video from The Cherno.

Implementation Details

I separate each assembly into a BatchedMesh for each material that is used in the assembly. I work backwards, first categorizing each mesh by first material, then geometry, and finally part instance. While doing so I keep tallies to know how big the batches need to be. Then, the batches are constructed, along with a map pointing each part instance to a given set of tuples, correlating where the geometry of a given body.

Performance Improvements

System

For the following data, I used my desktop computer, which has a RTX 3060 with 12GB GDDR6, running Chrome.
To collect the data I used a combination of the Stats react component, the Chrome profiler, and a custom print out telling me the number of triangles and draw calls in a given update loop.

Testing Details

I compared this branch with the latest dev branch at the time (specific commit). In each branch, I had the default 2018 mean machine spawn in, let it fall to the ground, spawn the 2018 FRC field, keep it where it was, and then finally spawn in the 2018 mean machine robot again, and place it to the left of the scale, in front of the platform.

Branch: dev

Stat Value
Draw Calls 5343
Triangles Rendered 2.81 M
FPS ~26
Graphics Memory 362 MB

Branch: barclah/batching

Stat Value
Draw Calls 200
Triangles Rendered 2.81 M
FPS ~54
Graphics Memory 324 MB

Results

Metric +/-%
Draw Calls -96%
FPS +108%
Graphics Memory -10%

Notes

  • According to the profiler, the load is being shared more equally between the MirabufSceneObject and the SceneRenderer. This makes sense as now all the transformations are being done CPU side, and it is reducing a significant number of glUniform calls to the GPU within the renderer.
  • I have no idea why graphics memory decreased, I actually expected it to either stay the same or increase slightly.
  • The more a material is shared within an assembly, the higher the performance gains will be.

@HunterBarclay HunterBarclay self-assigned this Jul 10, 2024
@BrandonPacewic BrandonPacewic added the rendering Relating to the rendering engine or how something is rendered label Jul 11, 2024
@HunterBarclay HunterBarclay marked this pull request as ready for review July 14, 2024 08:44
@HunterBarclay HunterBarclay requested a review from a team as a code owner July 14, 2024 08:44
@HunterBarclay HunterBarclay requested review from a-crowell, Dhruv-0-Arora, PepperLola and azaleacolburn and removed request for a team July 14, 2024 08:44
Copy link
Member

@BrandonPacewic BrandonPacewic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that is certainly something...

Comment on lines 75 to 79
// obj.mirabufInstance.meshes.get(part)!.forEach(mesh => {
// // iterating through each mesh and updating their position and rotation
// mesh.position.setFromMatrixPosition(partTransform)
// mesh.rotation.setFromRotationMatrix(partTransform)
// })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving this?

Comment on lines 97 to 100
// this._mirabufInstance.meshes.get(part)!.forEach(mesh => {
// mesh.position.setFromMatrixPosition(partTransform)
// mesh.rotation.setFromRotationMatrix(partTransform)
// })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving this?

Copy link
Collaborator

@Dhruv-0-Arora Dhruv-0-Arora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the comments it looks good

Copy link
Contributor

@a-crowell a-crowell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! With two 2471s, went from 19 fps to 34.

Copy link
Member

@BrandonPacewic BrandonPacewic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So fast.....

Copy link
Contributor

@azaleacolburn azaleacolburn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Blazingly Fast 🚀

@HunterBarclay HunterBarclay merged commit e97d4f7 into dev Jul 16, 2024
12 checks passed
@HunterBarclay HunterBarclay deleted the barclah/batching branch July 16, 2024 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rendering Relating to the rendering engine or how something is rendered
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants