DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (ecaceb8b8295)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
/* -*- 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 <deque>
#include <vector>

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<MLGBuffer> 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<MLGBuffer> mBuffer;
  };
  typedef std::deque<CacheEntry> 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<CachePool> mCaches;
};

}  // namespace layers
}  // namespace mozilla

#endif  // mozilla_gfx_layers_mlgpu_BufferCache_h