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. 4 5 // Tests for the Command Buffer Helper. 6 7 #include "gpu/command_buffer/client/transfer_buffer.h" 8 9 #include "base/compiler_specific.h" 10 #include "gpu/command_buffer/client/client_test_helper.h" 11 #include "gpu/command_buffer/client/cmd_buffer_helper.h" 12 #include "gpu/command_buffer/common/command_buffer.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gmock/include/gmock/gmock.h" 15 16 using ::testing::_; 17 using ::testing::AtMost; 18 using ::testing::Invoke; 19 using ::testing::Return; 20 using ::testing::SetArgPointee; 21 using ::testing::StrictMock; 22 23 namespace gpu { 24 25 26 class TransferBufferTest : public testing::Test { 27 protected: 28 static const int32 kNumCommandEntries = 400; 29 static const int32 kCommandBufferSizeBytes = 30 kNumCommandEntries * sizeof(CommandBufferEntry); 31 static const unsigned int kStartingOffset = 64; 32 static const unsigned int kAlignment = 4; 33 static const size_t kTransferBufferSize = 256; 34 35 TransferBufferTest() 36 : transfer_buffer_id_(0) { 37 } 38 39 virtual void SetUp() OVERRIDE; 40 virtual void TearDown() OVERRIDE; 41 42 virtual void Initialize(unsigned int size_to_flush) { 43 ASSERT_TRUE(transfer_buffer_->Initialize( 44 kTransferBufferSize, 45 kStartingOffset, 46 kTransferBufferSize, 47 kTransferBufferSize, 48 kAlignment, 49 size_to_flush)); 50 } 51 52 MockClientCommandBufferMockFlush* command_buffer() const { 53 return command_buffer_.get(); 54 } 55 56 scoped_ptr<MockClientCommandBufferMockFlush> command_buffer_; 57 scoped_ptr<CommandBufferHelper> helper_; 58 scoped_ptr<TransferBuffer> transfer_buffer_; 59 int32 transfer_buffer_id_; 60 }; 61 62 void TransferBufferTest::SetUp() { 63 command_buffer_.reset(new StrictMock<MockClientCommandBufferMockFlush>()); 64 ASSERT_TRUE(command_buffer_->Initialize()); 65 66 helper_.reset(new CommandBufferHelper(command_buffer())); 67 ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes)); 68 69 transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId(); 70 71 transfer_buffer_.reset(new TransferBuffer(helper_.get())); 72 } 73 74 void TransferBufferTest::TearDown() { 75 if (transfer_buffer_->HaveBuffer()) { 76 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 77 .Times(1) 78 .RetiresOnSaturation(); 79 } 80 // For command buffer. 81 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 82 .Times(1) 83 .RetiresOnSaturation(); 84 EXPECT_CALL(*command_buffer(), OnFlush()).Times(AtMost(1)); 85 transfer_buffer_.reset(); 86 } 87 88 // GCC requires these declarations, but MSVC requires they not be present 89 #ifndef _MSC_VER 90 const int32 TransferBufferTest::kNumCommandEntries; 91 const int32 TransferBufferTest::kCommandBufferSizeBytes; 92 const unsigned int TransferBufferTest::kStartingOffset; 93 const unsigned int TransferBufferTest::kAlignment; 94 const size_t TransferBufferTest::kTransferBufferSize; 95 #endif 96 97 TEST_F(TransferBufferTest, Basic) { 98 Initialize(0); 99 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 100 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId()); 101 EXPECT_EQ( 102 kTransferBufferSize - kStartingOffset, 103 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 104 } 105 106 TEST_F(TransferBufferTest, Free) { 107 Initialize(0); 108 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 109 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId()); 110 111 // Free buffer. 112 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 113 .Times(1) 114 .RetiresOnSaturation(); 115 transfer_buffer_->Free(); 116 // See it's freed. 117 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 118 // See that it gets reallocated. 119 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId()); 120 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 121 122 // Free buffer. 123 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 124 .Times(1) 125 .RetiresOnSaturation(); 126 transfer_buffer_->Free(); 127 // See it's freed. 128 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 129 // See that it gets reallocated. 130 EXPECT_TRUE(transfer_buffer_->GetResultBuffer() != NULL); 131 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 132 133 // Free buffer. 134 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 135 .Times(1) 136 .RetiresOnSaturation(); 137 transfer_buffer_->Free(); 138 // See it's freed. 139 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 140 // See that it gets reallocated. 141 unsigned int size = 0; 142 void* data = transfer_buffer_->AllocUpTo(1, &size); 143 EXPECT_TRUE(data != NULL); 144 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 145 transfer_buffer_->FreePendingToken(data, 1); 146 147 // Free buffer. 148 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 149 .Times(1) 150 .RetiresOnSaturation(); 151 transfer_buffer_->Free(); 152 // See it's freed. 153 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 154 // See that it gets reallocated. 155 transfer_buffer_->GetResultOffset(); 156 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 157 158 EXPECT_EQ( 159 kTransferBufferSize - kStartingOffset, 160 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 161 162 // Test freeing twice. 163 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 164 .Times(1) 165 .RetiresOnSaturation(); 166 transfer_buffer_->Free(); 167 transfer_buffer_->Free(); 168 } 169 170 TEST_F(TransferBufferTest, TooLargeAllocation) { 171 Initialize(0); 172 // Check that we can't allocate large than max size. 173 void* ptr = transfer_buffer_->Alloc(kTransferBufferSize + 1); 174 EXPECT_TRUE(ptr == NULL); 175 // Check we if we try to allocate larger than max we get max. 176 unsigned int size_allocated = 0; 177 ptr = transfer_buffer_->AllocUpTo( 178 kTransferBufferSize + 1, &size_allocated); 179 ASSERT_TRUE(ptr != NULL); 180 EXPECT_EQ(kTransferBufferSize - kStartingOffset, size_allocated); 181 transfer_buffer_->FreePendingToken(ptr, 1); 182 } 183 184 TEST_F(TransferBufferTest, Flush) { 185 Initialize(16u); 186 unsigned int size_allocated = 0; 187 for (int i = 0; i < 8; ++i) { 188 void* ptr = transfer_buffer_->AllocUpTo(8u, &size_allocated); 189 ASSERT_TRUE(ptr != NULL); 190 EXPECT_EQ(8u, size_allocated); 191 if (i % 2) { 192 EXPECT_CALL(*command_buffer(), Flush(_)) 193 .Times(1) 194 .RetiresOnSaturation(); 195 } 196 transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken()); 197 } 198 for (int i = 0; i < 8; ++i) { 199 void* ptr = transfer_buffer_->Alloc(8u); 200 ASSERT_TRUE(ptr != NULL); 201 if (i % 2) { 202 EXPECT_CALL(*command_buffer(), Flush(_)) 203 .Times(1) 204 .RetiresOnSaturation(); 205 } 206 transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken()); 207 } 208 } 209 210 class MockClientCommandBufferCanFail : public MockClientCommandBufferMockFlush { 211 public: 212 MockClientCommandBufferCanFail() { 213 } 214 virtual ~MockClientCommandBufferCanFail() { 215 } 216 217 MOCK_METHOD2(CreateTransferBuffer, Buffer(size_t size, int32* id)); 218 219 Buffer RealCreateTransferBuffer(size_t size, int32* id) { 220 return MockCommandBufferBase::CreateTransferBuffer(size, id); 221 } 222 }; 223 224 class TransferBufferExpandContractTest : public testing::Test { 225 protected: 226 static const int32 kNumCommandEntries = 400; 227 static const int32 kCommandBufferSizeBytes = 228 kNumCommandEntries * sizeof(CommandBufferEntry); 229 static const unsigned int kStartingOffset = 64; 230 static const unsigned int kAlignment = 4; 231 static const size_t kStartTransferBufferSize = 256; 232 static const size_t kMaxTransferBufferSize = 1024; 233 static const size_t kMinTransferBufferSize = 128; 234 235 TransferBufferExpandContractTest() 236 : transfer_buffer_id_(0) { 237 } 238 239 virtual void SetUp() OVERRIDE; 240 virtual void TearDown() OVERRIDE; 241 242 MockClientCommandBufferCanFail* command_buffer() const { 243 return command_buffer_.get(); 244 } 245 246 scoped_ptr<MockClientCommandBufferCanFail> command_buffer_; 247 scoped_ptr<CommandBufferHelper> helper_; 248 scoped_ptr<TransferBuffer> transfer_buffer_; 249 int32 transfer_buffer_id_; 250 }; 251 252 void TransferBufferExpandContractTest::SetUp() { 253 command_buffer_.reset(new StrictMock<MockClientCommandBufferCanFail>()); 254 ASSERT_TRUE(command_buffer_->Initialize()); 255 256 EXPECT_CALL(*command_buffer(), 257 CreateTransferBuffer(kCommandBufferSizeBytes, _)) 258 .WillOnce(Invoke( 259 command_buffer(), 260 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 261 .RetiresOnSaturation(); 262 263 helper_.reset(new CommandBufferHelper(command_buffer())); 264 ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes)); 265 266 transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId(); 267 268 EXPECT_CALL(*command_buffer(), 269 CreateTransferBuffer(kStartTransferBufferSize, _)) 270 .WillOnce(Invoke( 271 command_buffer(), 272 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 273 .RetiresOnSaturation(); 274 275 transfer_buffer_.reset(new TransferBuffer(helper_.get())); 276 ASSERT_TRUE(transfer_buffer_->Initialize( 277 kStartTransferBufferSize, 278 kStartingOffset, 279 kMinTransferBufferSize, 280 kMaxTransferBufferSize, 281 kAlignment, 282 0)); 283 } 284 285 void TransferBufferExpandContractTest::TearDown() { 286 if (transfer_buffer_->HaveBuffer()) { 287 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 288 .Times(1) 289 .RetiresOnSaturation(); 290 } 291 // For command buffer. 292 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 293 .Times(1) 294 .RetiresOnSaturation(); 295 transfer_buffer_.reset(); 296 } 297 298 // GCC requires these declarations, but MSVC requires they not be present 299 #ifndef _MSC_VER 300 const int32 TransferBufferExpandContractTest::kNumCommandEntries; 301 const int32 TransferBufferExpandContractTest::kCommandBufferSizeBytes; 302 const unsigned int TransferBufferExpandContractTest::kStartingOffset; 303 const unsigned int TransferBufferExpandContractTest::kAlignment; 304 const size_t TransferBufferExpandContractTest::kStartTransferBufferSize; 305 const size_t TransferBufferExpandContractTest::kMaxTransferBufferSize; 306 const size_t TransferBufferExpandContractTest::kMinTransferBufferSize; 307 #endif 308 309 TEST_F(TransferBufferExpandContractTest, Expand) { 310 // Check it starts at starting size. 311 EXPECT_EQ( 312 kStartTransferBufferSize - kStartingOffset, 313 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 314 315 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 316 .Times(1) 317 .RetiresOnSaturation(); 318 EXPECT_CALL(*command_buffer(), 319 CreateTransferBuffer(kStartTransferBufferSize * 2, _)) 320 .WillOnce(Invoke( 321 command_buffer(), 322 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 323 .RetiresOnSaturation(); 324 325 // Try next power of 2. 326 const size_t kSize1 = 512 - kStartingOffset; 327 unsigned int size_allocated = 0; 328 void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated); 329 ASSERT_TRUE(ptr != NULL); 330 EXPECT_EQ(kSize1, size_allocated); 331 EXPECT_EQ(kSize1, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 332 transfer_buffer_->FreePendingToken(ptr, 1); 333 334 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 335 .Times(1) 336 .RetiresOnSaturation(); 337 EXPECT_CALL(*command_buffer(), 338 CreateTransferBuffer(kMaxTransferBufferSize, _)) 339 .WillOnce(Invoke( 340 command_buffer(), 341 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 342 .RetiresOnSaturation(); 343 344 // Try next power of 2. 345 const size_t kSize2 = 1024 - kStartingOffset; 346 ptr = transfer_buffer_->AllocUpTo(kSize2, &size_allocated); 347 ASSERT_TRUE(ptr != NULL); 348 EXPECT_EQ(kSize2, size_allocated); 349 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 350 transfer_buffer_->FreePendingToken(ptr, 1); 351 352 // Try next one more. Should not go past max. 353 size_allocated = 0; 354 const size_t kSize3 = kSize2 + 1; 355 ptr = transfer_buffer_->AllocUpTo(kSize3, &size_allocated); 356 EXPECT_EQ(kSize2, size_allocated); 357 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 358 transfer_buffer_->FreePendingToken(ptr, 1); 359 } 360 361 TEST_F(TransferBufferExpandContractTest, Contract) { 362 // Check it starts at starting size. 363 EXPECT_EQ( 364 kStartTransferBufferSize - kStartingOffset, 365 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 366 367 // Free buffer. 368 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 369 .Times(1) 370 .RetiresOnSaturation(); 371 transfer_buffer_->Free(); 372 // See it's freed. 373 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 374 375 // Try to allocate again, fail first request 376 EXPECT_CALL(*command_buffer(), 377 CreateTransferBuffer(kStartTransferBufferSize, _)) 378 .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer()))) 379 .RetiresOnSaturation(); 380 EXPECT_CALL(*command_buffer(), 381 CreateTransferBuffer(kMinTransferBufferSize, _)) 382 .WillOnce(Invoke( 383 command_buffer(), 384 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 385 .RetiresOnSaturation(); 386 387 const size_t kSize1 = 256 - kStartingOffset; 388 const size_t kSize2 = 128 - kStartingOffset; 389 unsigned int size_allocated = 0; 390 void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated); 391 ASSERT_TRUE(ptr != NULL); 392 EXPECT_EQ(kSize2, size_allocated); 393 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 394 transfer_buffer_->FreePendingToken(ptr, 1); 395 396 // Free buffer. 397 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 398 .Times(1) 399 .RetiresOnSaturation(); 400 transfer_buffer_->Free(); 401 // See it's freed. 402 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 403 404 // Try to allocate again, 405 EXPECT_CALL(*command_buffer(), 406 CreateTransferBuffer(kMinTransferBufferSize, _)) 407 .WillOnce(Invoke( 408 command_buffer(), 409 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 410 .RetiresOnSaturation(); 411 412 ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated); 413 ASSERT_TRUE(ptr != NULL); 414 EXPECT_EQ(kSize2, size_allocated); 415 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 416 transfer_buffer_->FreePendingToken(ptr, 1); 417 } 418 419 TEST_F(TransferBufferExpandContractTest, OutOfMemory) { 420 // Free buffer. 421 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 422 .Times(1) 423 .RetiresOnSaturation(); 424 transfer_buffer_->Free(); 425 // See it's freed. 426 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 427 428 // Try to allocate again, fail both requests. 429 EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_, _)) 430 .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer()))) 431 .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer()))) 432 .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer()))) 433 .RetiresOnSaturation(); 434 435 const size_t kSize1 = 512 - kStartingOffset; 436 unsigned int size_allocated = 0; 437 void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated); 438 ASSERT_TRUE(ptr == NULL); 439 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 440 } 441 442 TEST_F(TransferBufferExpandContractTest, ReallocsToDefault) { 443 // Free buffer. 444 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 445 .Times(1) 446 .RetiresOnSaturation(); 447 transfer_buffer_->Free(); 448 // See it's freed. 449 EXPECT_FALSE(transfer_buffer_->HaveBuffer()); 450 451 // See that it gets reallocated. 452 EXPECT_CALL(*command_buffer(), 453 CreateTransferBuffer(kStartTransferBufferSize, _)) 454 .WillOnce(Invoke( 455 command_buffer(), 456 &MockClientCommandBufferCanFail::RealCreateTransferBuffer)) 457 .RetiresOnSaturation(); 458 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId()); 459 EXPECT_TRUE(transfer_buffer_->HaveBuffer()); 460 461 // Check it's the default size. 462 EXPECT_EQ( 463 kStartTransferBufferSize - kStartingOffset, 464 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); 465 } 466 467 } // namespace gpu 468 469 470