1 // Copyright (c) 2015 The Chromium 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
5 #include <stdint.h>
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/containers/queue.h"
11 #include "gpu/command_buffer/service/sync_point_manager.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace gpu {
15
16 class SyncPointManagerTest : public testing::Test {
17 public:
SyncPointManagerTest()18 SyncPointManagerTest() : sync_point_manager_(new SyncPointManager) {}
19 ~SyncPointManagerTest() override = default;
20
21 protected:
22 // Simple static function which can be used to test callbacks.
SetIntegerFunction(int * test,int value)23 static void SetIntegerFunction(int* test, int value) { *test = value; }
24
25 std::unique_ptr<SyncPointManager> sync_point_manager_;
26 };
27
28 struct SyncPointStream {
29 scoped_refptr<SyncPointOrderData> order_data;
30 scoped_refptr<SyncPointClientState> client_state;
31 base::queue<uint32_t> order_numbers;
32
SyncPointStreamgpu::SyncPointStream33 SyncPointStream(SyncPointManager* sync_point_manager,
34 CommandBufferNamespace namespace_id,
35 CommandBufferId command_buffer_id)
36 : order_data(sync_point_manager->CreateSyncPointOrderData()),
37 client_state(sync_point_manager->CreateSyncPointClientState(
38 namespace_id,
39 command_buffer_id,
40 order_data->sequence_id())) {}
41
~SyncPointStreamgpu::SyncPointStream42 ~SyncPointStream() {
43 if (order_data)
44 order_data->Destroy();
45 if (client_state)
46 client_state->Destroy();
47 }
48
AllocateOrderNumgpu::SyncPointStream49 void AllocateOrderNum() {
50 order_numbers.push(order_data->GenerateUnprocessedOrderNumber());
51 }
52
BeginProcessinggpu::SyncPointStream53 void BeginProcessing() {
54 ASSERT_FALSE(order_numbers.empty());
55 order_data->BeginProcessingOrderNumber(order_numbers.front());
56 }
57
EndProcessinggpu::SyncPointStream58 void EndProcessing() {
59 ASSERT_FALSE(order_numbers.empty());
60 order_data->FinishProcessingOrderNumber(order_numbers.front());
61 order_numbers.pop();
62 }
63 };
64
TEST_F(SyncPointManagerTest,BasicSyncPointOrderDataTest)65 TEST_F(SyncPointManagerTest, BasicSyncPointOrderDataTest) {
66 scoped_refptr<SyncPointOrderData> order_data =
67 sync_point_manager_->CreateSyncPointOrderData();
68
69 EXPECT_EQ(0u, order_data->current_order_num());
70 EXPECT_EQ(0u, order_data->processed_order_num());
71 EXPECT_EQ(0u, order_data->unprocessed_order_num());
72
73 uint32_t order_num = order_data->GenerateUnprocessedOrderNumber();
74 EXPECT_EQ(1u, order_num);
75
76 EXPECT_EQ(0u, order_data->current_order_num());
77 EXPECT_EQ(0u, order_data->processed_order_num());
78 EXPECT_EQ(order_num, order_data->unprocessed_order_num());
79
80 order_data->BeginProcessingOrderNumber(order_num);
81 EXPECT_EQ(order_num, order_data->current_order_num());
82 EXPECT_EQ(0u, order_data->processed_order_num());
83 EXPECT_EQ(order_num, order_data->unprocessed_order_num());
84 EXPECT_TRUE(order_data->IsProcessingOrderNumber());
85
86 order_data->PauseProcessingOrderNumber(order_num);
87 EXPECT_FALSE(order_data->IsProcessingOrderNumber());
88
89 order_data->BeginProcessingOrderNumber(order_num);
90 EXPECT_TRUE(order_data->IsProcessingOrderNumber());
91
92 order_data->FinishProcessingOrderNumber(order_num);
93 EXPECT_EQ(order_num, order_data->current_order_num());
94 EXPECT_EQ(order_num, order_data->processed_order_num());
95 EXPECT_EQ(order_num, order_data->unprocessed_order_num());
96 EXPECT_FALSE(order_data->IsProcessingOrderNumber());
97
98 order_data->Destroy();
99 }
100
TEST_F(SyncPointManagerTest,BasicFenceSyncRelease)101 TEST_F(SyncPointManagerTest, BasicFenceSyncRelease) {
102 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
103 CommandBufferId kBufferId = CommandBufferId::FromUnsafeValue(0x123);
104
105 uint64_t release_count = 1;
106 SyncToken sync_token(kNamespaceId, kBufferId, release_count);
107
108 // Can't wait for sync token before client is registered.
109 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
110
111 SyncPointStream stream(sync_point_manager_.get(), kNamespaceId, kBufferId);
112
113 stream.AllocateOrderNum();
114
115 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
116
117 stream.order_data->BeginProcessingOrderNumber(1);
118 stream.client_state->ReleaseFenceSync(release_count);
119 stream.order_data->FinishProcessingOrderNumber(1);
120
121 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
122 }
123
TEST_F(SyncPointManagerTest,OutOfOrderSyncTokenRelease)124 TEST_F(SyncPointManagerTest, OutOfOrderSyncTokenRelease) {
125 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
126 CommandBufferId kBufferId = CommandBufferId::FromUnsafeValue(0x123);
127
128 uint64_t release_count_1 = 2;
129 SyncToken sync_token_1(kNamespaceId, kBufferId, release_count_1);
130 uint64_t release_count_2 = 1;
131 SyncToken sync_token_2(kNamespaceId, kBufferId, release_count_2);
132
133 SyncPointStream stream(sync_point_manager_.get(), kNamespaceId, kBufferId);
134 stream.AllocateOrderNum();
135 stream.AllocateOrderNum();
136
137 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_1));
138 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_2));
139
140 // Releasing the first sync token also releases the second because the first
141 // token's release count is larger.
142 stream.order_data->BeginProcessingOrderNumber(1);
143 stream.client_state->ReleaseFenceSync(release_count_1);
144 stream.order_data->FinishProcessingOrderNumber(1);
145 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_1));
146 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_2));
147
148 // Releasing the second token should be a no-op.
149 stream.order_data->BeginProcessingOrderNumber(2);
150 stream.client_state->ReleaseFenceSync(release_count_2);
151 stream.order_data->FinishProcessingOrderNumber(2);
152 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_1));
153 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_2));
154 }
155
TEST_F(SyncPointManagerTest,MultipleClientsPerOrderData)156 TEST_F(SyncPointManagerTest, MultipleClientsPerOrderData) {
157 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
158 CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
159 CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
160
161 SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
162 kCmdBufferId1);
163 SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
164 kCmdBufferId2);
165
166 uint64_t release_count = 1;
167 SyncToken sync_token1(kNamespaceId, kCmdBufferId1, release_count);
168 stream1.AllocateOrderNum();
169
170 SyncToken sync_token2(kNamespaceId, kCmdBufferId2, release_count);
171 stream2.AllocateOrderNum();
172
173 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token1));
174 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token2));
175
176 stream1.order_data->BeginProcessingOrderNumber(1);
177 stream1.client_state->ReleaseFenceSync(release_count);
178 stream1.order_data->FinishProcessingOrderNumber(1);
179
180 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token1));
181 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token2));
182 }
183
TEST_F(SyncPointManagerTest,BasicFenceSyncWaitRelease)184 TEST_F(SyncPointManagerTest, BasicFenceSyncWaitRelease) {
185 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
186 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
187 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
188
189 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
190 kReleaseCmdBufferId);
191 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
192 kWaitCmdBufferId);
193
194 release_stream.AllocateOrderNum();
195 wait_stream.AllocateOrderNum();
196
197 uint64_t release_count = 1;
198 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
199
200 wait_stream.BeginProcessing();
201 int test_num = 10;
202 bool valid_wait = wait_stream.client_state->Wait(
203 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
204 &test_num, 123));
205 EXPECT_TRUE(valid_wait);
206 EXPECT_EQ(10, test_num);
207 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
208
209 release_stream.BeginProcessing();
210 release_stream.client_state->ReleaseFenceSync(release_count);
211 EXPECT_EQ(123, test_num);
212 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
213 }
214
TEST_F(SyncPointManagerTest,WaitWithOutOfOrderSyncTokenRelease)215 TEST_F(SyncPointManagerTest, WaitWithOutOfOrderSyncTokenRelease) {
216 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
217 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
218 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
219
220 int test_num_1 = 10;
221 int test_num_2 = 10;
222 int test_num_3 = 10;
223 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
224 kReleaseCmdBufferId);
225 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
226 kWaitCmdBufferId);
227
228 release_stream.AllocateOrderNum();
229 uint64_t release_count_1 = 2;
230 SyncToken sync_token_1(kNamespaceId, kReleaseCmdBufferId, release_count_1);
231 release_stream.AllocateOrderNum();
232 uint64_t release_count_2 = 1;
233 SyncToken sync_token_2(kNamespaceId, kReleaseCmdBufferId, release_count_2);
234 release_stream.AllocateOrderNum();
235 uint64_t release_count_3 = 3;
236 SyncToken sync_token_3(kNamespaceId, kReleaseCmdBufferId, release_count_3);
237
238 wait_stream.AllocateOrderNum();
239 wait_stream.BeginProcessing();
240 bool valid_wait = wait_stream.client_state->Wait(
241 sync_token_1, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
242 &test_num_1, 123));
243 EXPECT_TRUE(valid_wait);
244 EXPECT_EQ(10, test_num_1);
245 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_1));
246 wait_stream.EndProcessing();
247
248 wait_stream.AllocateOrderNum();
249 wait_stream.BeginProcessing();
250 valid_wait = wait_stream.client_state->Wait(
251 sync_token_2, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
252 &test_num_2, 123));
253 EXPECT_TRUE(valid_wait);
254 EXPECT_EQ(10, test_num_2);
255 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_2));
256 wait_stream.EndProcessing();
257
258 wait_stream.AllocateOrderNum();
259 wait_stream.BeginProcessing();
260 valid_wait = wait_stream.client_state->Wait(
261 sync_token_3, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
262 &test_num_3, 123));
263 EXPECT_TRUE(valid_wait);
264 EXPECT_EQ(10, test_num_3);
265 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_3));
266 wait_stream.EndProcessing();
267
268 // Releasing the first sync token should release the second one. Then,
269 // releasing the second one should be a no-op.
270 release_stream.BeginProcessing();
271 release_stream.client_state->ReleaseFenceSync(release_count_1);
272 EXPECT_EQ(123, test_num_1);
273 EXPECT_EQ(123, test_num_2);
274 EXPECT_EQ(10, test_num_3);
275 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_1));
276 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_2));
277 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_3));
278 release_stream.EndProcessing();
279
280 release_stream.BeginProcessing();
281 release_stream.client_state->ReleaseFenceSync(release_count_2);
282 EXPECT_EQ(123, test_num_1);
283 EXPECT_EQ(123, test_num_2);
284 EXPECT_EQ(10, test_num_3);
285 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_1));
286 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token_2));
287 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token_3));
288 release_stream.EndProcessing();
289 }
290
TEST_F(SyncPointManagerTest,WaitOnSelfFails)291 TEST_F(SyncPointManagerTest, WaitOnSelfFails) {
292 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
293 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
294 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
295
296 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
297 kReleaseCmdBufferId);
298 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
299 kWaitCmdBufferId);
300
301 release_stream.AllocateOrderNum();
302 wait_stream.AllocateOrderNum();
303
304 uint64_t release_count = 1;
305 SyncToken sync_token(kNamespaceId, kWaitCmdBufferId, release_count);
306
307 wait_stream.BeginProcessing();
308 int test_num = 10;
309 bool valid_wait = wait_stream.client_state->Wait(
310 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
311 &test_num, 123));
312 EXPECT_FALSE(valid_wait);
313 EXPECT_EQ(10, test_num);
314 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
315 }
316
TEST_F(SyncPointManagerTest,ReleaseAfterWaitOrderNumber)317 TEST_F(SyncPointManagerTest, ReleaseAfterWaitOrderNumber) {
318 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
319 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
320 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
321
322 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
323 kReleaseCmdBufferId);
324 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
325 kWaitCmdBufferId);
326
327 // Generate wait order number first.
328 wait_stream.AllocateOrderNum();
329 release_stream.AllocateOrderNum();
330
331 uint64_t release_count = 1;
332 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
333
334 wait_stream.BeginProcessing();
335 int test_num = 10;
336 bool valid_wait = wait_stream.client_state->Wait(
337 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
338 &test_num, 123));
339 EXPECT_FALSE(valid_wait);
340 EXPECT_EQ(10, test_num);
341 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
342 }
343
TEST_F(SyncPointManagerTest,HigherOrderNumberRelease)344 TEST_F(SyncPointManagerTest, HigherOrderNumberRelease) {
345 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
346 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
347 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
348
349 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
350 kReleaseCmdBufferId);
351 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
352 kWaitCmdBufferId);
353
354 // Generate wait order number first.
355 wait_stream.AllocateOrderNum();
356 release_stream.AllocateOrderNum();
357
358 uint64_t release_count = 1;
359 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
360
361 // Order number was higher but it was actually released.
362 release_stream.BeginProcessing();
363 release_stream.client_state->ReleaseFenceSync(release_count);
364 release_stream.EndProcessing();
365
366 // Release stream has already released so there's no need to wait.
367 wait_stream.BeginProcessing();
368 int test_num = 10;
369 bool valid_wait = wait_stream.client_state->Wait(
370 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
371 &test_num, 123));
372 EXPECT_FALSE(valid_wait);
373 EXPECT_EQ(10, test_num);
374 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
375 }
376
TEST_F(SyncPointManagerTest,DestroyedClientRelease)377 TEST_F(SyncPointManagerTest, DestroyedClientRelease) {
378 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
379 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
380 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
381
382 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
383 kReleaseCmdBufferId);
384 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
385 kWaitCmdBufferId);
386
387 release_stream.AllocateOrderNum();
388 wait_stream.AllocateOrderNum();
389
390 uint64_t release_count = 1;
391 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
392
393 wait_stream.BeginProcessing();
394
395 int test_num = 10;
396 bool valid_wait = wait_stream.client_state->Wait(
397 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
398 &test_num, 123));
399 EXPECT_TRUE(valid_wait);
400 EXPECT_EQ(10, test_num);
401
402 // Destroying the client should release the wait.
403 release_stream.client_state->Destroy();
404 release_stream.client_state = nullptr;
405
406 EXPECT_EQ(123, test_num);
407 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
408 }
409
TEST_F(SyncPointManagerTest,NonExistentRelease)410 TEST_F(SyncPointManagerTest, NonExistentRelease) {
411 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
412 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
413 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
414
415 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
416 kReleaseCmdBufferId);
417 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
418 kWaitCmdBufferId);
419
420 // Assign release stream order [1] and wait stream order [2].
421 // This test simply tests that a wait stream of order [2] waiting on
422 // release stream of order [1] will still release the fence sync even
423 // though nothing was released.
424 release_stream.AllocateOrderNum();
425 wait_stream.AllocateOrderNum();
426
427 uint64_t release_count = 1;
428 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
429
430 wait_stream.BeginProcessing();
431 int test_num = 10;
432 bool valid_wait = wait_stream.client_state->Wait(
433 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
434 &test_num, 123));
435 EXPECT_TRUE(valid_wait);
436 EXPECT_EQ(10, test_num);
437 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
438
439 // No release but finishing the order number should automatically release.
440 release_stream.BeginProcessing();
441 EXPECT_EQ(10, test_num);
442 release_stream.EndProcessing();
443 EXPECT_EQ(123, test_num);
444 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
445 }
446
TEST_F(SyncPointManagerTest,NonExistentRelease2)447 TEST_F(SyncPointManagerTest, NonExistentRelease2) {
448 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
449 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
450 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
451
452 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
453 kReleaseCmdBufferId);
454 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
455 kWaitCmdBufferId);
456
457 // Assign Release stream order [1] and assign Wait stream orders [2, 3].
458 // This test is similar to the NonExistentRelease case except
459 // we place an extra order number in between the release and wait.
460 // The wait stream [3] is waiting on release stream [1] even though
461 // order [2] was also generated. Although order [2] only exists on the
462 // wait stream so the release stream should only know about order [1].
463 release_stream.AllocateOrderNum();
464 wait_stream.AllocateOrderNum();
465 wait_stream.AllocateOrderNum();
466
467 uint64_t release_count = 1;
468 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
469
470 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
471 // Have wait with order [3] to wait on release.
472 wait_stream.BeginProcessing();
473 EXPECT_EQ(2u, wait_stream.order_data->current_order_num());
474 wait_stream.EndProcessing();
475 wait_stream.BeginProcessing();
476 EXPECT_EQ(3u, wait_stream.order_data->current_order_num());
477 int test_num = 10;
478 bool valid_wait = wait_stream.client_state->Wait(
479 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
480 &test_num, 123));
481 EXPECT_TRUE(valid_wait);
482 EXPECT_EQ(10, test_num);
483 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
484
485 // Even though release stream order [1] did not have a release, it
486 // should have changed test_num although the fence sync is still not released.
487 release_stream.BeginProcessing();
488 EXPECT_EQ(1u, release_stream.order_data->current_order_num());
489 release_stream.EndProcessing();
490 EXPECT_EQ(123, test_num);
491 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
492
493 // Ensure that the wait callback does not get triggered again when it is
494 // actually released.
495 test_num = 1;
496 release_stream.AllocateOrderNum();
497 release_stream.BeginProcessing();
498 release_stream.client_state->ReleaseFenceSync(release_count);
499 release_stream.EndProcessing();
500 EXPECT_EQ(1, test_num);
501 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
502 }
503
TEST_F(SyncPointManagerTest,NonExistentOrderNumRelease)504 TEST_F(SyncPointManagerTest, NonExistentOrderNumRelease) {
505 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
506 CommandBufferId kReleaseCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
507 CommandBufferId kWaitCmdBufferId = CommandBufferId::FromUnsafeValue(0x234);
508
509 SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId,
510 kReleaseCmdBufferId);
511 SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId,
512 kWaitCmdBufferId);
513
514 // Assign Release stream orders [1, 4] and assign Wait stream orders [2, 3].
515 // Here we are testing that wait order [3] will wait on a fence sync
516 // in either order [1] or order [2]. Order [2] was not actually assigned
517 // to the release stream so it is essentially non-existent to the release
518 // stream's point of view. Once the release stream begins processing the next
519 // order [3], it should realize order [2] didn't exist and release the fence.
520 release_stream.AllocateOrderNum();
521 wait_stream.AllocateOrderNum();
522 wait_stream.AllocateOrderNum();
523 release_stream.AllocateOrderNum();
524
525 uint64_t release_count = 1;
526 SyncToken sync_token(kNamespaceId, kReleaseCmdBufferId, release_count);
527
528 // Have wait with order [3] to wait on release order [1] or [2].
529 wait_stream.BeginProcessing();
530 EXPECT_EQ(2u, wait_stream.order_data->current_order_num());
531 wait_stream.EndProcessing();
532 wait_stream.BeginProcessing();
533 EXPECT_EQ(3u, wait_stream.order_data->current_order_num());
534 int test_num = 10;
535 bool valid_wait = wait_stream.client_state->Wait(
536 sync_token, base::BindOnce(&SyncPointManagerTest::SetIntegerFunction,
537 &test_num, 123));
538 EXPECT_TRUE(valid_wait);
539 EXPECT_EQ(10, test_num);
540
541 // Release stream should know it should release fence sync by order [3], but
542 // it has no unprocessed order numbers less than 3, so it runs the callback.
543 release_stream.BeginProcessing();
544 EXPECT_EQ(1u, release_stream.order_data->current_order_num());
545 release_stream.EndProcessing();
546 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
547 EXPECT_EQ(123, test_num);
548
549 // Ensure that the wait callback does not get triggered again when it is
550 // actually released.
551 release_stream.BeginProcessing();
552 test_num = 10;
553 release_stream.client_state->ReleaseFenceSync(1);
554 EXPECT_EQ(10, test_num);
555 EXPECT_TRUE(sync_point_manager_->IsSyncTokenReleased(sync_token));
556 }
557
TEST_F(SyncPointManagerTest,WaitOnSameSequenceFails)558 TEST_F(SyncPointManagerTest, WaitOnSameSequenceFails) {
559 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
560 CommandBufferId kCmdBufferId = CommandBufferId::FromUnsafeValue(0x123);
561
562 SyncPointStream stream(sync_point_manager_.get(), kNamespaceId, kCmdBufferId);
563
564 // Dummy order number to avoid the wait_order_num <= processed_order_num + 1
565 // check in SyncPointOrderData::ValidateReleaseOrderNum.
566 sync_point_manager_->GenerateOrderNumber();
567
568 // Order number for the wait.
569 stream.AllocateOrderNum();
570
571 uint64_t release_count = 1;
572 SyncToken sync_token(kNamespaceId, kCmdBufferId, release_count);
573
574 int test_num = 10;
575 bool valid_wait = sync_point_manager_->Wait(
576 sync_token, stream.order_data->sequence_id(),
577 stream.order_data->unprocessed_order_num(),
578 base::BindOnce(&SyncPointManagerTest::SetIntegerFunction, &test_num,
579 123));
580 EXPECT_FALSE(valid_wait);
581 EXPECT_EQ(10, test_num);
582 EXPECT_FALSE(sync_point_manager_->IsSyncTokenReleased(sync_token));
583 }
584
TEST_F(SyncPointManagerTest,HandleInvalidWaitOrderNumber)585 TEST_F(SyncPointManagerTest, HandleInvalidWaitOrderNumber) {
586 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
587 CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
588 CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
589
590 SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
591 kCmdBufferId1);
592 SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
593 kCmdBufferId2);
594
595 stream1.AllocateOrderNum(); // stream 1, order num 1
596 stream2.AllocateOrderNum(); // stream 2, order num 2
597 stream2.AllocateOrderNum(); // stream 2, order num 3
598 stream1.AllocateOrderNum(); // stream 1, order num 4
599
600 // Run stream 1, order num 1.
601 stream1.BeginProcessing();
602 stream1.EndProcessing();
603
604 // Stream 2 waits on stream 1 with order num 3. This wait is invalid because
605 // there's no unprocessed order num less than 3 on stream 1.
606 int test_num = 10;
607 bool valid_wait = sync_point_manager_->Wait(
608 SyncToken(kNamespaceId, kCmdBufferId1, 1),
609 stream2.order_data->sequence_id(), 3,
610 base::BindOnce(&SyncPointManagerTest::SetIntegerFunction, &test_num,
611 123));
612 EXPECT_FALSE(valid_wait);
613 EXPECT_EQ(10, test_num);
614 }
615
TEST_F(SyncPointManagerTest,RetireInvalidWaitAfterOrderNumberPasses)616 TEST_F(SyncPointManagerTest, RetireInvalidWaitAfterOrderNumberPasses) {
617 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
618 CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
619 CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
620
621 SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
622 kCmdBufferId1);
623 SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
624 kCmdBufferId2);
625
626 stream1.AllocateOrderNum(); // stream 1, order num 1
627 stream1.AllocateOrderNum(); // stream 1, order num 2
628 stream2.AllocateOrderNum(); // stream 2, order num 3
629
630 // Stream 2 waits on stream 1 with order num 3.
631 int test_num = 10;
632 bool valid_wait = sync_point_manager_->Wait(
633 SyncToken(kNamespaceId, kCmdBufferId1, 1),
634 stream2.order_data->sequence_id(), 3,
635 base::BindOnce(&SyncPointManagerTest::SetIntegerFunction, &test_num,
636 123));
637 EXPECT_TRUE(valid_wait);
638 EXPECT_EQ(10, test_num);
639
640 stream1.AllocateOrderNum(); // stream 1, order num 4
641
642 // Run stream 1, order num 1. The wait isn't retired.
643 stream1.BeginProcessing();
644 stream1.EndProcessing();
645 EXPECT_EQ(10, test_num);
646
647 // Run stream 1, order num 2. Wait is retired because we reach the last order
648 // number that was unprocessed at the time the wait was enqueued.
649 stream1.BeginProcessing();
650 stream1.EndProcessing();
651 EXPECT_EQ(123, test_num);
652 }
653
TEST_F(SyncPointManagerTest,HandleInvalidCyclicWaits)654 TEST_F(SyncPointManagerTest, HandleInvalidCyclicWaits) {
655 CommandBufferNamespace kNamespaceId = gpu::CommandBufferNamespace::GPU_IO;
656 CommandBufferId kCmdBufferId1 = CommandBufferId::FromUnsafeValue(0x123);
657 CommandBufferId kCmdBufferId2 = CommandBufferId::FromUnsafeValue(0x234);
658
659 SyncPointStream stream1(sync_point_manager_.get(), kNamespaceId,
660 kCmdBufferId1);
661 SyncPointStream stream2(sync_point_manager_.get(), kNamespaceId,
662 kCmdBufferId2);
663
664 stream1.AllocateOrderNum(); // stream 1, order num 1
665 stream2.AllocateOrderNum(); // stream 2, order num 2
666 stream1.AllocateOrderNum(); // stream 1, order num 3
667 stream2.AllocateOrderNum(); // stream 2, order num 4
668
669 // Stream 2 waits on stream 1 with order num 2.
670 int test_num1 = 10;
671 bool valid_wait = sync_point_manager_->Wait(
672 SyncToken(kNamespaceId, kCmdBufferId1, 1),
673 stream2.order_data->sequence_id(), 2,
674 base::BindOnce(&SyncPointManagerTest::SetIntegerFunction, &test_num1,
675 123));
676 EXPECT_TRUE(valid_wait);
677 EXPECT_EQ(10, test_num1);
678
679 // Stream 1 waits on stream 2 with order num 3.
680 int test_num2 = 10;
681 valid_wait = sync_point_manager_->Wait(
682 SyncToken(kNamespaceId, kCmdBufferId2, 1),
683 stream1.order_data->sequence_id(), 3,
684 base::BindOnce(&SyncPointManagerTest::SetIntegerFunction, &test_num2,
685 123));
686 EXPECT_TRUE(valid_wait);
687 EXPECT_EQ(10, test_num2);
688
689 // Run stream 1, order num 1.
690 stream1.BeginProcessing();
691 stream1.EndProcessing();
692
693 // Since there's no unprocessed order num less than 2 on stream 1, the wait is
694 // released.
695 EXPECT_EQ(123, test_num1);
696 EXPECT_EQ(10, test_num2);
697
698 // Run stream 2, order num 2.
699 stream2.BeginProcessing();
700 stream2.EndProcessing();
701
702 // Since there's no unprocessed order num less than 3 on stream 2, the wait is
703 // released.
704 EXPECT_EQ(123, test_num1);
705 EXPECT_EQ(123, test_num2);
706 }
707
708 } // namespace gpu
709