OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Test.h" | 8 #include "Test.h" |
9 // This is a GPU-backend specific test | 9 // This is a GPU-backend specific test |
10 #if SK_SUPPORT_GPU | 10 #if SK_SUPPORT_GPU |
11 #include "GrMemoryPool.h" | 11 #include "GrMemoryPool.h" |
12 #include "SkRandom.h" | 12 #include "SkRandom.h" |
| 13 #include "SkTArray.h" |
13 #include "SkTDArray.h" | 14 #include "SkTDArray.h" |
14 #include "SkTemplates.h" | 15 #include "SkTemplates.h" |
15 | 16 |
16 // A is the top of an inheritance tree of classes that overload op new and | 17 // A is the top of an inheritance tree of classes that overload op new and |
17 // and delete to use a GrMemoryPool. The objects have values of different types | 18 // and delete to use a GrMemoryPool. The objects have values of different types |
18 // that can be set and checked. | 19 // that can be set and checked. |
19 class A { | 20 class A { |
20 public: | 21 public: |
21 A() {} | 22 A() {} |
22 virtual void setValues(int v) { | 23 virtual void setValues(int v) { |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 221 } |
221 for (int i = 0; i < instanceRecs.count(); ++i) { | 222 for (int i = 0; i < instanceRecs.count(); ++i) { |
222 Rec& rec = instanceRecs[i]; | 223 Rec& rec = instanceRecs[i]; |
223 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)
); | 224 REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue)
); |
224 delete rec.fInstance; | 225 delete rec.fInstance; |
225 } | 226 } |
226 } | 227 } |
227 } | 228 } |
228 } | 229 } |
229 | 230 |
| 231 // GrMemoryPool requires that it's empty at the point of destruction. This helps |
| 232 // achieving that by releasing all added memory in the destructor. |
| 233 class AutoPoolReleaser { |
| 234 public: |
| 235 AutoPoolReleaser(GrMemoryPool& pool): fPool(pool) { |
| 236 } |
| 237 ~AutoPoolReleaser() { |
| 238 for (void* ptr: fAllocated) { |
| 239 fPool.release(ptr); |
| 240 } |
| 241 } |
| 242 void add(void* ptr) { |
| 243 fAllocated.push_back(ptr); |
| 244 } |
| 245 private: |
| 246 GrMemoryPool& fPool; |
| 247 SkTArray<void*> fAllocated; |
| 248 }; |
| 249 |
| 250 DEF_TEST(GrMemoryPoolAPI, reporter) { |
| 251 constexpr size_t kSmallestMinAllocSize = GrMemoryPool::kSmallestMinAllocSize
; |
| 252 |
| 253 // Allocates memory until pool adds a new block (pool.size() changes). |
| 254 auto allocateMemory = [](GrMemoryPool& pool, AutoPoolReleaser& r) { |
| 255 size_t origPoolSize = pool.size(); |
| 256 while (pool.size() == origPoolSize) { |
| 257 r.add(pool.allocate(31)); |
| 258 } |
| 259 }; |
| 260 |
| 261 // Effective prealloc space capacity is >= kSmallestMinAllocSize. |
| 262 { |
| 263 GrMemoryPool pool(0, 0); |
| 264 REPORTER_ASSERT(reporter, pool.preallocSize() == kSmallestMinAllocSize); |
| 265 } |
| 266 |
| 267 // Effective prealloc space capacity is >= minAllocSize. |
| 268 { |
| 269 constexpr size_t kMinAllocSize = kSmallestMinAllocSize * 2; |
| 270 GrMemoryPool pool(kSmallestMinAllocSize, kMinAllocSize); |
| 271 REPORTER_ASSERT(reporter, pool.preallocSize() == kMinAllocSize); |
| 272 } |
| 273 |
| 274 // Effective block size capacity >= kSmallestMinAllocSize. |
| 275 { |
| 276 GrMemoryPool pool(kSmallestMinAllocSize, kSmallestMinAllocSize / 2); |
| 277 AutoPoolReleaser r(pool); |
| 278 |
| 279 allocateMemory(pool, r); |
| 280 REPORTER_ASSERT(reporter, pool.size() == kSmallestMinAllocSize); |
| 281 } |
| 282 |
| 283 // Pool allocates exactly preallocSize on creation. |
| 284 { |
| 285 constexpr size_t kPreallocSize = kSmallestMinAllocSize * 5; |
| 286 GrMemoryPool pool(kPreallocSize, 0); |
| 287 REPORTER_ASSERT(reporter, pool.preallocSize() == kPreallocSize); |
| 288 } |
| 289 |
| 290 // Pool allocates exactly minAllocSize when it expands. |
| 291 { |
| 292 constexpr size_t kMinAllocSize = kSmallestMinAllocSize * 7; |
| 293 GrMemoryPool pool(0, kMinAllocSize); |
| 294 AutoPoolReleaser r(pool); |
| 295 |
| 296 allocateMemory(pool, r); |
| 297 REPORTER_ASSERT(reporter, pool.size() == kMinAllocSize); |
| 298 |
| 299 allocateMemory(pool, r); |
| 300 REPORTER_ASSERT(reporter, pool.size() == 2 * kMinAllocSize); |
| 301 } |
| 302 |
| 303 // When asked to allocate amount > minAllocSize, pool allocates larger block |
| 304 // to accommodate all internal structures. |
| 305 { |
| 306 constexpr size_t kMinAllocSize = kSmallestMinAllocSize * 2; |
| 307 GrMemoryPool pool(kSmallestMinAllocSize, kMinAllocSize); |
| 308 AutoPoolReleaser r(pool); |
| 309 |
| 310 REPORTER_ASSERT(reporter, pool.size() == 0); |
| 311 |
| 312 constexpr size_t hugeSize = 10 * kMinAllocSize; |
| 313 r.add(pool.allocate(hugeSize)); |
| 314 REPORTER_ASSERT(reporter, pool.size() > hugeSize); |
| 315 |
| 316 // Block size allocated to accommodate huge request doesn't include any
extra |
| 317 // space, so next allocation request allocates a new block. |
| 318 size_t hugeBlockSize = pool.size(); |
| 319 r.add(pool.allocate(0)); |
| 320 REPORTER_ASSERT(reporter, pool.size() == hugeBlockSize + kMinAllocSize); |
| 321 } |
| 322 } |
| 323 |
| 324 DEF_TEST(GrObjectMemoryPoolAPI, reporter) { |
| 325 struct Data { |
| 326 int value[5]; |
| 327 }; |
| 328 using DataObjectPool = GrObjectMemoryPool<Data>; |
| 329 constexpr size_t kSmallestMinAllocCount = DataObjectPool::kSmallestMinAllocC
ount; |
| 330 |
| 331 // Allocates objects until pool adds a new block (pool.size() changes). |
| 332 // Returns number of objects that fit into the current block (i.e. before po
ol.size() |
| 333 // changed; newly allocated block always ends up with one object allocated f
rom it). |
| 334 auto allocateObjects = [](DataObjectPool& pool, AutoPoolReleaser& r) -> size
_t { |
| 335 size_t count = 0; |
| 336 size_t origPoolSize = pool.size(); |
| 337 while (pool.size() == origPoolSize) { |
| 338 r.add(pool.allocate()); |
| 339 count++; |
| 340 } |
| 341 return count - 1; |
| 342 }; |
| 343 |
| 344 // Effective prealloc space capacity is >= kSmallestMinAllocCount. |
| 345 { |
| 346 DataObjectPool pool(kSmallestMinAllocCount / 3, 0); |
| 347 AutoPoolReleaser r(pool); |
| 348 |
| 349 size_t preallocCount = allocateObjects(pool, r); |
| 350 REPORTER_ASSERT(reporter, preallocCount == kSmallestMinAllocCount); |
| 351 } |
| 352 |
| 353 // Effective prealloc space capacity is >= minAllocCount. |
| 354 { |
| 355 DataObjectPool pool(kSmallestMinAllocCount, 2 * kSmallestMinAllocCount); |
| 356 AutoPoolReleaser r(pool); |
| 357 |
| 358 size_t preallocCount = allocateObjects(pool, r); |
| 359 REPORTER_ASSERT(reporter, preallocCount == 2 * kSmallestMinAllocCount); |
| 360 } |
| 361 |
| 362 // Effective block capacity is >= kSmallestMinAllocCount. |
| 363 { |
| 364 DataObjectPool pool(kSmallestMinAllocCount, kSmallestMinAllocCount / 2); |
| 365 AutoPoolReleaser r(pool); |
| 366 |
| 367 // Fill prealloc space |
| 368 allocateObjects(pool, r); |
| 369 |
| 370 size_t minAllocCount = 1 + allocateObjects(pool, r); |
| 371 REPORTER_ASSERT(reporter, minAllocCount == kSmallestMinAllocCount); |
| 372 } |
| 373 |
| 374 // Pool allocates space for exactly preallocCount objects on creation. |
| 375 { |
| 376 constexpr size_t kPreallocCount = kSmallestMinAllocCount * 7 / 3; |
| 377 DataObjectPool pool(kPreallocCount, 0); |
| 378 AutoPoolReleaser r(pool); |
| 379 |
| 380 size_t preallocCount = allocateObjects(pool, r); |
| 381 REPORTER_ASSERT(reporter, preallocCount == kPreallocCount); |
| 382 } |
| 383 |
| 384 // Pool allocates space for minAllocCount objects when it adds a new block. |
| 385 { |
| 386 constexpr size_t kMinAllocCount = kSmallestMinAllocCount * 11 / 3; |
| 387 DataObjectPool pool(0, kMinAllocCount); |
| 388 AutoPoolReleaser r(pool); |
| 389 |
| 390 // Fill prealloc space |
| 391 allocateObjects(pool, r); |
| 392 |
| 393 size_t firstBlockCount = 1 + allocateObjects(pool, r); |
| 394 REPORTER_ASSERT(reporter, firstBlockCount == kMinAllocCount); |
| 395 |
| 396 size_t secondBlockCount = 1 + allocateObjects(pool, r); |
| 397 REPORTER_ASSERT(reporter, secondBlockCount == kMinAllocCount); |
| 398 } |
| 399 } |
| 400 |
230 #endif | 401 #endif |
OLD | NEW |