Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: gpu/command_buffer/service/service_discardable_manager_unittest.cc

Issue 2814583002: Service/ClientDiscardableManager (Closed)
Patch Set: rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2017 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 "gpu/command_buffer/service/service_discardable_manager.h"
6
7 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/mailbox_manager.h"
10 #include "gpu/command_buffer/service/memory_tracking.h"
11 #include "gpu/command_buffer/service/mocks.h"
12 #include "gpu/command_buffer/service/test_helper.h"
13 #include "gpu/command_buffer/service/texture_manager.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/gl/gl_image_stub.h"
16 #include "ui/gl/gl_mock.h"
17 #include "ui/gl/gl_switches.h"
18
19 using ::testing::Pointee;
20 using ::testing::_;
21 using ::testing::Invoke;
22 using ::testing::Mock;
23 using ::testing::InSequence;
24
25 namespace gpu {
26 namespace gles2 {
27 namespace {
28
29 void CreateLockedHandlesForTesting(
30 std::unique_ptr<ServiceDiscardableHandle>* service_handle,
31 std::unique_ptr<ClientDiscardableHandle>* client_handle) {
32 std::unique_ptr<base::SharedMemory> shared_mem(new base::SharedMemory);
33 shared_mem->CreateAndMapAnonymous(sizeof(uint32_t));
34 scoped_refptr<gpu::Buffer> buffer =
35 MakeBufferFromSharedMemory(std::move(shared_mem), sizeof(uint32_t));
36
37 client_handle->reset(new ClientDiscardableHandle(buffer, 0, 0));
38 service_handle->reset(new ServiceDiscardableHandle(buffer, 0, 0));
39 }
40
41 ServiceDiscardableHandle CreateLockedServiceHandleForTesting() {
42 std::unique_ptr<ServiceDiscardableHandle> service_handle;
43 std::unique_ptr<ClientDiscardableHandle> client_handle;
44 CreateLockedHandlesForTesting(&service_handle, &client_handle);
45 return *service_handle;
46 }
47
48 class MockDestructionObserver : public TextureManager::DestructionObserver {
49 public:
50 MOCK_METHOD1(OnTextureManagerDestroying, void(TextureManager* manager));
51 MOCK_METHOD1(OnTextureRefDestroying, void(TextureRef* ref));
52 };
53
54 // A small texture that should never run up against our limits.
55 static const uint32_t kSmallTextureDim = 16;
56 static const size_t kSmallTextureSize = 4 * kSmallTextureDim * kSmallTextureDim;
57
58 } // namespace
59
60 class ServiceDiscardableManagerTest : public GpuServiceTest {
61 public:
62 ServiceDiscardableManagerTest() {}
63 ~ServiceDiscardableManagerTest() override {}
64
65 protected:
66 void SetUp() override {
67 GpuServiceTest::SetUp();
68 decoder_.reset(new MockGLES2Decoder());
69 feature_info_ = new FeatureInfo();
70 context_group_ = scoped_refptr<ContextGroup>(new ContextGroup(
71 gpu_preferences_, nullptr, nullptr, nullptr, nullptr, feature_info_,
72 false, nullptr, nullptr, GpuFeatureInfo(), &discardable_manager_));
73 TestHelper::SetupContextGroupInitExpectations(
74 gl_.get(), DisallowedFeatures(), "", "", CONTEXT_TYPE_OPENGLES2, false);
75 context_group_->Initialize(decoder_.get(), CONTEXT_TYPE_OPENGLES2,
76 DisallowedFeatures());
77 texture_manager_ = context_group_->texture_manager();
78 texture_manager_->AddObserver(&destruction_observer_);
79 }
80
81 void TearDown() override {
82 EXPECT_CALL(destruction_observer_, OnTextureManagerDestroying(_))
83 .RetiresOnSaturation();
84 // Texture manager will destroy the 6 black/default textures.
85 EXPECT_CALL(*gl_, DeleteTextures(TextureManager::kNumDefaultTextures, _));
86
87 context_group_->Destroy(decoder_.get(), true);
88 context_group_ = nullptr;
89 EXPECT_EQ(0u, discardable_manager_.NumCacheEntriesForTesting());
90 GpuServiceTest::TearDown();
91 }
92
93 void ExpectUnlockedTextureDeletion(uint32_t client_id) {
94 TextureRef* ref = discardable_manager_.UnlockedTextureRefForTesting(
95 client_id, texture_manager_);
96 ExpectTextureRefDeletion(ref);
97 }
98
99 void ExpectTextureDeletion(uint32_t client_id) {
100 TextureRef* ref = texture_manager_->GetTexture(client_id);
101 ExpectTextureRefDeletion(ref);
102 }
103
104 void ExpectTextureRefDeletion(TextureRef* ref) {
105 EXPECT_NE(nullptr, ref);
106 ref->AddObserver();
107 EXPECT_CALL(destruction_observer_, OnTextureRefDestroying(ref))
108 .WillOnce(Invoke([](TextureRef* ref) { ref->RemoveObserver(); }));
109 EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(ref->service_id())))
110 .RetiresOnSaturation();
111 }
112
113 ServiceDiscardableManager discardable_manager_;
114 GpuPreferences gpu_preferences_;
115 scoped_refptr<FeatureInfo> feature_info_;
116 MockDestructionObserver destruction_observer_;
117 TextureManager* texture_manager_;
118 std::unique_ptr<MockGLES2Decoder> decoder_;
119 scoped_refptr<gles2::ContextGroup> context_group_;
120 };
121
122 TEST_F(ServiceDiscardableManagerTest, BasicUsage) {
123 const GLuint kClientId = 1;
124 const GLuint kServiceId = 2;
125
126 // Create and insert a new texture.
127 texture_manager_->CreateTexture(kClientId, kServiceId);
128 auto handle = CreateLockedServiceHandleForTesting();
129 discardable_manager_.InsertLockedTexture(kClientId, kSmallTextureSize,
130 texture_manager_, handle);
131 EXPECT_EQ(1u, discardable_manager_.NumCacheEntriesForTesting());
132 EXPECT_TRUE(discardable_manager_.IsEntryLockedForTesting(kClientId,
133 texture_manager_));
134 EXPECT_NE(nullptr, texture_manager_->GetTexture(kClientId));
135
136 // Unlock the texture, ServiceDiscardableManager should take ownership of the
137 // TextureRef.
138 gles2::TextureRef* texture_to_unbind;
139 EXPECT_TRUE(discardable_manager_.UnlockTexture(kClientId, texture_manager_,
140 &texture_to_unbind));
141 EXPECT_NE(nullptr, texture_to_unbind);
142 EXPECT_FALSE(discardable_manager_.IsEntryLockedForTesting(kClientId,
143 texture_manager_));
144 EXPECT_EQ(nullptr, texture_manager_->GetTexture(kClientId));
145
146 // Re-lock the texture, the TextureManager should now resume ownership of
147 // the TextureRef.
148 discardable_manager_.LockTexture(kClientId, texture_manager_);
149 EXPECT_NE(nullptr, texture_manager_->GetTexture(kClientId));
150
151 // Delete the texture from the TextureManager, it should also be removed from
152 // the ServiceDiscardableManager.
153 ExpectTextureDeletion(kClientId);
154 texture_manager_->RemoveTexture(kClientId);
155 EXPECT_EQ(0u, discardable_manager_.NumCacheEntriesForTesting());
156 }
157
158 TEST_F(ServiceDiscardableManagerTest, DeleteAtShutdown) {
159 // Create 8 small textures (which will not hit memory limits), leaving every
160 // other one unlocked.
161 for (int i = 1; i <= 8; ++i) {
162 texture_manager_->CreateTexture(i, i);
163 auto handle = CreateLockedServiceHandleForTesting();
164 discardable_manager_.InsertLockedTexture(i, kSmallTextureSize,
165 texture_manager_, handle);
166 if (i % 2) {
167 TextureRef* texture_to_unbind;
168 EXPECT_TRUE(discardable_manager_.UnlockTexture(i, texture_manager_,
169 &texture_to_unbind));
170 EXPECT_NE(nullptr, texture_to_unbind);
171 }
172 }
173
174 // Expect that all 8 will be deleted at shutdown, regardless of
175 // locked/unlocked state.
176 for (int i = 1; i <= 8; ++i) {
177 if (i % 2) {
178 ExpectUnlockedTextureDeletion(i);
179 } else {
180 ExpectTextureDeletion(i);
181 }
182 }
183
184 // Let the test shut down, the expectations should be fulfilled.
185 }
186
187 TEST_F(ServiceDiscardableManagerTest, UnlockInvalid) {
188 const GLuint kClientId = 1;
189 gles2::TextureRef* texture_to_unbind;
190 EXPECT_FALSE(discardable_manager_.UnlockTexture(kClientId, texture_manager_,
191 &texture_to_unbind));
192 EXPECT_EQ(nullptr, texture_to_unbind);
193 }
194
195 TEST_F(ServiceDiscardableManagerTest, Limits) {
196 // Size textures so that four fit in the discardable manager.
197 const size_t texture_size = ServiceDiscardableManager::kMaxSize / 4;
198 const size_t large_texture_size = 3 * texture_size;
199
200 // Create 4 textures, this should fill up the discardable cache.
201 for (int i = 1; i < 5; ++i) {
202 texture_manager_->CreateTexture(i, i);
203 auto handle = CreateLockedServiceHandleForTesting();
204 discardable_manager_.InsertLockedTexture(i, texture_size, texture_manager_,
205 handle);
206 }
207
208 gles2::TextureRef* texture_to_unbind;
209 EXPECT_TRUE(discardable_manager_.UnlockTexture(3, texture_manager_,
210 &texture_to_unbind));
211 EXPECT_NE(nullptr, texture_to_unbind);
212 EXPECT_TRUE(discardable_manager_.UnlockTexture(1, texture_manager_,
213 &texture_to_unbind));
214 EXPECT_NE(nullptr, texture_to_unbind);
215 EXPECT_TRUE(discardable_manager_.UnlockTexture(2, texture_manager_,
216 &texture_to_unbind));
217 EXPECT_NE(nullptr, texture_to_unbind);
218 EXPECT_TRUE(discardable_manager_.UnlockTexture(4, texture_manager_,
219 &texture_to_unbind));
220 EXPECT_NE(nullptr, texture_to_unbind);
221
222 // Allocate four more textures - the previous 4 should be evicted / deleted in
223 // LRU order.
224 {
225 InSequence s;
226 ExpectUnlockedTextureDeletion(3);
227 ExpectUnlockedTextureDeletion(1);
228 ExpectUnlockedTextureDeletion(2);
229 ExpectUnlockedTextureDeletion(4);
230 }
231
232 for (int i = 5; i < 9; ++i) {
233 texture_manager_->CreateTexture(i, i);
234 auto handle = CreateLockedServiceHandleForTesting();
235 discardable_manager_.InsertLockedTexture(i, texture_size, texture_manager_,
236 handle);
237 }
238
239 // Ensure that the above expectations are handled by this point.
240 Mock::VerifyAndClearExpectations(gl_.get());
241 Mock::VerifyAndClearExpectations(&destruction_observer_);
242
243 // Unlock the next four textures:
244 EXPECT_TRUE(discardable_manager_.UnlockTexture(5, texture_manager_,
245 &texture_to_unbind));
246 EXPECT_NE(nullptr, texture_to_unbind);
247 EXPECT_TRUE(discardable_manager_.UnlockTexture(6, texture_manager_,
248 &texture_to_unbind));
249 EXPECT_NE(nullptr, texture_to_unbind);
250 EXPECT_TRUE(discardable_manager_.UnlockTexture(8, texture_manager_,
251 &texture_to_unbind));
252 EXPECT_NE(nullptr, texture_to_unbind);
253 EXPECT_TRUE(discardable_manager_.UnlockTexture(7, texture_manager_,
254 &texture_to_unbind));
255 EXPECT_NE(nullptr, texture_to_unbind);
256
257 // Allocate one more *large* texture, it should evict the LRU 3 textures.
258 {
259 InSequence s;
260 ExpectUnlockedTextureDeletion(5);
261 ExpectUnlockedTextureDeletion(6);
262 ExpectUnlockedTextureDeletion(8);
263 }
264
265 texture_manager_->CreateTexture(9, 9);
266 auto handle = CreateLockedServiceHandleForTesting();
267 discardable_manager_.InsertLockedTexture(9, large_texture_size,
268 texture_manager_, handle);
269
270 // Expect the two remaining textures to clean up.
271 ExpectTextureDeletion(9);
272 ExpectUnlockedTextureDeletion(7);
273 }
274
275 TEST_F(ServiceDiscardableManagerTest, TextureSizeChanged) {
276 const GLuint kClientId = 1;
277 const GLuint kServiceId = 2;
278
279 texture_manager_->CreateTexture(kClientId, kServiceId);
280 TextureRef* texture_ref = texture_manager_->GetTexture(kClientId);
281 auto handle = CreateLockedServiceHandleForTesting();
282 discardable_manager_.InsertLockedTexture(kClientId, 0, texture_manager_,
283 handle);
284 EXPECT_EQ(0u, discardable_manager_.TotalSizeForTesting());
285 texture_manager_->SetTarget(texture_ref, GL_TEXTURE_2D);
286 texture_manager_->SetLevelInfo(texture_ref, GL_TEXTURE_2D, 0, GL_RGBA,
287 kSmallTextureDim, kSmallTextureDim, 1, 0,
288 GL_RGBA, GL_UNSIGNED_BYTE,
289 gfx::Rect(kSmallTextureDim, kSmallTextureDim));
290 EXPECT_EQ(kSmallTextureSize, discardable_manager_.TotalSizeForTesting());
291
292 ExpectTextureDeletion(kClientId);
293 }
294
295 TEST_F(ServiceDiscardableManagerTest, OwnershipOnUnlock) {
296 const GLuint kClientId = 1;
297 const GLuint kServiceId = 2;
298
299 std::unique_ptr<ServiceDiscardableHandle> service_handle;
300 std::unique_ptr<ClientDiscardableHandle> client_handle;
301 CreateLockedHandlesForTesting(&service_handle, &client_handle);
302 texture_manager_->CreateTexture(kClientId, kServiceId);
303 discardable_manager_.InsertLockedTexture(kClientId, kSmallTextureSize,
304 texture_manager_, *service_handle);
305
306 // Ensure that the service ref count is used to determine ownership changes.
307 client_handle->Lock();
308 TextureRef* texture_to_unbind;
309 discardable_manager_.UnlockTexture(kClientId, texture_manager_,
310 &texture_to_unbind);
311 EXPECT_NE(nullptr, texture_to_unbind);
312 EXPECT_TRUE(discardable_manager_.IsEntryLockedForTesting(kClientId,
313 texture_manager_));
314
315 // Get the counts back in sync.
316 discardable_manager_.LockTexture(kClientId, texture_manager_);
317 discardable_manager_.UnlockTexture(kClientId, texture_manager_,
318 &texture_to_unbind);
319 EXPECT_NE(nullptr, texture_to_unbind);
320 EXPECT_FALSE(discardable_manager_.IsEntryLockedForTesting(kClientId,
321 texture_manager_));
322
323 // Re-lock the texture twice.
324 client_handle->Lock();
325 discardable_manager_.LockTexture(kClientId, texture_manager_);
326 client_handle->Lock();
327 discardable_manager_.LockTexture(kClientId, texture_manager_);
328
329 // Ensure that unlocking once doesn't cause us to unbind the texture.
330 discardable_manager_.UnlockTexture(kClientId, texture_manager_,
331 &texture_to_unbind);
332 EXPECT_EQ(nullptr, texture_to_unbind);
333 EXPECT_TRUE(discardable_manager_.IsEntryLockedForTesting(kClientId,
334 texture_manager_));
335
336 // The second unlock should unbind/unlock the texture.
337 discardable_manager_.UnlockTexture(kClientId, texture_manager_,
338 &texture_to_unbind);
339 EXPECT_NE(nullptr, texture_to_unbind);
340 EXPECT_FALSE(discardable_manager_.IsEntryLockedForTesting(kClientId,
341 texture_manager_));
342
343 ExpectUnlockedTextureDeletion(kClientId);
344 }
345
346 TEST_F(ServiceDiscardableManagerTest, BindGeneratedTextureLock) {
347 const GLuint kClientId = 1;
348 const GLuint kServiceId = 2;
349 const GLuint kGeneratedServiceId = 3;
350
351 // Create and insert a new texture.
352 texture_manager_->CreateTexture(kClientId, kServiceId);
353 auto handle = CreateLockedServiceHandleForTesting();
354 discardable_manager_.InsertLockedTexture(kClientId, kSmallTextureSize,
355 texture_manager_, handle);
356
357 // Unlock the texture, ServiceDiscardableManager should take ownership of the
358 // TextureRef.
359 gles2::TextureRef* texture_to_unbind;
360 EXPECT_TRUE(discardable_manager_.UnlockTexture(kClientId, texture_manager_,
361 &texture_to_unbind));
362 EXPECT_NE(nullptr, texture_to_unbind);
363 EXPECT_EQ(nullptr, texture_manager_->GetTexture(kClientId));
364
365 // Generate a new texture for the given client id, similar to "bind generates
366 // resource" behavior.
367 texture_manager_->CreateTexture(kClientId, kGeneratedServiceId);
368 TextureRef* generated_texture_ref = texture_manager_->GetTexture(kClientId);
369
370 // Re-lock the texture, the TextureManager should delete the returned
371 // texture and keep the generated one.
372 ExpectUnlockedTextureDeletion(kClientId);
373 discardable_manager_.LockTexture(kClientId, texture_manager_);
374 EXPECT_EQ(generated_texture_ref, texture_manager_->GetTexture(kClientId));
375
376 // Delete the texture from the TextureManager, it should also be removed from
377 // the ServiceDiscardableManager.
378 ExpectTextureDeletion(kClientId);
379 texture_manager_->RemoveTexture(kClientId);
380 EXPECT_EQ(0u, discardable_manager_.NumCacheEntriesForTesting());
381 }
382
383 TEST_F(ServiceDiscardableManagerTest, BindGeneratedTextureInitialization) {
384 const GLuint kClientId = 1;
385 const GLuint kServiceId = 2;
386 const GLuint kGeneratedServiceId = 3;
387
388 // Create and insert a new texture.
389 texture_manager_->CreateTexture(kClientId, kServiceId);
390 auto handle = CreateLockedServiceHandleForTesting();
391 discardable_manager_.InsertLockedTexture(kClientId, kSmallTextureSize,
392 texture_manager_, handle);
393
394 // Unlock the texture, ServiceDiscardableManager should take ownership of the
395 // TextureRef.
396 gles2::TextureRef* texture_to_unbind;
397 EXPECT_TRUE(discardable_manager_.UnlockTexture(kClientId, texture_manager_,
398 &texture_to_unbind));
399 EXPECT_NE(nullptr, texture_to_unbind);
400 EXPECT_EQ(nullptr, texture_manager_->GetTexture(kClientId));
401
402 // Generate a new texture for the given client id, similar to "bind generates
403 // resource" behavior.
404 texture_manager_->CreateTexture(kClientId, kGeneratedServiceId);
405 TextureRef* generated_texture_ref = texture_manager_->GetTexture(kClientId);
406
407 // Re-initialize the texture, the TextureManager should delete the old
408 // texture and keep the generated one.
409 ExpectUnlockedTextureDeletion(kClientId);
410 discardable_manager_.InsertLockedTexture(kClientId, kSmallTextureSize,
411 texture_manager_, handle);
412 EXPECT_EQ(generated_texture_ref, texture_manager_->GetTexture(kClientId));
413
414 ExpectTextureDeletion(kClientId);
415 }
416
417 TEST_F(ServiceDiscardableManagerTest, BindGeneratedTextureSizeChange) {
418 const GLuint kClientId = 1;
419 const GLuint kServiceId = 2;
420 const GLuint kGeneratedServiceId = 3;
421
422 // Create and insert a new texture.
423 texture_manager_->CreateTexture(kClientId, kServiceId);
424 auto handle = CreateLockedServiceHandleForTesting();
425 discardable_manager_.InsertLockedTexture(kClientId, 0, texture_manager_,
426 handle);
427
428 // Unlock the texture, ServiceDiscardableManager should take ownership of the
429 // TextureRef.
430 gles2::TextureRef* texture_to_unbind;
431 EXPECT_TRUE(discardable_manager_.UnlockTexture(kClientId, texture_manager_,
432 &texture_to_unbind));
433 EXPECT_NE(nullptr, texture_to_unbind);
434 EXPECT_EQ(nullptr, texture_manager_->GetTexture(kClientId));
435
436 // Generate a new texture for the given client id, similar to "bind generates
437 // resource" behavior.
438 texture_manager_->CreateTexture(kClientId, kGeneratedServiceId);
439 TextureRef* generated_texture_ref = texture_manager_->GetTexture(kClientId);
440
441 // Re-size the generated texture. The tracked size should update.
442 EXPECT_EQ(0u, discardable_manager_.TotalSizeForTesting());
443 texture_manager_->SetTarget(generated_texture_ref, GL_TEXTURE_2D);
444 texture_manager_->SetLevelInfo(generated_texture_ref, GL_TEXTURE_2D, 0,
445 GL_RGBA, kSmallTextureDim, kSmallTextureDim, 1,
446 0, GL_RGBA, GL_UNSIGNED_BYTE,
447 gfx::Rect(kSmallTextureDim, kSmallTextureDim));
448 EXPECT_EQ(kSmallTextureSize, discardable_manager_.TotalSizeForTesting());
449
450 ExpectUnlockedTextureDeletion(kClientId);
451 ExpectTextureDeletion(kClientId);
452 }
453
454 } // namespace gles2
455 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/service_discardable_manager.cc ('k') | gpu/command_buffer/service/texture_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698