Skip to content

ImDrawList: Support for large meshes (64k+ vertices) with 16-bits indices #2591

Closed
@ocornut

Description

@ocornut

Info: I'll be pushing a change to support large meshes (64k+ vertices) with 16-bits indices.

TL;DR;

  • No breakage of existing renderer back-ends.
  • New feature needs to be supported by renderer back-end. When enabled, the total mesh limit of 64k vertices doesn't apply anymore.
  • If you've been using 32-bits indices, I would appreciate if you try to revert back to 16-bit indices and use this feature (need to update your renderer).

Until now wiith 16-bits indices (default compile-time setting) the code would assert when trying to create a ImDrawList with more than 64k vertices, and visuals would get glitched.
The solution until now was to enable 32-bits indices by using #define ImDrawIdx unsigned int in imconfig.h. However some hardware and api don't support 32-bits indices and this needed to be a compile-time setting I've been asked to come with a different solution.

The new solution comes in the form of adding VtxOffset field to ImDrawCmd.

// Pre 1.71 back-ends will typically ignore the VtxOffset/IdxOffset fields. When (io.BackendFlags & ImGuiBackendFlags_HasVtxOffset) 
// is enabled, those fields allow us to render meshes larger than 64K vertices while keeping 16-bits indices.
struct ImDrawCmd
{
    [....]
    unsigned int VtxOffset; // Start offset in vertex buffer. Pre-1.71 or without ImGuiBackendFlags_HasVtxOffset: always 0. With ImGuiBackendFlags_HasVtxOffset: may be >0 to support meshes larger than 64K vertices with 16-bits indices.

The feature needs the renderer to be able to offset the base vertex number, which is not available in some api (GL ES 2) so this is optional. Making it optional also ensure zero breakage of existing changes.

The back-end needs to set:

// Renderer Back-end supports ImDrawCmd::VtxOffset. This enables output of large meshes (64K+ vertices) while still using 16-bits indices.
ImGuiBackendFlags_RendererHasVtxOffset          = 1 << 3    

Note that I've also added an IdxOffset field in ImDrawCmd, which is the equivalent of the summing of cmd->ElemCount that every render loop already did.

struct ImDrawCmd
{
    [....]
    unsigned int IdxOffset; // Start offset in index buffer. Always equal to sum of ElemCount drawn so far.

Commit for this change in core imgui is: d1e8b69
Commit for supporting this in examples renderers is: b3dd03f

Feedback welcome. I don't rule out that there may be an issue with this.

@warrenm @bear24rw Would you mind adding corresponding support in the Metal back-end? It should be very easy but as I can't test Metal at the moment. You can refer for commit b3dd03f for how it was added to the other back-ends. Thank you very much!

(EDIT Renamed new flag to ImGuiBackendFlags_RendererHasVtxOffset)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions