Index: gpu/command_buffer/service/sync_point_manager_unittest.cc |
diff --git a/gpu/command_buffer/service/sync_point_manager_unittest.cc b/gpu/command_buffer/service/sync_point_manager_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0b42505bcb6d42bcb3f3555000ad50e17384c951 |
--- /dev/null |
+++ b/gpu/command_buffer/service/sync_point_manager_unittest.cc |
@@ -0,0 +1,415 @@ |
+// Copyright (c) 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <queue> |
+ |
+#include "base/bind.h" |
+#include "gpu/command_buffer/service/sync_point_manager.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace gpu { |
+ |
+class SyncPointManagerTest : public testing::Test { |
+ public: |
+ SyncPointManagerTest() {} |
+ |
+ ~SyncPointManagerTest() override {} |
+ |
+ protected: |
+ void SetUp() override { |
+ sync_point_manager_.reset(new SyncPointManager(false)); |
+ } |
+ |
+ void TearDown() override { sync_point_manager_.reset(); } |
+ |
+ // Simple static function which can be used to test callbacks. |
+ static void SetIntegerFunction(int* test, int value) { *test = value; } |
+ |
+ scoped_ptr<SyncPointManager> sync_point_manager_; |
+}; |
+ |
+struct SyncPointStream { |
+ scoped_refptr<SyncPointOrderData> order_data; |
+ scoped_ptr<SyncPointClient> client; |
+ std::queue<uint32_t> order_numbers; |
+ |
+ SyncPointStream(SyncPointManager* sync_point_manager, |
+ CommandBufferNamespace namespace_id, |
+ uint64_t command_buffer_id) |
+ : order_data(SyncPointOrderData::Create()), |
+ client(sync_point_manager->CreateSyncPointClient(order_data, |
+ namespace_id, |
+ command_buffer_id)) {} |
+ |
+ ~SyncPointStream() { |
+ order_data->Destroy(); |
+ order_data = nullptr; |
+ } |
+ |
+ void AllocateOrderNum(SyncPointManager* sync_point_manager) { |
+ order_numbers.push( |
+ order_data->GenerateUnprocessedOrderNumber(sync_point_manager)); |
+ } |
+ |
+ void BeginProcessing() { |
+ ASSERT_FALSE(order_numbers.empty()); |
+ order_data->BeginProcessingOrderNumber(order_numbers.front()); |
+ } |
+ |
+ void EndProcessing() { |
+ ASSERT_FALSE(order_numbers.empty()); |
+ order_data->FinishProcessingOrderNumber(order_numbers.front()); |
+ order_numbers.pop(); |
+ } |
+}; |
+ |
+TEST_F(SyncPointManagerTest, BasicSyncPointOrderDataTest) { |
+ scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); |
+ |
+ EXPECT_EQ(0u, order_data->current_order_num()); |
+ EXPECT_EQ(0u, order_data->processed_order_num()); |
+ EXPECT_EQ(0u, order_data->unprocessed_order_num()); |
+ |
+ const uint32_t order_num = |
+ order_data->GenerateUnprocessedOrderNumber(sync_point_manager_.get()); |
+ EXPECT_EQ(1u, order_num); |
+ |
+ EXPECT_EQ(0u, order_data->current_order_num()); |
+ EXPECT_EQ(0u, order_data->processed_order_num()); |
+ EXPECT_EQ(order_num, order_data->unprocessed_order_num()); |
+ |
+ order_data->BeginProcessingOrderNumber(order_num); |
+ EXPECT_EQ(order_num, order_data->current_order_num()); |
+ EXPECT_EQ(0u, order_data->processed_order_num()); |
+ EXPECT_EQ(order_num, order_data->unprocessed_order_num()); |
+ |
+ order_data->FinishProcessingOrderNumber(order_num); |
+ EXPECT_EQ(order_num, order_data->current_order_num()); |
+ EXPECT_EQ(order_num, order_data->processed_order_num()); |
+ EXPECT_EQ(order_num, order_data->unprocessed_order_num()); |
+} |
+ |
+TEST_F(SyncPointManagerTest, SyncPointClientRegistration) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId = 0x123; |
+ |
+ scoped_refptr<SyncPointClientState> empty_state = |
+ sync_point_manager_->GetSyncPointClientState(kNamespaceId, kBufferId); |
+ EXPECT_FALSE(empty_state); |
+ |
+ scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); |
+ |
+ scoped_ptr<SyncPointClient> client = |
+ sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, |
+ kBufferId); |
+ |
+ EXPECT_EQ(order_data, client->client_state()->order_data()); |
+ EXPECT_EQ( |
+ client->client_state(), |
+ sync_point_manager_->GetSyncPointClientState(kNamespaceId, kBufferId)); |
+} |
+ |
+TEST_F(SyncPointManagerTest, BasicFenceSyncRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId = 0x123; |
+ |
+ scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); |
+ scoped_ptr<SyncPointClient> client = |
+ sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, |
+ kBufferId); |
+ scoped_refptr<SyncPointClientState> client_state = client->client_state(); |
+ |
+ EXPECT_EQ(0u, client_state->fence_sync_release()); |
+ EXPECT_FALSE(client_state->IsFenceSyncReleased(1)); |
+ |
+ client->ReleaseFenceSync(1); |
+ |
+ EXPECT_EQ(1u, client_state->fence_sync_release()); |
+ EXPECT_TRUE(client_state->IsFenceSyncReleased(1)); |
+} |
+ |
+TEST_F(SyncPointManagerTest, MultipleClientsPerOrderData) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ scoped_refptr<SyncPointOrderData> order_data = SyncPointOrderData::Create(); |
+ scoped_ptr<SyncPointClient> client1 = |
+ sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, |
+ kBufferId1); |
+ scoped_ptr<SyncPointClient> client2 = |
+ sync_point_manager_->CreateSyncPointClient(order_data, kNamespaceId, |
+ kBufferId2); |
+ |
+ scoped_refptr<SyncPointClientState> client_state1 = client1->client_state(); |
+ scoped_refptr<SyncPointClientState> client_state2 = client2->client_state(); |
+ |
+ client1->ReleaseFenceSync(1); |
+ |
+ EXPECT_TRUE(client_state1->IsFenceSyncReleased(1)); |
+ EXPECT_FALSE(client_state2->IsFenceSyncReleased(1)); |
+} |
+ |
+TEST_F(SyncPointManagerTest, BasicFenceSyncWaitRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ wait_stream.BeginProcessing(); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ ASSERT_TRUE(valid_wait); |
+ EXPECT_EQ(10, test_num); |
+ |
+ release_stream.BeginProcessing(); |
+ release_stream.client->ReleaseFenceSync(1); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, WaitOnSelfFails) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ // Generate wait order number first. |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ wait_stream.BeginProcessing(); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ wait_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_FALSE(valid_wait); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, OutOfOrderRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ // Generate wait order number first. |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ wait_stream.BeginProcessing(); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_FALSE(valid_wait); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, HigherOrderNumberRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ // Generate wait order number first. |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ // Order number was higher but it was actually released. |
+ release_stream.BeginProcessing(); |
+ release_stream.client->ReleaseFenceSync(1); |
+ release_stream.EndProcessing(); |
+ |
+ wait_stream.BeginProcessing(); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_TRUE(valid_wait); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, DestroyedClientRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ wait_stream.BeginProcessing(); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_TRUE(valid_wait); |
+ EXPECT_EQ(10, test_num); |
+ |
+ // Destroying the client should release the wait. |
+ release_stream.client.reset(); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, NonExistentRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ // Assign release stream order [1] and wait stream order [2]. |
+ // This test simply tests that a wait stream of order [2] waiting on |
+ // release stream of order [1] will still release the fence sync even |
+ // though nothing was released. |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ wait_stream.BeginProcessing(); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_TRUE(valid_wait); |
+ EXPECT_EQ(10, test_num); |
+ |
+ // No release but finishing the order number should automatically release. |
+ release_stream.BeginProcessing(); |
+ EXPECT_EQ(10, test_num); |
+ release_stream.EndProcessing(); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, NonExistentRelease2) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ // Assign Release stream order [1] and assign Wait stream orders [2, 3]. |
+ // This test is similar to the NonExistentRelease case except |
+ // we place an extra order number in between the release and wait. |
+ // The wait stream [3] is waiting on release stream [1] even though |
+ // order [2] was also generated. Although order [2] only exists on the |
+ // wait stream so the release stream should only know about order [1]. |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ // Have wait with order [3] to wait on release. |
+ wait_stream.BeginProcessing(); |
+ ASSERT_EQ(2u, wait_stream.order_data->current_order_num()); |
+ wait_stream.EndProcessing(); |
+ wait_stream.BeginProcessing(); |
+ ASSERT_EQ(3u, wait_stream.order_data->current_order_num()); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_TRUE(valid_wait); |
+ EXPECT_EQ(10, test_num); |
+ |
+ // Even though release stream order [1] did not have a release, it |
+ // should still release the fence when finish processing since the wait |
+ // stream had expected on to exist there. |
+ release_stream.BeginProcessing(); |
+ ASSERT_EQ(1u, release_stream.order_data->current_order_num()); |
+ release_stream.EndProcessing(); |
+ EXPECT_TRUE(release_stream.client->client_state()->IsFenceSyncReleased(1)); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+TEST_F(SyncPointManagerTest, NonExistentOrderNumRelease) { |
+ const CommandBufferNamespace kNamespaceId = |
+ gpu::CommandBufferNamespace::GPU_IO; |
+ const uint64_t kBufferId1 = 0x123; |
+ const uint64_t kBufferId2 = 0x234; |
+ |
+ SyncPointStream release_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId1); |
+ SyncPointStream wait_stream(sync_point_manager_.get(), kNamespaceId, |
+ kBufferId2); |
+ |
+ // Assign Release stream orders [1, 4] and assign Wait stream orders [2, 3]. |
+ // Here we are testing that wait order [3] will wait on a fence sync |
+ // in either order [1] or order [2]. Order [2] was not actually assigned |
+ // to the release stream so it is essentially non-existent to the release |
+ // stream's point of view. Once the release stream begins processing the next |
+ // order [3], it should realize order [2] didn't exist and release the fence. |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ wait_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ release_stream.AllocateOrderNum(sync_point_manager_.get()); |
+ |
+ // Have wait with order [3] to wait on release order [1] or [2]. |
+ wait_stream.BeginProcessing(); |
+ ASSERT_EQ(2u, wait_stream.order_data->current_order_num()); |
+ wait_stream.EndProcessing(); |
+ wait_stream.BeginProcessing(); |
+ ASSERT_EQ(3u, wait_stream.order_data->current_order_num()); |
+ int test_num = 10; |
+ const bool valid_wait = wait_stream.client->Wait( |
+ release_stream.client->client_state().get(), 1, |
+ base::Bind(&SyncPointManagerTest::SetIntegerFunction, &test_num, 123)); |
+ EXPECT_TRUE(valid_wait); |
+ EXPECT_EQ(10, test_num); |
+ |
+ // Release stream should know it should release fence sync by order [3], |
+ // so going through order [1] should not release it yet. |
+ release_stream.BeginProcessing(); |
+ ASSERT_EQ(1u, release_stream.order_data->current_order_num()); |
+ release_stream.EndProcessing(); |
+ EXPECT_FALSE(release_stream.client->client_state()->IsFenceSyncReleased(1)); |
+ EXPECT_EQ(10, test_num); |
+ |
+ // Beginning order [4] should immediately trigger the release. |
+ release_stream.BeginProcessing(); |
+ ASSERT_EQ(4u, release_stream.order_data->current_order_num()); |
+ EXPECT_TRUE(release_stream.client->client_state()->IsFenceSyncReleased(1)); |
+ EXPECT_EQ(123, test_num); |
+} |
+ |
+} // namespace gpu |