[Impeller] Move queue submission into a callback that is invoked by FenceWaiterVK::AddFence only if it can accept the fence#187761
Conversation
…enceWaiterVK::AddFence only if it can accept the fence The FenceWaiterVK owns the lifetime of the fences that signal completion of a Vulkan command buffer submitted through vkQueueSubmit. Prior to this PR, CommandQueueVK::Submit was submitting the command buffer to the queue with a fence before calling FenceWaiterVK::AddFence. If AddFence failed, then the fence would be destroyed even though the Vulkan driver still holds its handle. That could cause a crash when the command completes and the Vulkan driver tries to signal the fence. With this PR, the vkQueueSubmit call is moved into a callback that will be invoked by FenceWaiterVK::AddFence only if the FenceWaiterVK can take ownership of the fence. If the FenceWaiterVK has been terminated, then AddFence will skip the submit and destroy the fence. Fixes flutter#187703
There was a problem hiding this comment.
Code Review
This pull request refactors Vulkan command submission by moving the queue submission step into FenceWaiterVK::AddFence via a callback, preventing submissions if the fence waiter is terminated. Unit tests and mock Vulkan helpers are updated to verify this behavior. Feedback recommends including <functional> in fence_waiter_vk.h to support std::function and declaring default_submit_callback as const auto in the unit tests to avoid potential linker errors.
gaaclarke
left a comment
There was a problem hiding this comment.
Looking good, just a few notes.
Am I crazy or did I already submit a review on this? Did this PR get recreated? Maybe I just looked at it and didn't get a chance to submit my review =)
| EXPECT_EQ(std::find(called->begin(), called->end(), "vkQueueSubmit"), | ||
| called->end()); |
There was a problem hiding this comment.
Can you add a simple test to show that vkQueueSubmit is properly recorded too, please?
| /// the submitted command completes and the fence is signaled. | ||
| fml::Status AddFence(vk::UniqueFence fence, | ||
| std::function<fml::Status(vk::Fence)> submit_callback, | ||
| const fml::closure& completion_callback); |
There was a problem hiding this comment.
nit: we are going to store this so we could std::move it and often people put rvalues in callback parameters.
| const fml::closure& completion_callback); | |
| fml::closure completion_callback); |
| EXPECT_FALSE(waiter->AddFence(std::move(fence), nullptr)); | ||
| const auto add_status = | ||
| waiter->AddFence(std::move(fence), default_submit_callback, nullptr); | ||
| EXPECT_FALSE(add_status.ok()); |
There was a problem hiding this comment.
instead of expecting something is not ok, can you turn it to a equality assertion about what the error should be?
| namespace impeller { | ||
| namespace testing { | ||
|
|
||
| const auto default_submit_callback = [](vk::Fence) { return fml::Status(); }; |
There was a problem hiding this comment.
I think gemini's advice here wrong. I would have just put it in an anonymous namespace.
| EXPECT_FALSE(waiter->AddFence(vk::UniqueFence(), []() {})); | ||
| const auto add_status = | ||
| waiter->AddFence(vk::UniqueFence(), default_submit_callback, []() {}); | ||
| EXPECT_FALSE(add_status.ok()); |
There was a problem hiding this comment.
same here, eq test not false test.
| VALIDATION_LOG << "Failed to submit queue: " << vk::to_string(status); | ||
| return fml::Status(fml::StatusCode::kCancelled, "Failed to submit queue: "); | ||
| } | ||
| auto submit_callback = [&](vk::Fence submit_fence) { |
There was a problem hiding this comment.
"Use default capture by reference ([&]) only when the lifetime of the lambda is obviously shorter than any potential captures."
It doesn't escape the current scope, but since we are passing the lambda along instead of calling it, it's probably better to treat it that way.
| /// @brief Invokes the [submit_callback] and adds the fence to the wait set | ||
| /// if it succeeds. The [completion_callback] will be called when |
There was a problem hiding this comment.
We should specify that the submit_callback is invoked synchronously so people can reason about lifetimes of objects captured by it.
This PR is an updated variant of #187698 |
|
autosubmit label was removed for flutter/flutter/187761, because - The status or check suite Linux linux_clang_tidy has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
Oops, I said "still lgtm" I mean to say, "thanks, lgtm!" I forgot I didn't approve this one yet. |
flutter/flutter@3a0420c...b10d0f1 2026-06-17 [email protected] Skip platform-specific plugin registration if no platforms enabled (flutter/flutter#186304) 2026-06-17 [email protected] Roll Packages from 8286d39 to 6ce00a8 (1 revision) (flutter/flutter#188109) 2026-06-17 [email protected] Roll Skia from 79f93fd5f36e to 5d19002eb73e (1 revision) (flutter/flutter#188108) 2026-06-17 [email protected] Import `dart:_js_interop_wasm` in addition to `dart:_wasm` to convert between `JSAny` and `WasmExternRef?` (flutter/flutter#186974) 2026-06-17 [email protected] Roll Dart SDK from f811ecae9ca0 to e39bde5b1bfc (2 revisions) (flutter/flutter#188107) 2026-06-17 [email protected] Roll Skia from 026f6a6be2b9 to 79f93fd5f36e (1 revision) (flutter/flutter#188105) 2026-06-17 [email protected] Roll Dart SDK from 462bf0a1d489 to f811ecae9ca0 (1 revision) (flutter/flutter#188099) 2026-06-17 [email protected] Roll Fuchsia Linux SDK from VeLhhlDcod09NR4Hb... to or21OEdGtairm6nl9... (flutter/flutter#188098) 2026-06-17 [email protected] Roll Skia from 2ffd155313f5 to 026f6a6be2b9 (10 revisions) (flutter/flutter#188097) 2026-06-17 [email protected] Roll Dart SDK from 824b4b48b6d4 to 462bf0a1d489 (1 revision) (flutter/flutter#188093) 2026-06-17 [email protected] Manual Dart roll from f6c31f4c3a63 to 824b4b48b6d4 (flutter/flutter#188023) 2026-06-17 [email protected] Add a platform view test to android_hardware_smoke_test (flutter/flutter#188069) 2026-06-17 [email protected] [flutter_tools] Format empty app template with latest dart format (flutter/flutter#187443) 2026-06-16 49699333+dependabot[bot]@users.noreply.github.com Bump the all-github-actions group across 1 directory with 3 updates (flutter/flutter#188086) 2026-06-16 [email protected] Roll Skia from d7196b0b4939 to 2ffd155313f5 (9 revisions) (flutter/flutter#188081) 2026-06-16 [email protected] Prevent downgrading `project.pbxproj` when greater version number (flutter/flutter#186250) 2026-06-16 [email protected] Only allow dependabot to autoupdate GitHub-owned actions (flutter/flutter#187936) 2026-06-16 [email protected] Fall back to source AndroidManifest.xml if AAPT fails or returns garbage (flutter/flutter#187197) 2026-06-16 [email protected] Roll pub packages (flutter/flutter#187769) 2026-06-16 [email protected] [Impeller] Move queue submission into a callback that is invoked by FenceWaiterVK::AddFence only if it can accept the fence (flutter/flutter#187761) 2026-06-16 [email protected] Reland [a11y] Map some framework semantics roles to android classes. (flutter/flutter#188037) 2026-06-16 [email protected] refactor(web): Unify Image on Skwasm and CanvasKit (flutter/flutter#187873) 2026-06-16 [email protected] Adds arm64 variant of impeller devicelab tests for windows. (flutter/flutter#188053) If this roll has caused a breakage, revert this CL and stop the roller 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
…enceWaiterVK::AddFence only if it can accept the fence (flutter#187761) The FenceWaiterVK owns the lifetime of the fences that signal completion of a Vulkan command buffer submitted through vkQueueSubmit. Prior to this PR, CommandQueueVK::Submit was submitting the command buffer to the queue with a fence before calling FenceWaiterVK::AddFence. If AddFence failed, then the fence would be destroyed even though the Vulkan driver still holds its handle. That could cause a crash when the command completes and the Vulkan driver tries to signal the fence. With this PR, the vkQueueSubmit call is moved into a callback that will be invoked by FenceWaiterVK::AddFence only if the FenceWaiterVK can take ownership of the fence. If the FenceWaiterVK has been terminated, then AddFence will skip the submit and destroy the fence. Fixes flutter#187703
…enceWaiterVK::AddFence only if it can accept the fence (flutter#187761) The FenceWaiterVK owns the lifetime of the fences that signal completion of a Vulkan command buffer submitted through vkQueueSubmit. Prior to this PR, CommandQueueVK::Submit was submitting the command buffer to the queue with a fence before calling FenceWaiterVK::AddFence. If AddFence failed, then the fence would be destroyed even though the Vulkan driver still holds its handle. That could cause a crash when the command completes and the Vulkan driver tries to signal the fence. With this PR, the vkQueueSubmit call is moved into a callback that will be invoked by FenceWaiterVK::AddFence only if the FenceWaiterVK can take ownership of the fence. If the FenceWaiterVK has been terminated, then AddFence will skip the submit and destroy the fence. Fixes flutter#187703
The FenceWaiterVK owns the lifetime of the fences that signal completion of a Vulkan command buffer submitted through vkQueueSubmit.
Prior to this PR, CommandQueueVK::Submit was submitting the command buffer to the queue with a fence before calling
FenceWaiterVK::AddFence. If AddFence failed, then the fence would be destroyed even though the Vulkan driver still holds its handle. That could cause a crash when the command completes and the Vulkan driver tries to signal the fence.
With this PR, the vkQueueSubmit call is moved into a callback that will be invoked by FenceWaiterVK::AddFence only if the FenceWaiterVK can take ownership of the fence. If the FenceWaiterVK has been terminated, then AddFence will skip the submit and destroy the fence.
Fixes #187703