/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_gfx_layers_mlgpu_BufferCache_h #define mozilla_gfx_layers_mlgpu_BufferCache_h #include "mozilla/EnumeratedArray.h" #include "mozilla/RefPtr.h" #include #include namespace mozilla { namespace layers { class MLGBuffer; class MLGDevice; // Cache MLGBuffers based on how long ago they were last used. class BufferCache final { public: explicit BufferCache(MLGDevice* aDevice); ~BufferCache(); // Get a buffer that has at least |aBytes|, or create a new one // if none can be re-used. RefPtr GetOrCreateBuffer(size_t aBytes); // Age out old buffers after a frame has been completed. void EndFrame(); private: // Not RefPtr since this would create a cycle. MLGDevice* mDevice; // The first size class is Log2(N), where 16 is the minimum size of a // constant buffer (currently 16 bytes). size_t mFirstSizeClass; // Each size class is a power of 2. Each pool of buffers is represented as a // deque, with the least-recently-used (i.e., oldest) buffers at the front, // and most-recently-used (i.e., newest) buffers at the back. To re-use a // buffer it is popped off the front and re-added to the back. // // This is not always efficient use of storage: if a single frame allocates // 300 buffers of the same size, we may keep recycling through all those // buffers for a long time, as long as at least one gets used per frame. // But since buffers use tiny amounts of memory, and they are only mapped // while drawing, it shouldn't be a big deal. struct CacheEntry { CacheEntry() : mLastUsedFrame(0) {} // XXX The copy constructor can be deleted once RefPtr's move constructor is // declared noexcept, see Bug 1612680. CacheEntry(const CacheEntry& aEntry) = default; CacheEntry(CacheEntry&& aEntry) = default; CacheEntry(size_t aLastUsedFrame, MLGBuffer* aBuffer) : mLastUsedFrame(aLastUsedFrame), mBuffer(aBuffer) {} uint64_t mLastUsedFrame; RefPtr mBuffer; }; typedef std::deque CachePool; // We track how many frames have occurred to determine the age of cache // entries. uint64_t mFrameNumber; // To avoid doing too much work in one frame, we only shrink one size class // per frame. uint64_t mNextSizeClassToShrink; // There is one pool of buffers for each power of 2 allocation size. The // maximum buffer size is at most 64KB on Direct3D 11. std::vector mCaches; }; } // namespace layers } // namespace mozilla #endif // mozilla_gfx_layers_mlgpu_BufferCache_h