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 // Flush only once if no more flushes happened between a call to
165 // EndQuery command and CheckResultsAvailable
166 // Advance put_ so flush calls in CheckResultsAvailable go through
167 // and updates flush_generation count
170 // Store FlushGeneration count after EndQuery is called
171 uint32 gen1
= GetFlushGeneration();
173 // Check CheckResultsAvailable.
174 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
175 EXPECT_FALSE(query
->NeverUsed());
176 EXPECT_TRUE(query
->Pending());
178 uint32 gen2
= GetFlushGeneration();
179 EXPECT_NE(gen1
, gen2
);
181 // Repeated calls to CheckResultsAvailable should not flush unnecessarily
182 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
183 gen1
= GetFlushGeneration();
184 EXPECT_EQ(gen1
, gen2
);
185 EXPECT_FALSE(query
->CheckResultsAvailable(helper_
.get()));
186 gen1
= GetFlushGeneration();
187 EXPECT_EQ(gen1
, gen2
);
189 // Simulate GPU process marking it as available.
190 QuerySync
* sync
= GetSync(query
);
191 sync
->process_count
= query
->submit_count();
192 sync
->result
= kResult
;
194 // Check CheckResultsAvailable.
195 EXPECT_TRUE(query
->CheckResultsAvailable(helper_
.get()));
196 EXPECT_EQ(kResult
, query
->GetResult());
197 EXPECT_FALSE(query
->NeverUsed());
198 EXPECT_FALSE(query
->Pending());
201 TEST_F(QueryTrackerTest
, Remove
) {
202 const GLuint kId1
= 123;
203 const int32 kToken
= 46;
204 const uint32 kResult
= 456;
207 QueryTracker::Query
* query
= query_tracker_
->CreateQuery(
208 kId1
, GL_ANY_SAMPLES_PASSED_EXT
);
209 ASSERT_TRUE(query
!= NULL
);
211 QuerySyncManager::Bucket
* bucket
= GetBucket(query
);
212 EXPECT_EQ(1u, bucket
->used_query_count
);
214 query
->MarkAsActive();
215 query
->MarkAsPending(kToken
);
217 query_tracker_
->RemoveQuery(kId1
);
218 // Check we get nothing for a non-existent query.
219 EXPECT_TRUE(query_tracker_
->GetQuery(kId1
) == NULL
);
221 // Check that memory was not freed.
222 EXPECT_EQ(1u, bucket
->used_query_count
);
224 // Simulate GPU process marking it as available.
225 QuerySync
* sync
= GetSync(query
);
226 sync
->process_count
= query
->submit_count();
227 sync
->result
= kResult
;
229 // Check FreeCompletedQueries.
230 query_tracker_
->FreeCompletedQueries();
231 EXPECT_EQ(0u, bucket
->used_query_count
);