/src/mozilla-central/gfx/layers/mlgpu/BufferCache.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef mozilla_gfx_layers_mlgpu_BufferCache_h |
8 | | #define mozilla_gfx_layers_mlgpu_BufferCache_h |
9 | | |
10 | | #include "mozilla/EnumeratedArray.h" |
11 | | #include "mozilla/RefPtr.h" |
12 | | #include <deque> |
13 | | #include <vector> |
14 | | |
15 | | namespace mozilla { |
16 | | namespace layers { |
17 | | |
18 | | class MLGBuffer; |
19 | | class MLGDevice; |
20 | | |
21 | | // Cache MLGBuffers based on how long ago they were last used. |
22 | | class BufferCache |
23 | | { |
24 | | public: |
25 | | explicit BufferCache(MLGDevice* aDevice); |
26 | | ~BufferCache(); |
27 | | |
28 | | // Get a buffer that has at least |aBytes|, or create a new one |
29 | | // if none can be re-used. |
30 | | RefPtr<MLGBuffer> GetOrCreateBuffer(size_t aBytes); |
31 | | |
32 | | // Age out old buffers after a frame has been completed. |
33 | | void EndFrame(); |
34 | | |
35 | | private: |
36 | | // Not RefPtr since this would create a cycle. |
37 | | MLGDevice* mDevice; |
38 | | |
39 | | // The first size class is Log2(N), where 16 is the minimum size of a |
40 | | // constant buffer (currently 16 bytes). |
41 | | size_t mFirstSizeClass; |
42 | | |
43 | | // Each size class is a power of 2. Each pool of buffers is represented as a |
44 | | // deque, with the least-recently-used (i.e., oldest) buffers at the front, |
45 | | // and most-recently-used (i.e., newest) buffers at the back. To re-use a |
46 | | // buffer it is popped off the front and re-added to the back. |
47 | | // |
48 | | // This is not always efficient use of storage: if a single frame allocates |
49 | | // 300 buffers of the same size, we may keep recycling through all those |
50 | | // buffers for a long time, as long as at least one gets used per frame. |
51 | | // But since buffers use tiny amounts of memory, and they are only mapped |
52 | | // while drawing, it shouldn't be a big deal. |
53 | | struct CacheEntry { |
54 | | CacheEntry() : mLastUsedFrame(0) |
55 | 0 | {} |
56 | | CacheEntry(const CacheEntry& aEntry) |
57 | | : mLastUsedFrame(aEntry.mLastUsedFrame), |
58 | | mBuffer(aEntry.mBuffer) |
59 | 0 | {} |
60 | | CacheEntry(CacheEntry&& aEntry) |
61 | | : mLastUsedFrame(aEntry.mLastUsedFrame), |
62 | | mBuffer(std::move(aEntry.mBuffer)) |
63 | 0 | {} |
64 | | CacheEntry(size_t aLastUsedFrame, MLGBuffer* aBuffer) |
65 | | : mLastUsedFrame(aLastUsedFrame), |
66 | | mBuffer(aBuffer) |
67 | 0 | {} |
68 | | |
69 | | uint64_t mLastUsedFrame; |
70 | | RefPtr<MLGBuffer> mBuffer; |
71 | | }; |
72 | | typedef std::deque<CacheEntry> CachePool; |
73 | | |
74 | | // We track how many frames have occurred to determine the age of cache entries. |
75 | | uint64_t mFrameNumber; |
76 | | |
77 | | // To avoid doing too much work in one frame, we only shrink one size class |
78 | | // per frame. |
79 | | uint64_t mNextSizeClassToShrink; |
80 | | |
81 | | // There is one pool of buffers for each power of 2 allocation size. The |
82 | | // maximum buffer size is at most 64KB on Direct3D 11. |
83 | | std::vector<CachePool> mCaches; |
84 | | }; |
85 | | |
86 | | } // namespace layers |
87 | | } // namespace mozilla |
88 | | |
89 | | #endif // mozilla_gfx_layers_mlgpu_BufferCache_h |