LCOV - code coverage report
Current view: top level - gfx/layers/mlgpu - BufferCache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 39 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          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             : #include "BufferCache.h"
       7             : #include "MLGDevice.h"
       8             : #include "ShaderDefinitionsMLGPU.h"
       9             : #include "mozilla/MathAlgorithms.h"
      10             : 
      11             : namespace mozilla {
      12             : namespace layers {
      13             : 
      14             : using namespace mlg;
      15             : 
      16           0 : BufferCache::BufferCache(MLGDevice* aDevice)
      17             :  : mDevice(aDevice),
      18           0 :    mFirstSizeClass(CeilingLog2(kConstantBufferElementSize)),
      19             :    mFrameNumber(0),
      20           0 :    mNextSizeClassToShrink(0)
      21             : {
      22             :   // Create a cache of buffers for each size class, where each size class is a
      23             :   // power of 2 between the minimum and maximum size of a constant buffer.
      24           0 :   size_t maxBindSize = mDevice->GetMaxConstantBufferBindSize();
      25           0 :   MOZ_ASSERT(IsPowerOfTwo(maxBindSize));
      26             : 
      27           0 :   size_t lastSizeClass = CeilingLog2(maxBindSize);
      28           0 :   MOZ_ASSERT(lastSizeClass >= mFirstSizeClass);
      29             : 
      30           0 :   mCaches.resize(lastSizeClass - mFirstSizeClass + 1);
      31           0 : }
      32             : 
      33           0 : BufferCache::~BufferCache()
      34             : {
      35           0 : }
      36             : 
      37             : RefPtr<MLGBuffer>
      38           0 : BufferCache::GetOrCreateBuffer(size_t aBytes)
      39             : {
      40           0 :   size_t sizeClass = CeilingLog2(aBytes);
      41           0 :   size_t sizeClassIndex = sizeClass - mFirstSizeClass;
      42           0 :   if (sizeClassIndex >= mCaches.size()) {
      43           0 :     return mDevice->CreateBuffer(MLGBufferType::Constant, aBytes, MLGUsage::Dynamic, nullptr);
      44             :   }
      45             : 
      46           0 :   CachePool& pool = mCaches[sizeClassIndex];
      47             : 
      48             :   // See if we've cached a buffer that wasn't used in the past 2 frames. A buffer
      49             :   // used this frame could have already been mapped and written to, and a buffer
      50             :   // used the previous frame might still be in-use by the GPU. While the latter
      51             :   // case is okay, it causes aliasing in the driver. Since content is double
      52             :   // buffered we do not let the compositor get more than 1 frames ahead, and a
      53             :   // count of 2 frames should ensure the buffer is unused.
      54           0 :   if (!pool.empty() && mFrameNumber >= pool.front().mLastUsedFrame + 2) {
      55           0 :     RefPtr<MLGBuffer> buffer = pool.front().mBuffer;
      56           0 :     pool.pop_front();
      57           0 :     pool.push_back(CacheEntry(mFrameNumber, buffer));
      58           0 :     MOZ_RELEASE_ASSERT(buffer->GetSize() >= aBytes);
      59           0 :     return buffer;
      60             :   }
      61             : 
      62             :   // Allocate a new buffer and cache it.
      63           0 :   size_t bytes = (size_t(1) << sizeClass);
      64           0 :   MOZ_ASSERT(bytes >= aBytes);
      65             : 
      66             :   RefPtr<MLGBuffer> buffer =
      67           0 :     mDevice->CreateBuffer(MLGBufferType::Constant, bytes, MLGUsage::Dynamic, nullptr);
      68           0 :   if (!buffer) {
      69           0 :     return nullptr;
      70             :   }
      71             : 
      72           0 :   pool.push_back(CacheEntry(mFrameNumber, buffer));
      73           0 :   return buffer;
      74             : }
      75             : 
      76             : void
      77           0 : BufferCache::EndFrame()
      78             : {
      79             :   // Consider a buffer dead after ~5 seconds assuming 60 fps.
      80             :   static size_t kMaxUnusedFrameCount = 60 * 5;
      81             : 
      82             :   // At the end of each frame we pick one size class and see if it has any
      83             :   // buffers that haven't been used for many frames. If so we clear them.
      84             :   // The next frame we'll search the next size class. (This is just to spread
      85             :   // work over more than one frame.)
      86           0 :   CachePool& pool = mCaches[mNextSizeClassToShrink];
      87           0 :   while (!pool.empty()) {
      88             :     // Since the deque is sorted oldest-to-newest, front-to-back, we can stop
      89             :     // searching as soon as a buffer is active.
      90           0 :     if (mFrameNumber - pool.front().mLastUsedFrame < kMaxUnusedFrameCount) {
      91           0 :       break;
      92             :     }
      93           0 :     pool.pop_front();
      94             :   }
      95           0 :   mNextSizeClassToShrink = (mNextSizeClassToShrink + 1) % mCaches.size();
      96             : 
      97           0 :   mFrameNumber++;
      98           0 : }
      99             : 
     100             : } // namespace layers
     101             : } // namespace mozilla

Generated by: LCOV version 1.13