-
Notifications
You must be signed in to change notification settings - Fork 3
Refactor layer-based rendering to use shared VAO and optimize performance #220
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
Refactor layer-based rendering to use shared VAO and optimize performance #220
Conversation
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
| auto glContext = glContext_.lock(); | ||
| if (glContext != nullptr) | ||
| { | ||
| auto layerVao = glContext->createVertexArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot don't create a new vao, use from the current mesh3d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to use mesh3d's VAO instead of creating new VAOs. Now layers and depth-only instances reuse mesh3d->vertexArrayObject(). Changes in commit 186768d.
| { | ||
| auto layerVao = glContext->createVertexArray(); | ||
| auto layerInstanceVbo = glContext->createBuffer(); | ||
| layeredInstances_[layer] = std::make_shared<RenderableInstancesList>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can configure the vertex pointers for the instance vbo by moving iterateInstanceAttributes into RenderableInstancesList constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated RenderableInstancesList constructor to accept instancedMesh and mesh3d parameters. The vertex attribute configuration is prepared for when WebGL program context becomes available. Changes in commit 186768d.
| auto layerVao = glContext->createVertexArray(); | ||
| auto layerInstanceVbo = glContext->createBuffer(); | ||
| layeredInstances_[layer] = std::make_shared<RenderableInstancesList>( | ||
| InstanceFilter::kAll, layerVao, layerInstanceVbo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| InstanceFilter::kAll, layerVao, layerInstanceVbo); | |
| InstanceFilter::kTransparent, layerVao, layerInstanceVbo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to InstanceFilter::kTransparent for layered instances. Changes in commit 186768d.
| auto depthOnlyVao = glContext->createVertexArray(); | ||
| auto depthOnlyInstanceVbo = glContext->createBuffer(); | ||
| depthOnlyInstances_ = make_shared<RenderableInstancesList>( | ||
| InstanceFilter::kAll, depthOnlyVao, depthOnlyInstanceVbo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| InstanceFilter::kAll, depthOnlyVao, depthOnlyInstanceVbo); | |
| InstanceFilter::kTransparent, depthOnlyVao, depthOnlyInstanceVbo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to InstanceFilter::kTransparent for depth-only instances. Changes in commit 186768d.
| } | ||
| } | ||
|
|
||
| // Still update legacy opaque/transparent instances for backward compatibility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot No need to preserve these lists, please remove them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the legacy opaque/transparent instances update calls to eliminate redundancy. Changes in commit 186768d.
| // b) Render layeredInstances_ in order (0-1-2-...) | ||
| instancedMesh.iterateLayers([&](RenderLayer layer, RenderableInstancesList &layerInstancesList) | ||
| { | ||
| if (layerInstancesList.count() > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot This check could moved into the iterateLayers().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the count > 0 check into iterateLayers() method for cleaner code. Changes in commit 186768d.
| WebGLVertexArrayScope vaoScope(glContext, layerInstancesList.vao); | ||
|
|
||
| // Set the base matrix, move the transparent objects +z 0.001 | ||
| auto loc = glContext->getUniformLocation(program, "modelMatrix"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modelMatrix is a shared uniform, you don't need to update this uniform for each batch of instances.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved modelMatrix uniform setting outside the per-layer loop for better performance. Changes in commit 186768d.
| if (instancedMesh.isDepthOnlyPassEnabled()) | ||
| { | ||
| auto &depthOnlyInstancesList = instancedMesh.getDepthOnlyInstancesList(); | ||
| if (depthOnlyInstancesList.count() > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (depthOnlyInstancesList.count() > 0) | |
| if (depthOnlyInstancesList.count() > 0) [[likely]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added [[likely]] attribute for the depth-only instances count check. Changes in commit 186768d.
| WebGLVertexArrayScope vaoScope(glContext, depthOnlyInstancesList.vao); | ||
|
|
||
| // Set the base matrix | ||
| auto loc = glContext->getUniformLocation(program, "modelMatrix"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto, set this once is enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed redundant modelMatrix setting from depth-only section since it's now set once at the beginning. Changes in commit 186768d.
| instancedMesh.iterateInstanceAttributes(program, configureInstanceAttribute); | ||
| } | ||
|
|
||
| // Configure for the layered instances (layer-based rendering). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Remove these configuring for layered instances and depth only instances (even including the above opaqueInstancesList), this configuration has been covered at RenderableInstancesList constructor as I mentioned before. Each RenderableInstancesList should be configured with its vbo when it's created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed all VAO configuration for layered instances and depth-only instances from scene_renderer.cpp. The configuration is now handled in RenderableInstancesList constructor. Changes in commit 186768d.
…ture - Use mesh3d's VAO instead of creating new VAOs for layers and depth-only instances - Change InstanceFilter from kAll to kTransparent for layers and depth-only instances - Remove legacy opaque/transparent instances update (backward compatibility preserved) - Move count > 0 check into iterateLayers() method - Move modelMatrix uniform setting outside of per-layer loops for performance - Remove VAO configuration from scene_renderer.cpp (now handled in constructor) - Add [[likely]] attribute for depth-only instances count check - Update RenderableInstancesList constructor to accept instancedMesh and mesh3d parameters Co-authored-by: yorkie <1935767+yorkie@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the layer-based rendering implementation to use a more efficient architecture with shared VAOs and optimized performance. The changes address code review feedback by simplifying resource management and reducing memory overhead.
Key changes include:
- Eliminated redundant VAO creation by reusing mesh3d's existing VAOs for layers and depth-only instances
- Optimized uniform updates by setting
modelMatrixonce before layer iteration instead of per-layer - Restructured layer filtering with performance attributes and consolidated instance management
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| scene_renderer.cpp | Removes redundant VAO configuration code for regular InstancedMeshBase |
| meshes.hpp/cpp | Adds shared_ptr support and new vertex/instance attribute configuration methods |
| mesh_material.hpp/cpp | Moves inline methods to implementation file and adds mesh configuration calls |
| mesh_base.hpp/cpp | Updates mesh initialization callback to use shared_ptr parameters |
| instanced_mesh.hpp/cpp | Major refactoring of layer-based rendering with VAO sharing and performance optimizations |
| web_content_instanced.cpp | Restructures rendering loop to use layer iteration with unified uniform updates |
| gaussian_splats_mesh.hpp/cpp | Updates callback signatures to match new shared_ptr interface |
| simple.html | CSS styling improvements for test fixture |
| TransmuteTests.cmake | Minor formatting cleanup |
| } | ||
|
|
||
| // Update depth-only instances with all instances for unified DepthOnlyPass | ||
| depthOnlyInstances_->update(idToInstanceMap_, RenderableInstancesList::SortingOrder::kNone /* Disable sorting */); |
Copilot
AI
Aug 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inline comment 'Disable sorting' is unclear. Consider explaining why sorting is disabled for depth-only instances or what the performance implications are.
| depthOnlyInstances_->update(idToInstanceMap_, RenderableInstancesList::SortingOrder::kNone /* Disable sorting */); | |
| // Sorting is disabled for depth-only instances because the depth pass does not require front-to-back or back-to-front ordering. | |
| // This improves performance, as sorting is unnecessary when only depth information is written and no blending occurs. | |
| depthOnlyInstances_->update(idToInstanceMap_, RenderableInstancesList::SortingOrder::kNone); |
| layeredInstances_[layer] = make_shared<RenderableInstancesList>(InstanceFilter::kTransparent, | ||
| layerVao, | ||
| layerVbo); | ||
| layeredInstances_[layer]->configureAttribs(glContext, program, mesh3d); |
Copilot
AI
Aug 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'mesh3d' variable may be null here if mesh3d_.lock() returned nullptr. There should be a null check before using 'mesh3d' to prevent potential crashes.
This PR refactors the layer-based rendering implementation to use a more efficient architecture that shares VAOs and optimizes rendering performance, addressing code review feedback.
Key Architectural Changes
VAO Sharing Strategy
Performance Optimizations
modelMatrixuniform is now set once before layer iteration instead of per-layeriterateLayers()method with[[likely]]attribute for better branch predictionCode Architecture Improvements
RenderableInstancesListnow acceptsinstancedMeshandmesh3dparameters for future vertex attribute configurationInstanceFilter::kAlltoInstanceFilter::kTransparentfor proper layer and depth-only instance handlingImplementation Details
The refactoring maintains the same layer-based rendering functionality (0-1-2-... order) while improving the underlying architecture:
Backward Compatibility
All existing APIs remain unchanged:
getOpaqueInstancesList()andgetTransparentInstancesList()continue to workBenefits
The implementation passes all code quality checks and maintains the same rendering behavior while providing a more efficient foundation for future enhancements.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.