Repository navigation
Description
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:
- 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. - 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
gaaclarke commentedon Sep 21, 2026
fyi @andywolff