1 // Copyright (c) 2012 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.
5 // Tests for the QueryTracker.
7 #include "gpu/command_buffer/client/query_tracker.h"
9 #include <GLES2/gl2ext.h>
10 #include "base/memory/scoped_ptr.h"
11 #include "gpu/command_buffer/client/client_test_helper.h"
12 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
13 #include "gpu/command_buffer/client/mapped_memory.h"
14 #include "gpu/command_buffer/common/command_buffer.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "testing/gmock/include/gmock/gmock.h"
26 class QuerySyncManagerTest
: public testing::Test
{
28 static const int32 kNumCommandEntries
= 400;
29 static const int32 kCommandBufferSizeBytes
=
30 kNumCommandEntries
* sizeof(CommandBufferEntry
);
32 void SetUp() override
{
33 command_buffer_
.reset(new MockClientCommandBuffer());
34 helper_
.reset(new GLES2CmdHelper(command_buffer_
.get()));
35 helper_
->Initialize(kCommandBufferSizeBytes
);
36 mapped_memory_
.reset(new MappedMemoryManager(
37 helper_
.get(), base::Bind(&EmptyPoll
), MappedMemoryManager::kNoLimit
));
38 sync_manager_
.reset(new QuerySyncManager(mapped_memory_
.get()));
41 void TearDown() override
{
42 sync_manager_
.reset();
43 mapped_memory_
.reset();
45 command_buffer_
.reset();
48 scoped_ptr
<CommandBuffer
> command_buffer_
;
49 scoped_ptr
<GLES2CmdHelper
> helper_
;
50 scoped_ptr
<MappedMemoryManager
> mapped_memory_
;
51 scoped_ptr
<QuerySyncManager
> sync_manager_
;
54 TEST_F(QuerySyncManagerTest
, Basic
) {
55 QuerySyncManager::QueryInfo infos
[4];
56 memset(&infos
, 0xBD, sizeof(infos
));
58 for (size_t ii
= 0; ii
< arraysize(infos
); ++ii
) {
59 EXPECT_TRUE(sync_manager_
->Alloc(&infos
[ii
]));
60 EXPECT_NE(0, infos
[ii
].shm_id
);
61 ASSERT_TRUE(infos
[ii
].sync
!= NULL
);
62 EXPECT_EQ(0, infos
[ii
].sync
->process_count
);
63 EXPECT_EQ(0u, infos
[ii
].sync
->result
);
66 for (size_t ii
= 0; ii
< arraysize(infos
); ++ii
) {
67 sync_manager_
->Free(infos
[ii
]);
71 TEST_F(QuerySyncManagerTest
, DontFree
) {
72 QuerySyncManager::QueryInfo infos
[4];
73 memset(&infos
, 0xBD, sizeof(infos
));
75 for (size_t ii
= 0; ii
< arraysize(infos
); ++ii
) {
76 EXPECT_TRUE(sync_manager_
->Alloc(&infos
[ii
]));
80 class QueryTrackerTest
: public testing::Test
{
82 static const int32 kNumCommandEntries
= 400;
83 static const int32 kCommandBufferSizeBytes
=
84 kNumCommandEntries
* sizeof(CommandBufferEntry
);
86 void SetUp() override
{
87 command_buffer_
.reset(new MockClientCommandBuffer());
88 helper_
.reset(new GLES2CmdHelper(command_buffer_
.get()));
89 helper_
->Initialize(kCommandBufferSizeBytes
);
90 mapped_memory_
.reset(new MappedMemoryManager(
91 helper_
.get(), base::Bind(&EmptyPoll
), MappedMemoryManager::kNoLimit
));
92 query_tracker_
.reset(new QueryTracker(mapped_memory_
.get()));
95 void TearDown() override
{
96 query_tracker_
.reset();
97 mapped_memory_
.reset();
99 command_buffer_
.reset();
102 QuerySync
* GetSync(QueryTracker::Query
* query
) {
103 return query
->info_
.sync
;
106 QuerySyncManager::Bucket
* GetBucket(QueryTracker::Query
* query
) {
107 return query
->info_
.bucket
;
110 uint32
GetFlushGeneration() { return helper_
->flush_generation(); }
112 scoped_ptr
<CommandBuffer
> command_buffer_
;
113 scoped_ptr
<GLES2CmdHelper
> helper_
;
114 scoped_ptr
<MappedMemoryManager
> mapped_memory_
;
115 scoped_ptr
<QueryTracker
> query_tracker_
;
118 TEST_F(QueryTrackerTest
, Basic
) {
119 const GLuint kId1
= 123;
120 const GLuint kId2
= 124;
122 // Check we can create a Query.
123 QueryTracker::Query
* query
= query_tracker_
->CreateQuery(
124 kId1
, GL_ANY_SAMPLES_PASSED_EXT
);
125 ASSERT_TRUE(query
!= NULL
);
126 // Check we can get the same Query.
127 EXPECT_EQ(query
, query_tracker_
->GetQuery(kId1
));
128 // Check we get nothing for a non-existent query.
129 EXPECT_TRUE(query_tracker_
->GetQuery(kId2
) == NULL
);
130 // Check we can delete the query.
131 query_tracker_
->RemoveQuery(kId1
);
132 // Check we get nothing for a non-existent query.
133 EXPECT_TRUE(query_tracker_
->GetQuery(kId1
) == NULL
);
136 TEST_F(QueryTrackerTest
, Query
) {
137 const GLuint kId1
= 123;
138 const int32 kToken
= 46;
139 const uint32 kResult
= 456;
142 QueryTracker::Query
* query
= query_tracker_
->CreateQuery(
143 kId1
, GL_ANY_SAMPLES_PASSED_EXT
);
144 ASSERT_TRUE(query
!= NULL
);
145 EXPECT_TRUE(query
->NeverUsed());
146 EXPECT_FALSE(query
->Pending());
147 EXPECT_EQ(0, query
->token());
148 EXPECT_EQ(0, query
->submit_count());
150 // Check MarkAsActive.
151 query
->MarkAsActive();
152 EXPECT_FALSE(query
->NeverUsed());
153 EXPECT_FALSE(query
->Pending());
154 EXPECT_EQ(0, query
->token());
155 EXPECT_EQ(1, query
->submit_count());
157 // Check MarkAsPending.
158 query
->MarkAsPending(kToken
);
159 EXPECT_FALSE(query
->NeverUsed());
160 EXPECT_TRUE(query
->Pending());
161 EXPECT_EQ(kToken
, query
->token());
162 EXPECT_EQ(1, query
->submit_count());
164 // Check CheckResultsAvailable.
165 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
166 EXPECT_FALSE(query
->NeverUsed());
167 EXPECT_TRUE(query
->Pending());
169 // Flush only once if no more flushes happened between a call to
170 // EndQuery command and CheckResultsAvailable
171 // Advance put_ so flush calls in CheckResultsAvailable go through
172 // and updates flush_generation count
174 // Set Query in pending state_ to simulate EndQuery command is called
175 query
->MarkAsPending(kToken
);
176 EXPECT_TRUE(query
->Pending());
177 // Store FlushGeneration count after EndQuery is called
178 uint32 gen1
= GetFlushGeneration();
179 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
180 uint32 gen2
= GetFlushGeneration();
181 EXPECT_NE(gen1
, gen2
);
182 // Repeated calls to CheckResultsAvailable should not flush unnecessarily
183 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
184 gen1
= GetFlushGeneration();
185 EXPECT_EQ(gen1
, gen2
);
186 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
187 gen1
= GetFlushGeneration();
188 EXPECT_EQ(gen1
, gen2
);
190 // Simulate GPU process marking it as available.
191 QuerySync
* sync
= GetSync(query
);
192 sync
->process_count
= query
->submit_count();
193 sync
->result
= kResult
;
195 // Check CheckResultsAvailable.
196 EXPECT_TRUE(query
->CheckResultsAvailable(helper_
.get()));
197 EXPECT_EQ(kResult
, query
->GetResult());
198 EXPECT_FALSE(query
->NeverUsed());
199 EXPECT_FALSE(query
->Pending());
202 TEST_F(QueryTrackerTest
, Remove
) {
203 const GLuint kId1
= 123;
204 const int32 kToken
= 46;
205 const uint32 kResult
= 456;
208 QueryTracker::Query
* query
= query_tracker_
->CreateQuery(
209 kId1
, GL_ANY_SAMPLES_PASSED_EXT
);
210 ASSERT_TRUE(query
!= NULL
);
212 QuerySyncManager::Bucket
* bucket
= GetBucket(query
);
213 EXPECT_EQ(1u, bucket
->used_query_count
);
215 query
->MarkAsActive();
216 query
->MarkAsPending(kToken
);
218 query_tracker_
->RemoveQuery(kId1
);
219 // Check we get nothing for a non-existent query.
220 EXPECT_TRUE(query_tracker_
->GetQuery(kId1
) == NULL
);
222 // Check that memory was not freed.
223 EXPECT_EQ(1u, bucket
->used_query_count
);
225 // Simulate GPU process marking it as available.
226 QuerySync
* sync
= GetSync(query
);
227 sync
->process_count
= query
->submit_count();
228 sync
->result
= kResult
;
230 // Check FreeCompletedQueries.
231 query_tracker_
->FreeCompletedQueries();
232 EXPECT_EQ(0u, bucket
->used_query_count
);