Skip to content

Comments

GPU Batching#695

Open
Alex2772 wants to merge 3 commits intodevelopfrom
feat/game-inventory
Open

GPU Batching#695
Alex2772 wants to merge 3 commits intodevelopfrom
feat/game-inventory

Conversation

@Alex2772
Copy link
Collaborator

@Alex2772 Alex2772 commented Feb 4, 2026

No description provided.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Alex2772, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the rendering pipeline by introducing a GPU batching system. The core change involves abstracting rendering operations into a new IBatchingRenderer interface, which queues commands rather than executing them immediately. The OpenGLRenderer now implements this interface, collecting various drawing commands (like rectangles, shadows, strings) into a buffer. These commands are then processed efficiently in a single flush operation, which is triggered at the end of a framebuffer render cycle. This approach aims to reduce OpenGL state changes and improve rendering performance.

Highlights

  • Introduction of IBatchingRenderer: A new interface IBatchingRenderer and its implementation are added, providing a mechanism to queue rendering commands.
  • OpenGLRenderer Refactoring: The OpenGLRenderer now inherits from IBatchingRenderer, collecting rendering commands and processing them in a single handleCmds call.
  • Command Batching: All direct rendering calls in OpenGLRenderer (e.g., rectangle, string) are now prefixed with render (e.g., renderRectangle, renderString) and are invoked via a std::visit on a std::variant of command structs.
  • New Game Inventory Example: A new UI example demonstrating a game inventory is added, showcasing the framework's capabilities.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • aui.views/src/AUI/GL/IBatchingRenderer.cpp
    • Implemented the command recording logic for various rendering primitives.
  • aui.views/src/AUI/GL/IBatchingRenderer.h
    • Defined the IBatchingRenderer interface, including command structs for different drawing operations and a std::variant to hold them.
  • aui.views/src/AUI/GL/OpenGLRenderer.cpp
    • Modified to implement the handleCmds method, which uses std::visit to dispatch batched commands to their respective rendering functions.
    • Existing rendering methods were renamed to renderX (e.g., renderRectangle).
  • aui.views/src/AUI/GL/OpenGLRenderer.h
    • Updated OpenGLRenderer to inherit from IBatchingRenderer.
    • Declared the new renderX helper methods.
  • aui.views/src/AUI/Platform/OpenGLRenderingContext.cpp
    • Added a call to mRenderer->flush() within endFramebuffer() to ensure all batched commands are executed.
  • examples/ui/game_inventory/CMakeLists.txt
    • Added CMake configuration for the new game_inventory example.
  • examples/ui/game_inventory/src/main.cpp
    • Introduced a new example application demonstrating a game inventory UI, utilizing the AUI framework's declarative UI and rendering capabilities.
Activity
  • The author, Alex2772, initiated a significant refactoring of the rendering system.
  • The core changes involve introducing a new IBatchingRenderer abstraction.
  • OpenGLRenderer was updated to conform to this new batching paradigm.
  • A new example game_inventory was added to showcase the UI framework.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a batching renderer to improve GPU performance by reducing the number of draw calls. The overall approach is solid, but I've found a critical issue with the implementation of stencil mask operations that would break masking functionality. I've provided detailed comments and suggestions to fix this. Additionally, there's a minor inconsistency in the use of std::move that should be addressed for code clarity. A new example for a game inventory UI has been added, which is a great way to showcase the framework's capabilities. I've also found a potential performance issue in the new example where flagRedraw() is called on every frame, which could lead to unnecessary CPU usage.

Comment on lines 122 to 124
void IBatchingRenderer::pushMaskAfter() {
mCmds.emplace_back(CmdPushMask{});
}

Choose a reason for hiding this comment

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

critical

This is part of a critical bug in the masking implementation. pushMaskAfter() should queue a distinct command (CmdPushMaskAfter) instead of CmdPushMask. Reusing CmdPushMask causes pushMaskAfter() to be handled as pushMaskBefore(), which is incorrect. Please see my other comments on this topic for the full context and fix.

Suggested change
void IBatchingRenderer::pushMaskAfter() {
mCmds.emplace_back(CmdPushMask{});
}
void IBatchingRenderer::pushMaskAfter() {
mCmds.emplace_back(CmdPushMaskAfter{});
}

