Skip to content

[Embedder API] No synchronization contract for embedder-provided Vulkan images #192838

Open

Description

@jwinarske

Problem

Embedder-provided Vulkan images have no stated ordering. The engine→embedder direction does:

/// Prior to calling this callback, the engine performs a host sync, and so the
/// VkImage can be used in a pipeline by the embedder without any additional
/// synchronization.
FlutterVulkanPresentCallback present_image_callback;

Same wording on FlutterVulkanImage for compositor layers. The embedder→engine direction says nothing.

That covers FlutterVulkanBackingStore today, and FlutterVulkanExternalTexture once #188855 lands. Both tell the embedder which layout to leave the image in. Neither says when its writes have to be visible.

Not the same as the queue interposer

get_instance_proc_address_callback is documented for swapping vkQueueSubmit/vkQueueWaitIdle for locking variants, so the raster thread and the embedder do not touch one VkQueue concurrently. That is host-side mutual exclusion on the queue handle. It says nothing about when an image's contents are visible.

Worth being precise about the overlap, because it narrows this issue: an embedder that submits its producer work on the engine's own queue already gets ordering from same-queue submission plus a pipeline barrier, and needs nothing new. The gap is producers that are not on that queue — camera/ISP, video decoders, GStreamer, a different queue family, another process. Those are the cases the external-texture API exists for, and they have nothing to synchronize against.

Proposal

Either:

  1. Document the reciprocal contract — embedder must make its writes visible before returning, host sync being the simple way — in the words already used for present_image_callback. Costs nothing, makes correct embedders possible now.
  2. Carry an acquire semaphore in the struct so an off-queue producer can stay on the GPU.

(1) is consistent with the rest of the Vulkan embedder API. (2) is what camera and video actually want, and is the reason to reserve the field before embedders ship against these structs.

Metal is not a counterexample: FlutterMetalExternalTexture has no primitive either and EmbedderExternalTextureMetal::ResolveTexture does no synchronization. Same gap.

Split out of #144613. Raised on #188855 as review feedback; filing so it outlives that PR.

Activity

  1. added
    engineflutter/engine related. See also e: labels.
    e: embedderUsers of the Embedder API
    c: proposalA detailed proposal for a change to Flutter
    in triagePresently being triaged by the triage team
    and removed
    in triagePresently being triaged by the triage team
    on Sep 16, 2026
  2. added
    P2Important issues not at the top of the work list
    on Sep 21, 2026
  3. gaaclarke commented on Sep 21, 2026

    @gaaclarke
    Member
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

    P2Important issues not at the top of the work listc: proposalA detailed proposal for a change to Fluttercustomer: toyotae: embedderUsers of the Embedder APIengineflutter/engine related. See also e: labels.team-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions