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