Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fence_waiter_vk_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6#include "gtest/gtest.h" // IWYU pragma: keep
7#include "impeller/renderer/backend/vulkan/fence_waiter_vk.h" // IWYU pragma: keep
9
10namespace impeller {
11namespace testing {
12
13namespace {
14auto default_submit_callback = [](vk::Fence) { return fml::Status(); };
15} // namespace
16
17TEST(FenceWaiterVKTest, IgnoresNullFence) {
18 auto const context = MockVulkanContextBuilder().Build();
19 auto const waiter = context->GetFenceWaiter();
20 const auto add_status =
21 waiter->AddFence(vk::UniqueFence(), default_submit_callback, []() {});
22 EXPECT_EQ(add_status.code(), fml::StatusCode::kInvalidArgument);
23}
24
25TEST(FenceWaiterVKTest, IgnoresNullCallback) {
26 auto const context = MockVulkanContextBuilder().Build();
27 auto const device = context->GetDevice();
28 auto const waiter = context->GetFenceWaiter();
29
30 auto fence = device.createFenceUnique({}).value;
31 const auto add_status =
32 waiter->AddFence(std::move(fence), default_submit_callback, nullptr);
33 EXPECT_EQ(add_status.code(), fml::StatusCode::kInvalidArgument);
34}
35
36TEST(FenceWaiterVKTest, ReturnsSubmitError) {
37 auto const context = MockVulkanContextBuilder().Build();
38 auto const device = context->GetDevice();
39 auto const waiter = context->GetFenceWaiter();
40
41 auto submit_callback = [&](vk::Fence) {
42 return fml::Status(fml::StatusCode::kCancelled, "Submit failed");
43 };
44
45 auto fence = device.createFenceUnique({}).value;
46 const auto add_status =
47 waiter->AddFence(std::move(fence), submit_callback, []() {});
48 EXPECT_EQ(add_status.code(), fml::StatusCode::kCancelled);
49}
50
51TEST(FenceWaiterVKTest, ExecutesFenceCallback) {
52 auto const context = MockVulkanContextBuilder().Build();
53 auto const device = context->GetDevice();
54 auto const waiter = context->GetFenceWaiter();
55
56 bool submit_called = false;
57 auto submit_callback = [&](vk::Fence) {
58 submit_called = true;
59 return fml::Status();
60 };
61
62 auto signal = fml::ManualResetWaitableEvent();
63 auto fence = device.createFenceUnique({}).value;
64 waiter->AddFence(std::move(fence), submit_callback,
65 [&signal]() { signal.Signal(); });
66 EXPECT_TRUE(submit_called);
67
68 signal.Wait();
69}
70
71TEST(FenceWaiterVKTest, ExecutesFenceCallbackX2) {
72 auto const context = MockVulkanContextBuilder().Build();
73 auto const device = context->GetDevice();
74 auto const waiter = context->GetFenceWaiter();
75
76 auto signal = fml::ManualResetWaitableEvent();
77 auto fence = device.createFenceUnique({}).value;
78 waiter->AddFence(std::move(fence), default_submit_callback,
79 [&signal]() { signal.Signal(); });
80
81 auto signal2 = fml::ManualResetWaitableEvent();
82 auto fence2 = device.createFenceUnique({}).value;
83 waiter->AddFence(std::move(fence2), default_submit_callback,
84 [&signal2]() { signal2.Signal(); });
85
86 signal.Wait();
87 signal2.Wait();
88}
89
90TEST(FenceWaiterVKTest, ExecutesNewFenceThenOldFence) {
91 auto const context = MockVulkanContextBuilder().Build();
92 auto const device = context->GetDevice();
93 auto const waiter = context->GetFenceWaiter();
94
95 auto signal = fml::ManualResetWaitableEvent();
96 auto fence = device.createFenceUnique({}).value;
97 MockFence::SetStatus(fence, vk::Result::eNotReady);
98 auto raw_fence = MockFence::GetRawPointer(fence);
99 waiter->AddFence(std::move(fence), default_submit_callback,
100 [&signal]() { signal.Signal(); });
101
102 // The easiest way to verify that the callback was _not_ called is to wait
103 // for a timeout, but that could introduce flakiness. Instead, we'll add a
104 // second fence that will signal immediately, and wait for that one instead.
105 {
106 auto signal2 = fml::ManualResetWaitableEvent();
107 auto fence2 = device.createFenceUnique({}).value;
108 MockFence::SetStatus(fence2, vk::Result::eSuccess);
109 waiter->AddFence(std::move(fence2), default_submit_callback,
110 [&signal2]() { signal2.Signal(); });
111 signal2.Wait();
112 }
113
114 // Now, we'll signal the first fence, and wait for the callback to be called.
115 raw_fence->SetStatus(vk::Result::eSuccess);
116
117 // Now, we'll signal the first fence, and wait for the callback to be called.
118 signal.Wait();
119}
120
121TEST(FenceWaiterVKTest, AddFenceDoesNothingIfTerminating) {
122 auto signal = fml::ManualResetWaitableEvent();
123
124 {
125 auto const context = MockVulkanContextBuilder().Build();
126 auto const device = context->GetDevice();
127 auto const waiter = context->GetFenceWaiter();
128 waiter->Terminate();
129
130 auto fence = device.createFenceUnique({}).value;
131 waiter->AddFence(std::move(fence), default_submit_callback,
132 [&signal]() { signal.Signal(); });
133 }
134
135 // Ensure the fence did _not_ signal.
136 EXPECT_TRUE(signal.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(100)));
137}
138
139TEST(FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated) {
140 MockFence* raw_fence = nullptr;
141 auto signal = fml::ManualResetWaitableEvent();
142
143 auto const context = MockVulkanContextBuilder().Build();
144 auto const device = context->GetDevice();
145 auto const waiter = context->GetFenceWaiter();
146
147 // Add a fence that isn't signalled yet.
148 auto fence = device.createFenceUnique({}).value;
149
150 // Even if the fence is eSuccess, it's not guaranteed to be called in time.
151 MockFence::SetStatus(fence, vk::Result::eNotReady);
152 raw_fence = MockFence::GetRawPointer(fence);
153 waiter->AddFence(std::move(fence), default_submit_callback,
154 [&signal]() { signal.Signal(); });
155
156 // Signal the fence after a delay.
157 std::thread thread([&]() {
158 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
159 raw_fence->SetStatus(vk::Result::eSuccess);
160 });
161
162 // Terminate the waiter. This will block until all pending fences are
163 // signalled.
164 waiter->Terminate();
165
166 // This will hang if the fence was not signalled.
167 signal.Wait();
168
169 thread.join();
170}
171
172} // namespace testing
173} // namespace impeller
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition time_delta.h:46
void SetStatus(vk::Result result)
Definition mock_vulkan.h:33
static MockFence * GetRawPointer(vk::UniqueFence &fence)
Definition mock_vulkan.h:44
std::shared_ptr< ContextVK > Build()
Create a Vulkan context with Vulkan functions mocked. The caller is given a chance to tinker on the s...
int32_t value
VkDevice device
Definition main.cc:69
TEST(FrameTimingsRecorderTest, RecordVsync)
std::shared_ptr< ContextGLES > context