Comment on lines 130 to 132
void IBatchingRenderer::popMaskAfter() {
mCmds.emplace_back(CmdPopMask{});
}

Choose a reason for hiding this comment

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

critical

Similar to pushMaskAfter, popMaskAfter() should queue a distinct command (CmdPopMaskAfter) to differentiate it from popMaskBefore(). Reusing CmdPopMask here is incorrect and will lead to broken masking behavior.

Suggested change
void IBatchingRenderer::popMaskAfter() {
mCmds.emplace_back(CmdPopMask{});
}
void IBatchingRenderer::popMaskAfter() {
mCmds.emplace_back(CmdPopMaskAfter{});
}

Comment on lines 112 to 113
struct CmdPushMask {};
struct CmdPopMask {};

Choose a reason for hiding this comment

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

critical

The masking logic is broken because there are no distinct command types for pushMaskAfter and popMaskAfter. This causes them to be handled incorrectly. You should add CmdPushMaskAfter and CmdPopMaskAfter command structs to fix this.

    struct CmdPushMask {};
    struct CmdPushMaskAfter {};
    struct CmdPopMask {};
    struct CmdPopMaskAfter {};

Comment on lines 121 to 123
using Cmd = std::variant<CmdRectangle, CmdRoundedRectangle, CmdRectangleBorder, CmdRoundedRectangleBorder,
CmdBoxShadow, CmdBoxShadowInner, CmdString, CmdLines, CmdPoints, CmdLinesPairs,
CmdSquareSector, CmdPushMask, CmdPopMask, CmdSetBlending, CmdNewRenderViewToTexture, CmdSetWindow>;

Choose a reason for hiding this comment

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

critical

To complete the fix for the broken masking logic, the Cmd variant needs to be updated to include the new CmdPushMaskAfter and CmdPopMaskAfter types.

    using Cmd = std::variant<CmdRectangle, CmdRoundedRectangle, CmdRectangleBorder, CmdRoundedRectangleBorder,
                             CmdBoxShadow, CmdBoxShadowInner, CmdString, CmdLines, CmdPoints, CmdLinesPairs,
                             CmdSquareSector, CmdPushMask, CmdPushMaskAfter, CmdPopMask, CmdPopMaskAfter, CmdSetBlending, CmdNewRenderViewToTexture, CmdSetWindow>;

Comment on lines 297 to 298
[&](const CmdPushMask&) { renderPushMaskBefore(); },
[&](const CmdPopMask&) { renderPopMaskBefore(); },

Choose a reason for hiding this comment

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

critical

The handlers for mask commands are incomplete, which will break masking functionality. You are missing handlers for CmdPushMaskAfter and CmdPopMaskAfter. You should add them to call renderPushMaskAfter() and renderPopMaskAfter() respectively.

            [&](const CmdPushMask&) { renderPushMaskBefore(); },
            [&](const CmdPushMaskAfter&) { renderPushMaskAfter(); },
            [&](const CmdPopMask&) { renderPopMaskBefore(); },
            [&](const CmdPopMaskAfter&) { renderPopMaskAfter(); },


void render(ARenderContext context) override {
AWindow::render(context);
flagRedraw();

Choose a reason for hiding this comment

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

high

Calling flagRedraw() unconditionally in every render call will cause the application to redraw on every frame, even when nothing has changed. This can lead to unnecessary CPU and GPU usage, which is especially problematic on battery-powered devices. You should only flag for a redraw when the state of the UI actually changes.


void IBatchingRenderer::rectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size) {
mCmds.emplace_back(CmdRectangle{
.brush = std::move(brush),

Choose a reason for hiding this comment

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

medium

The use of std::move(brush) here is inconsistent with other methods in this file that also take a const ABrush& and simply copy it (e.g., roundedRectangle). Since brush is a const reference, std::move performs a copy anyway, but it can be misleading to future readers of the code. For consistency and clarity, it's better to just use brush for the assignment.

Suggested change
.brush = std::move(brush),
.brush = brush,

everything is fine except fonts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant