Skip to content

[Embedder] Support render texture for vulkan - #188855

Merged
auto-submit[bot] merged 47 commits into
flutter:masterfrom
xiaowei-guan:linux_vulkan_texture
Oct 2, 2026
Merged

auto-submit[bot] merged 47 commits into
flutter:masterfrom
xiaowei-guan:linux_vulkan_texture

Conversation

@xiaowei-guan

@xiaowei-guan xiaowei-guan commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

This PR adds external texture support for the Vulkan embedder API.

Embedders using Flutter in Vulkan mode can now register a texture frame callback and have the engine directly sample embedder-owned VkImages during composition.

Both the Impeller and Skia Vulkan backends are supported, including RGBA/BGRA formats and multi-planar YUV formats (e.g. NV12) via YCbCr conversion.

API changes (embedder.h)

  • Added FlutterVulkanExternalTexture, describing an embedder-owned VkImage handed to the engine:
    • image: handle to the VkImage, which must be in the VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL layout when provided to the engine.
    • format: the VkFormat of the image (for example VK_FORMAT_R8G8B8A8_UNORM).
    • Optional width/height (non-zero specifies the texture size).
    • Optional destruction_callback + user_data, invoked on an engine-managed thread when the texture can be collected.
  • Added FlutterVulkanTextureFrameCallback, invoked by the engine when a texture marked with a new frame available needs to be resolved. The embedder must perform a host sync before returning so the engine can sample the VkImage without additional synchronization.
  • Added external_texture_frame_callback to FlutterVulkanRendererConfig.

Engine changes

  • Added EmbedderExternalTextureVulkan (embedder_external_texture_vulkan.{h,cc}), a flutter::Texture implementation that resolves embedder textures on both backends:
    • Impeller: EmbedderExternalTextureSourceVulkan implements impeller::TextureSourceVK, creating the image view and a YUVConversionVK when the format requires YCbCr conversion.
    • Skia: wraps the VkImage into a Skia image, dynamically selecting the SkColorType based on the VkFormat.
  • Extended EmbedderExternalTextureResolver to create Vulkan external textures.
  • Wired the new callback through embedder.cc and embedder_surface_vulkan.cc.

Tests

  • Added unit tests in embedder_vk_unittests.cc covering RGBA, BGRA and NV12 textures on both Impeller and Skia, plus destruction-callback variants (RenderTextureWith*Vulkan, Render*TextureWith*Vulkan, RenderTextureWith*VulkanDestructCallback).
  • Added NV12 fixtures (texture.nv12, external_texture_nv12.png).
  • Extended TestVulkanContext and EmbedderTestContextVulkan to support external texture rendering and sampler YCbCr conversion.

Addresses: #117937

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@xiaowei-guan
xiaowei-guan requested a review from loic-sharma as a code owner July 1, 2026 13:16
@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@github-actions github-actions Bot added the engine flutter/engine related. See also e: labels. label Jul 1, 2026
@xiaowei-guan
xiaowei-guan marked this pull request as draft July 1, 2026 13:16
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@xiaowei-guan
xiaowei-guan force-pushed the linux_vulkan_texture branch from d00520d to b55309e Compare July 20, 2026 07:23
Comment thread engine/src/flutter/shell/platform/embedder/embedder.h
@loic-sharma loic-sharma added the CICD Run CI/CD label Jul 20, 2026
@xiaowei-guan xiaowei-guan changed the title [Embedder] Support render texture for vulkan + impeller [Embedder] Support render texture for vulkan Aug 3, 2026
@xiaowei-guan
xiaowei-guan force-pushed the linux_vulkan_texture branch from b55309e to a4618a8 Compare August 3, 2026 10:01
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Aug 3, 2026
@xiaowei-guan
xiaowei-guan marked this pull request as ready for review September 3, 2026 02:34
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@xiaowei-guan
xiaowei-guan marked this pull request as draft September 3, 2026 02:43
@xiaowei-guan
xiaowei-guan marked this pull request as ready for review September 3, 2026 07:51

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

Copy link
Copy Markdown
Contributor

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 support for external Vulkan textures in the Flutter embedder API, adding the necessary structures, callbacks, and resolver classes to handle texture rendering across both Skia and Impeller backends, including YUV/YCbCr conversion support. Feedback on the changes highlights several critical issues and improvements: correcting a function signature mismatch for the destruction callback to prevent undefined behavior and CFI crashes, respecting the freeze parameter during painting to avoid resolving new frames, adding a null check for the command buffer in the Impeller texture resolver, simplifying the YUV conversion check, and querying vkGetPhysicalDeviceFeatures2KHR as a fallback on Vulkan 1.0 devices to ensure compatibility.

Comment thread engine/src/flutter/shell/platform/embedder/embedder.h
Comment thread engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc Outdated
Comment thread engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc Outdated
@loic-sharma

loic-sharma commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

FYI I'm out on vacation for the next two weeks.

cc @andywolff @gaaclarke @mboetger This PR - which adds support for external Vulkan textures to the embedder API - is ready for review. This is a prerequisite for Android to migrate to the embedder API.

If there are any ABI concerns for the embedder API, please also get a review from @cbracken.

@mboetger

mboetger commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

FYI I'm out on vacation for the next two weeks.

cc @andywolff @gaaclarke @mboetger This PR - which adds support for external Vulkan textures to the embedder API - is ready for review. This is a prerequisite for Android to migrate to the embedder API.

If there are any ABI concerns for the embedder API, please also get a review from @cbracken.

Awesome. This actually aligns with the work that I have done: prototype embedder api.

The biggest divergences in the Embedder API:

I'm curious what @andywolff and @gaaclarke have to say though.

@andywolff andywolff left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I read through the ABI setup, struct versioning, and lifecycle management, and those parts make sense to me. Using struct_size alongside SAFE_ACCESS handles versioning cleanly. This will also allow appending Android-specific fields like external_format later for the embedder migration @mboetger mentioned without breaking backward compatibility. Keeping embedder.h self-contained without direct <vulkan/vulkan.h> includes avoids header leakage across the C ABI. Using VoidCallback with user data batons keeps the cleanup callback signatures consistent. The RAII destruction callbacks ensure resources are freed across normal rendering paths and early failure exits. The physical device feature query in Skia also properly enables samplerYcbcrConversion.

I have a few comments with suggestions on specific areas. I suggest clarifying texture usage and layout expectations to avoid per-frame queue submission overhead in Impeller. I also suggest ensuring parity between Skia and Impeller on multi-planar YUV format handling and BGRA color type mapping, along with adding unit tests for those paths.

Comment thread engine/src/flutter/shell/platform/embedder/embedder.h Outdated
Comment thread engine/src/flutter/shell/platform/embedder/embedder.h
Comment thread engine/src/flutter/shell/platform/embedder/embedder.h
Comment thread engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc Outdated
Comment thread engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc Outdated
Comment thread engine/src/flutter/shell/platform/embedder/embedder_external_texture_vulkan.cc Outdated

@andywolff andywolff left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for responding to my feedback. I have a few more small comments

Comment thread engine/src/flutter/testing/test_vulkan_context.cc Outdated
Comment thread engine/src/flutter/shell/platform/embedder/embedder.h Outdated

@jwinarske jwinarske left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two things worth resolving before this lands. Both are in the public API rather than the implementation, so they are cheaper to change now than after embedders ship against it.

1. No synchronization contract for the embedder→engine hand-off.

The doc states the image must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL when handed over, but nothing says when the embedder's writes to it become visible. There is no semaphore or fence in the struct, and no sync in either resolve path.

The producers this exists for are cameras and video decoders, writing on their own queue or in another process. Without an ordering guarantee the engine can sample a frame mid-write.

This engine's Vulkan API already states such a contract — in the other direction:

/// The callback invoked when a VkImage has been written to and is ready for
/// use by the embedder. 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;

and for compositor layers:

/// The engine will perform a host sync for all layers prior to calling the
/// compositor present callback, and so the written layer images can be freely
/// bound by the embedder without any additional synchronization.

So engine→embedder is an explicit, documented host sync. This PR is the reciprocal direction and documents no obligation: the embedder is told which layout to leave the image in, but not that its writes must have retired before it returns.

Two ways to close it:

  1. Document the reciprocal contract — the embedder must host-sync before returning from the callback — matching the wording already used for present_image_callback. Costs nothing in the API and makes correct embedders possible today.
  2. Carry an acquire semaphore in the struct, letting the producer stay on the GPU.

(1) is consistent with what the rest of the Vulkan embedder API promises and is probably the right scope here. (2) is the better long-term answer for camera and video, and is the reason to at least reserve the field now rather than break the struct later.

For the record, Metal is not a counterexample: FlutterMetalExternalTexture carries no synchronization primitive either and EmbedderExternalTextureMetal::ResolveTexture does no synchronization, so it has the same gap rather than a solution to borrow.

2. struct_size is never validated.

The struct carries struct_size, but the returned texture is read unconditionally on both paths — texture->width, ->height, ->format, ->destruction_callback. SAFE_ACCESS appears twice in the diff and both are on vulkan_config/args, never on the callback's result.

An embedder compiled against an earlier header returns a shorter struct and the engine reads past it. That is the case struct_size exists for, and the rest of embedder.h guards it consistently. Suggest SAFE_ACCESS on each field read, matching the other resolvers.

Minor, while here:

  • ResolveTextureImpeller binds auto& impeller_context = impeller::ContextVK::Cast(...) and never uses it; the code below goes through aiks_context->GetContext() directly.
  • The PR description is still the template (*Replace this paragraph...*).

Nice to see both ResolveTextureSkia and ResolveTextureImpeller implemented, and NV12 covered with a fixture — the Vulkan paths in the embedder have a habit of landing Skia-only.

cbracken
cbracken previously approved these changes Sep 30, 2026

@cbracken cbracken left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM for the embedder ABI side of things! (Sorry, was out last week)

I haven't looked at any of the rest, purely just the usual ABI-stability/evolvability suspects :)

@cbracken cbracken added the CICD Run CI/CD label Sep 30, 2026
@andywolff

andywolff commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Thanks! Looks like fuchia tests are failing because they think two of the variables are unused. Please fix

[9501/9617] ACTION //flutter/shell/platform/fuchsia/flutter:ui_tests__package__archive-metadata(//build/toolchain/fuchsia:fuchsia)
[9502/9617] CXX obj/flutter/shell/platform/embedder/tests/embedder_unittests_library.embedder_test_context_vulkan.o
FAILED: obj/flutter/shell/platform/embedder/tests/embedder_unittests_library.embedder_test_context_vulkan.o 
../../../flutter/buildtools/linux-x64/reclient/rewrapper --cfg=../../../flutter/build/rbe/rewrapper-linux-x64.cfg --exec_root=../../../ --server_address=unix:///b/s/w/ir/x/w/rc/rbenlfdo4pn/reproxy.sock --exec_strategy=remote_local_fallback --remote_wrapper=../../../flutter/build/rbe/remote_wrapper_linux.sh --local_wrapper=../../../flutter/build/rbe/local_wrapper.sh --labels=type=compile,compiler=clang,lang=cpp --inputs=//flutter/buildtools/linux-x64/clang/include/aarch64-unknown-fuchsia/c++/v1/__config_site ../../../flutter/buildtools/linux-x64/clang/bin/clang++ -MMD -MF obj/flutter/shell/platform/embedder/tests/embedder_unittests_library.embedder_test_context_vulkan.o.d  -DUSE_OPENSSL=1 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DFUCHSIA_SDK_VERSION=33.20260927.4.1 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -DSHELL_ENABLE_SOFTWARE -DSHELL_ENABLE_VULKAN -DSK_FONTMGR_FREETYPE_EMPTY_AVAILABLE -DSK_TYPEFACE_FACTORY_FREETYPE -DSK_FONTMGR_FUCHSIA_AVAILABLE -DSK_VULKAN -DSK_CODEC_ENCODES_JPEG -DSK_CODEC_ENCODES_PNG -DSK_CODEC_ENCODES_PNG_WITH_LIBPNG -DSK_CODEC_ENCODES_WEBP -DSK_CODEC_DECODES_JPEG -DSK_CODEC_DECODES_PNG -DSK_CODEC_DECODES_ICO -DSK_CODEC_DECODES_PNG_WITH_LIBPNG -DSK_CODEC_DECODES_WEBP -DSK_HAS_WUFFS_LIBRARY -DSK_CODEC_DECODES_GIF -DSK_XML -DIMPELLER_DEBUG=1 -DFLUTTER_RUNTIME_MODE_DEBUG=1 -DFLUTTER_RUNTIME_MODE_PROFILE=2 -DFLUTTER_RUNTIME_MODE_RELEASE=3 -DFLUTTER_RUNTIME_MODE_JIT_RELEASE=4 -DDART_LEGACY_API=\[\[deprecated\]\] -DFLUTTER_RUNTIME_MODE=2 -DVK_USE_PLATFORM_FUCHSIA -DSK_DISABLE_LEGACY_INIT_DECODERS -DSK_ENABLE_DUMP_GPU -DSK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER -DSK_DISABLE_LEGACY_MOCK_BACKENDSURFACE -DSK_DISABLE_LEGACY_SHADERCONTEXT -DSK_DISABLE_LOWP_RASTER_PIPELINE -DSK_FORCE_RASTER_PIPELINE_BLITTER -DSK_METAL_WAIT_UNTIL_SCHEDULED -DSK_R32_SHIFT=16 -DSK_ENABLE_PRECOMPILE -DSK_GANESH -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DUSE_CHROMIUM_ICU=1 -DU_ENABLE_TRACING=1 -DU_ENABLE_RESOURCE_TRACING=0 -DU_STATIC_IMPLEMENTATION -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE -DRAPIDJSON_HAS_STDSTRING -DRAPIDJSON_HAS_CXX11_RANGE_FOR -DRAPIDJSON_HAS_CXX11_RVALUE_REFS -DRAPIDJSON_HAS_CXX11_TYPETRAITS -DRAPIDJSON_HAS_CXX11_NOEXCEPT -DSK_ENABLE_PARAGRAPH -DSK_UNICODE_AVAILABLE -DSK_UNICODE_ICU_IMPLEMENTATION -I../../../flutter/shell/platform/embedder -I../../.. -Igen -I../../../flutter -I../../../flutter/third_party/vulkan-deps/vulkan-headers/src/include -I../../../flutter/third_party/skia -I../../../third_party/fuchsia-sdk/sdk/pkg/vulkan/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fdio/include -I../../../third_party/fuchsia-sdk/sdk/pkg/trace-engine/include -I../../../third_party/fuchsia-sdk/sdk/pkg/async/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fit/include -I../../../third_party/fuchsia-sdk/sdk/pkg/stdcompat/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fit-promise/include -I../../../third_party/fuchsia-sdk/sdk/pkg/trace-engine-headersonly/include -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.diagnostics.types/fidl/cpp -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_cpp_v2/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_base/include -I../../../third_party/fuchsia-sdk/sdk/pkg/utf-utils/include -I../../../third_party/fuchsia-sdk/sdk/pkg/zx/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_cpp_base_v2/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_cpp_wire/include -I../../../third_party/fuchsia-sdk/sdk/pkg/async-cpp/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl/include -I../../../third_party/fuchsia-sdk/sdk/pkg/sync/include -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger/fidl/cpp -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.diagnostics/fidl/hlcpp -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.diagnostics.types/fidl/hlcpp -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_cpp/include -I../../../third_party/fuchsia-sdk/sdk/pkg/async-default/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_cpp_sync/include -I../../../third_party/fuchsia-sdk/sdk/pkg/fidl_cpp_base/include -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem/fidl/hlcpp -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.diagnostics/fidl/cpp -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem/fidl/cpp -I../../../third_party/fuchsia-sdk/sdk/pkg/async-loop-cpp/include -I../../../third_party/fuchsia-sdk/sdk/pkg/async-loop/include -I../../../third_party/fuchsia-sdk/sdk/pkg/async-loop-default/include -I../../../third_party/fuchsia-sdk/sdk/pkg/component_incoming_cpp/include -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.io/fidl/cpp -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.unknown/fidl/hlcpp -Igen/third_party/fuchsia-sdk/sdk/fidl/fuchsia.unknown/fidl/cpp -I../../../third_party/fuchsia-sdk/sdk/pkg/syslog_cpp/include -I../../../third_party/fuchsia-sdk/sdk/pkg/backend_fuchsia_globals/include -I../../../third_party/fuchsia-sdk/sdk/pkg/syslog_structured_backend/include -I../../../third_party/fuchsia-sdk/sdk/pkg/trace/include -I../../../third_party/fuchsia-sdk/sdk/pkg/trace-headersonly/include -I../../../flutter/txt/src -I../../../third_party/abseil-cpp -Igen/flutter -Igen/flutter/impeller/runtime_stage -I../../../flutter/third_party/flatbuffers/include -I../../../flutter/third_party/harfbuzz/src -I../../../flutter/third_party/icu/source/common -I../../../flutter/third_party/icu/source/i18n -I../../../flutter/third_party/rapidjson -I../../../flutter/third_party/rapidjson/include -I../../../flutter/third_party -I../../../flutter/third_party/dart/runtime -I../../../flutter/third_party/dart/runtime/include -I../../../flutter/third_party/skia/modules/skparagraph/include -I../../../flutter/third_party/skia/modules/skunicode/include -I../../../flutter/third_party/googletest/googlemock/include -I../../../flutter/third_party/googletest/googletest/include -fno-strict-aliasing -fstack-protector --param=ssp-buffer-size=8 -fcolor-diagnostics --target=aarch64-unknown-fuchsia -ffuchsia-api-level=31 -Wall -Wextra -Wendif-labels -Wno-missing-field-initializers -Wno-unused-parameter -Werror -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-psabi -Wno-implicit-int-float-conversion -Wno-deprecated-copy -Wno-deprecated-literal-operator -Wno-unqualified-std-cast-call -Wno-nontrivial-memcall --sysroot=../../../third_party/fuchsia-sdk/sdk/obj/arm64-api-31/sysroot -no-canonical-prefixes -fvisibility=hidden -Wstring-conversion -Wnewline-eof -Oz -fno-ident -fdata-sections -ffunction-sections -g2 -Wunreachable-code -Wno-redundant-parens -Wno-newline-eof -fvisibility-inlines-hidden -std=c++20 -Wno-deprecated-this-capture -fno-modules -Xclang -fno-cxx-modules -fno-rtti -fno-exceptions -Wno-inconsistent-missing-override -c ../../../flutter/shell/platform/embedder/tests/embedder_test_context_vulkan.cc -o obj/flutter/shell/platform/embedder/tests/embedder_unittests_library.embedder_test_context_vulkan.o
../../../flutter/shell/platform/embedder/tests/embedder_test_context_vulkan.cc:33:20: error: unused variable 'kInstanceExtensionCount' [-Werror,-Wunused-variable]
   33 |   constexpr size_t kInstanceExtensionCount =
      |                    ^~~~~~~~~~~~~~~~~~~~~~~
../../../flutter/shell/platform/embedder/tests/embedder_test_context_vulkan.cc:39:20: error: unused variable 'kDeviceExtensionCount' [-Werror,-Wunused-variable]
   39 |   constexpr size_t kDeviceExtensionCount =
      |                    ^~~~~~~~~~~~~~~~~~~~~
2 errors generated.

@andywolff andywolff left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See my previous comment about unused variables breaking CI

@xiaowei-guan

Copy link
Copy Markdown
Contributor Author

See my previous comment about unused variables breaking CI

Done

@andywolff andywolff added the CICD Run CI/CD label Sep 30, 2026

@andywolff andywolff left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

google testing was stuck in a failure loop again so I overwrote it. But Dashboard Checks are all passing now, so LGTM

@andywolff

Copy link
Copy Markdown
Contributor

@gaaclarke this is ready for you to take another look, please do

@andywolff andywolff added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 1, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Oct 2, 2026
Merged via the queue into flutter:master with commit 4db99a7 Oct 2, 2026
41 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 2, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Oct 2, 2026
flutter/flutter@e89fd0a...d03768e

2026-10-02 [email protected] Roll Skia from 7b7326917e77 to 9e88bf828078 (8 revisions) (flutter/flutter#193694)
2026-10-02 [email protected] [Widget Preview] Provide descriptive error when widget preview is unconstrained (flutter/flutter#193005)
2026-10-02 [email protected] Roll Dart SDK from 0e7642b85457 to ac1a97aae47d (26 revisions) (flutter/flutter#193692)
2026-10-02 [email protected] Remove unused Fuchsia sysmem header files (flutter/flutter#193244)
2026-10-02 [email protected] [Windows] Preserve composing extent in setEditingState (flutter/flutter#189968)
2026-10-02 [email protected] [docs] Make Border.symmetric docs more explicit about their arguments (flutter/flutter#193222)
2026-10-02 [email protected] [Embedder] Support render texture for vulkan (flutter/flutter#188855)
2026-10-02 [email protected] Updated Remaining Engine Defaults to SDK 37 (flutter/flutter#190429)
2026-10-02 [email protected] Document that enableSuggestions: false can disable keyboard languages on Android (flutter/flutter#192714)
2026-10-02 [email protected] [flutter_tools] Explicitly track host CPU architecture in command result analytics (flutter/flutter#191836)
2026-10-02 [email protected] [web] Preserve DOM focus on role update and honor isAccessibilityFocusBlocked (flutter/flutter#192963)
2026-10-02 [email protected] [flutter_tools] Include base href in web hot reload script paths (flutter/flutter#193678)
2026-10-02 [email protected] [Impeller] Deduplicate GLES render pass state (flutter/flutter#193427)
2026-10-02 [email protected] Roll Skia from f2d68e0b8863 to 7b7326917e77 (16 revisions) (flutter/flutter#193676)
2026-10-01 [email protected] Fix analysis failures due to missing `const` (flutter/flutter#193685)
2026-10-01 [email protected] Removes a11y_assessment app (flutter/flutter#193671)
2026-10-01 [email protected] test: configure Xvfb and openbox for windowing_test (flutter/flutter#193529)
2026-10-01 [email protected] Sync CHANGELOG.md from stable (flutter/flutter#193666)
2026-10-01 [email protected] Avoid using relative path in Process.start (flutter/flutter#193664)
2026-10-01 [email protected] [AGP 9.1.0 Migration #6] Deliver Flutter assets as a generated assets source directory on the app path (flutter/flutter#192488)
2026-10-01 [email protected] ci(bringup): android_java17_build_android_host_app_with_module_aar is green (flutter/flutter#193580)
2026-10-01 [email protected] [flutter_tools] Fix Use dependency graph to determine plugin initialization order (flutter/flutter#191591)
2026-10-01 [email protected] [flutter_tools] Migrate DaemonCommand and Daemon domains to constructor DI (flutter/flutter#193542)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
jwinarske added a commit to toyota-connected/ivi-homescreen that referenced this pull request Oct 9, 2026
Adopt the Vulkan external texture embedder API from flutter/flutter#188855
so plugins can hand the engine a VkImage on the Vulkan backends, the
counterpart of kFlutterDesktopGpuSurfaceTypeGlTexture2D on EGL.

API
- embedder.h: add FlutterVulkanExternalTexture,
  FlutterVulkanTextureFrameCallback and
  FlutterVulkanRendererConfig::external_texture_frame_callback, verbatim
  from the merged upstream header.
- flutter_texture_registrar.h: new kFlutterDesktopGpuSurfaceTypeVkImage;
  the descriptor's handle points to a FlutterDesktopVulkanImage
  {VkImage, VkFormat}. The GPU-surface callback runs on the raster thread
  on every resolve, so a producer can cycle images. The header documents
  the full contract: device, layout, host sync, image lifetime, supported
  formats, and asynchronous unregistration.

Resolve and lifetime (flutter_desktop_vk_texture.{h,cc})
- The plugin callback runs with no registrar lock held, so it may
  host-sync or (un)register textures without stalling or deadlocking
  other plugins.
- Each frame handed to the engine carries an embedder token instead of
  the plugin's release context. The plugin's release_callback fires
  exactly once even if the engine reports a frame twice (its Skia path
  can: BorrowTextureFrom releases on failure and the engine releases
  again).
- Unregistration completes only after the engine has released every
  frame and no plugin callback is running, so a plugin cannot free an
  image the engine is still sampling. With a completion callback it
  never blocks; without one it waits for an in-flight callback (not a
  re-entrant one) and warns if the engine still holds frames.
- Rejects formats the engine cannot sample on both renderers, YCbCr
  formats unless the device enabled samplerYcbcrConversion (creating a
  conversion without it is undefined behavior), and sizes beyond
  maxImageDimension2D. A rejected frame goes straight back to the
  plugin.
- The token table is leaked so engine threads releasing frames during
  exit() never touch a destroyed map; tokens skip 0 and any still in use
  after a 32-bit wrap.

Backends
- wayland_vulkan, drm_kms_vulkan, headless_vulkan: wire the callback.
  BackendVulkanContext reports sampler_ycbcr_conversion (wayland_vulkan
  enables it when supported; the others do not request it).
- wayland_vulkan set vulkan.struct_size to sizeof(FlutterRendererConfig);
  it now uses sizeof(FlutterVulkanRendererConfig).

Tests
- vk_external_texture-test (21 cases, no GPU or GL): resolve,
  validation, ABI bounds, idempotent release, deferred and re-entrant
  unregistration, lock-free callback. Clean under TSan and ASan+UBSan.

On an engine without #188855 the config field is ignored and VkImage
textures register but never resolve. Pixel-buffer textures still
resolve only on GL backends.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
jwinarske added a commit to toyota-connected/ivi-homescreen that referenced this pull request Oct 9, 2026
Adopt the Vulkan external texture embedder API from flutter/flutter#188855
so plugins can hand the engine a VkImage on the Vulkan backends, the
counterpart of kFlutterDesktopGpuSurfaceTypeGlTexture2D on EGL.

API
- embedder.h: add FlutterVulkanExternalTexture,
  FlutterVulkanTextureFrameCallback and
  FlutterVulkanRendererConfig::external_texture_frame_callback, verbatim
  from the merged upstream header.
- flutter_texture_registrar.h: new kFlutterDesktopGpuSurfaceTypeVkImage;
  the descriptor's handle points to a FlutterDesktopVulkanImage
  {VkImage, VkFormat}. The GPU-surface callback runs on the raster thread
  on every resolve, so a producer can cycle images. The header documents
  the full contract: device, layout, host sync, image lifetime, supported
  formats, and asynchronous unregistration.

Resolve and lifetime (flutter_desktop_vk_texture.{h,cc})
- The plugin callback runs with no registrar lock held, so it may
  host-sync or (un)register textures without stalling or deadlocking
  other plugins.
- Each frame handed to the engine carries an embedder token instead of
  the plugin's release context. The plugin's release_callback fires
  exactly once even if the engine reports a frame twice (its Skia path
  can: BorrowTextureFrom releases on failure and the engine releases
  again).
- Unregistration completes only after the engine has released every
  frame and no plugin callback is running, so a plugin cannot free an
  image the engine is still sampling. With a completion callback it
  never blocks; without one it waits for an in-flight callback (not a
  re-entrant one) and warns if the engine still holds frames.
- Rejects formats the engine cannot sample on both renderers, YCbCr
  formats unless the device enabled samplerYcbcrConversion (creating a
  conversion without it is undefined behavior), and sizes beyond
  maxImageDimension2D. A rejected frame goes straight back to the
  plugin.
- The token table is leaked so engine threads releasing frames during
  exit() never touch a destroyed map; tokens skip 0 and any still in use
  after a 32-bit wrap.

Backends
- wayland_vulkan, drm_kms_vulkan, headless_vulkan: wire the callback.
  BackendVulkanContext reports sampler_ycbcr_conversion (wayland_vulkan
  enables it when supported; the others do not request it).
- wayland_vulkan set vulkan.struct_size to sizeof(FlutterRendererConfig);
  it now uses sizeof(FlutterVulkanRendererConfig).

Tests
- vk_external_texture-test (21 cases, no GPU or GL): resolve,
  validation, ABI bounds, idempotent release, deferred and re-entrant
  unregistration, lock-free callback. Clean under TSan and ASan+UBSan.

On an engine without #188855 the config field is ignored and VkImage
textures register but never resolve. Pixel-buffer textures still
resolve only on GL backends.
jwinarske added a commit to toyota-connected/ivi-homescreen that referenced this pull request Oct 9, 2026
Adopt the Vulkan external texture embedder API from flutter/flutter#188855
so plugins can hand the engine a VkImage on the Vulkan backends, the
counterpart of kFlutterDesktopGpuSurfaceTypeGlTexture2D on EGL.

API
- embedder.h: add FlutterVulkanExternalTexture,
  FlutterVulkanTextureFrameCallback and
  FlutterVulkanRendererConfig::external_texture_frame_callback, verbatim
  from the merged upstream header.
- flutter_texture_registrar.h: new kFlutterDesktopGpuSurfaceTypeVkImage;
  the descriptor's handle points to a FlutterDesktopVulkanImage
  {VkImage, VkFormat}. The GPU-surface callback runs on the raster thread
  on every resolve, so a producer can cycle images. The header documents
  the full contract: device, layout, host sync, image lifetime, supported
  formats, and asynchronous unregistration.

Resolve and lifetime (flutter_desktop_vk_texture.{h,cc})
- The plugin callback runs with no registrar lock held, so it may
  host-sync or (un)register textures without stalling or deadlocking
  other plugins.
- Each frame handed to the engine carries an embedder token instead of
  the plugin's release context. The plugin's release_callback fires
  exactly once even if the engine reports a frame twice (its Skia path
  can: BorrowTextureFrom releases on failure and the engine releases
  again).
- Unregistration completes only after the engine has released every
  frame and no plugin callback is running, so a plugin cannot free an
  image the engine is still sampling. With a completion callback it
  never blocks; without one it waits for an in-flight callback (not a
  re-entrant one) and warns if the engine still holds frames.
- Rejects formats the engine cannot sample on both renderers, YCbCr
  formats unless the device enabled samplerYcbcrConversion (creating a
  conversion without it is undefined behavior), and sizes beyond
  maxImageDimension2D. A rejected frame goes straight back to the
  plugin.
- The token table is leaked so engine threads releasing frames during
  exit() never touch a destroyed map; tokens skip 0 and any still in use
  after a 32-bit wrap.

Backends
- wayland_vulkan, drm_kms_vulkan, headless_vulkan: wire the callback.
  BackendVulkanContext reports sampler_ycbcr_conversion (wayland_vulkan
  enables it when supported; the others do not request it).
- wayland_vulkan set vulkan.struct_size to sizeof(FlutterRendererConfig);
  it now uses sizeof(FlutterVulkanRendererConfig).

Tests
- vk_external_texture-test (21 cases, no GPU or GL): resolve,
  validation, ABI bounds, idempotent release, deferred and re-entrant
  unregistration, lock-free callback. Clean under TSan and ASan+UBSan.

On an engine without #188855 the config field is ignored and VkImage
textures register but never resolve. Pixel-buffer textures still
resolve only on GL backends.

Signed-off-by: Joel Winarske <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants