Skip to content

[Flutter GPU] Add deterministic disposal for DeviceBuffer and Texture #191867

Open

Description

@ben-milanko

Use case

We are building a long-lived retained renderer with package:flutter_gpu. Navigating hundreds of image-heavy and CAD PDF pages creates and retires many immutable geometry DeviceBuffers, decoded-image Textures, transient upload buffers, and render-pass attachments.

Flutter 3.47's Dart wrappers expose no explicit lifecycle operation for DeviceBuffer or Texture. Dropping the last Dart reference therefore leaves release timing to native-wrapper finalization and garbage collection. A fast producer can retire GPU resources faster than collection runs, so it cannot enforce a deterministic native GPU memory ceiling.

Our current workaround in dart_pdf_editor_flutter_gpu is substantial:

  • pool retained geometry in power-of-two DeviceBuffer size classes under a hard byte ceiling;
  • pool host-visible transient buffers and render-pass attachments;
  • lease every pooled resource until all command buffers that reference it reach their completion callbacks;
  • retain decoded textures in a separate byte-budgeted LRU; and
  • reject a new GPU scene and fall back to Canvas when active leases leave no room under the ceiling.

Pooling is still useful for performance, but without disposal it cannot return unused resources to the device deterministically. One-shot resources that miss the pools are also finalizer-driven. Calling or encouraging gc() is not a production lifecycle API, and lowering cache limits only shifts the problem to more one-shot allocations.

I searched the Flutter tracker for DeviceBuffer, Texture dispose, and Flutter GPU resource lifetime proposals and did not find an existing issue covering deterministic release.

Proposal

Expose deterministic, idempotent release for Flutter GPU resources, for example:

abstract interface class GpuResource {
  bool get isDisposed;
  void dispose();
}

base class DeviceBuffer extends NativeFieldWrapperClass1
    implements GpuResource { ... }

base class Texture extends NativeFieldWrapperClass1
    implements GpuResource { ... }

The exact API shape is less important than these semantics:

  • native storage can be released deterministically after the caller knows all referencing GPU submissions have completed;
  • disposal is idempotent;
  • later reads, writes, binds, or submissions involving a disposed resource fail predictably;
  • behavior for an in-flight resource is explicit: either disposal defers native release until completion, throws, or documents that completion fencing is the caller's responsibility; and
  • finalization remains a safety net for resources the application forgets to dispose.

If exposing dispose() directly conflicts with command-buffer ownership, a context-owned deferred-release API keyed to a submission/completion fence would also solve the use case.

Texture ownership also needs to be clear when Texture.asImage() or Texture.fromImage() shares backing storage with ui.Image: disposing one wrapper must not invalidate storage still owned by the other. That can be reference-counted or documented as a separate ownership rule.

This capability needs to live in Flutter GPU because a package cannot release the native object associated with NativeFieldWrapperClass1. It would let applications enforce real memory budgets while keeping pooling as an optimization rather than the only way to control resource lifetime.

Activity

  1. mbcorona commented on Aug 27, 2026

    @mbcorona
    Member

    Hi @ben-milanko, thanks for the well-scoped proposal. Routing to the Flutter GPU team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: proposalA detailed proposal for a change to Flutterteam-fluttergpuOwned by Flutter GPU team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions