LCOV - code coverage report
Current view: top level - gfx/layers/mlgpu - SharedBufferMLGPU.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 127 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 44 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             : #ifndef mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h
       7             : #define mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h
       8             : 
       9             : #include "ShaderDefinitionsMLGPU.h"
      10             : #include "MLGDeviceTypes.h"
      11             : #include "StagingBuffer.h"
      12             : #include "mozilla/gfx/Logging.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace layers {
      16             : 
      17             : class MLGBuffer;
      18             : 
      19             : class SharedBufferMLGPU
      20             : {
      21             : public:
      22             :   virtual ~SharedBufferMLGPU();
      23             : 
      24             :   bool Init();
      25             : 
      26             :   // Call before starting a new frame.
      27             :   void Reset();
      28             : 
      29             :   // Call to finish any pending uploads.
      30             :   void PrepareForUsage();
      31             : 
      32             : protected:
      33             :   SharedBufferMLGPU(MLGDevice* aDevice, MLGBufferType aType, size_t aDefaultSize);
      34             : 
      35             :   bool EnsureMappedBuffer(size_t aBytes);
      36             :   bool GrowBuffer(size_t aBytes);
      37             :   void ForgetBuffer();
      38             :   bool Map();
      39             :   void Unmap();
      40             : 
      41           0 :   uint8_t* GetBufferPointer(size_t aBytes, ptrdiff_t* aOutOffset, RefPtr<MLGBuffer>* aOutBuffer) {
      42           0 :     if (!EnsureMappedBuffer(aBytes)) {
      43           0 :       return nullptr;
      44             :     }
      45             : 
      46           0 :     ptrdiff_t newPos = mCurrentPosition + aBytes;
      47           0 :     MOZ_ASSERT(size_t(newPos) <= mMaxSize);
      48             : 
      49           0 :     *aOutOffset = mCurrentPosition;
      50           0 :     *aOutBuffer = mBuffer;
      51             : 
      52           0 :     uint8_t* ptr = reinterpret_cast<uint8_t*>(mMap.mData) + mCurrentPosition;
      53           0 :     mCurrentPosition = newPos;
      54           0 :     return ptr;
      55             :   }
      56             : 
      57             : protected:
      58             :   // Note: RefPtr here would cause a cycle. Only MLGDevice should own
      59             :   // SharedBufferMLGPU objects for now.
      60             :   MLGDevice* mDevice;
      61             :   MLGBufferType mType;
      62             :   size_t mDefaultSize;
      63             :   bool mCanUseOffsetAllocation;
      64             : 
      65             :   // When |mBuffer| is non-null, mMaxSize is the buffer size. If mapped, the
      66             :   // position is between 0 and mMaxSize, otherwise it is always 0.
      67             :   RefPtr<MLGBuffer> mBuffer;
      68             :   ptrdiff_t mCurrentPosition;
      69             :   size_t mMaxSize;
      70             : 
      71             :   MLGMappedResource mMap;
      72             :   bool mMapped;
      73             : 
      74             :   // These are used to track how many frames come in under the default
      75             :   // buffer size in a row.
      76             :   size_t mBytesUsedThisFrame;
      77             :   size_t mNumSmallFrames;
      78             : };
      79             : 
      80           0 : class VertexBufferSection final
      81             : {
      82             :   friend class SharedVertexBuffer;
      83             : public:
      84           0 :   VertexBufferSection()
      85           0 :    : mOffset(-1),
      86             :      mNumVertices(0),
      87           0 :      mStride(0)
      88           0 :   {}
      89             : 
      90           0 :   uint32_t Stride() const {
      91           0 :     return mStride;
      92             :   }
      93           0 :   MLGBuffer* GetBuffer() const {
      94           0 :     return mBuffer;
      95             :   }
      96           0 :   ptrdiff_t Offset() const {
      97           0 :     MOZ_ASSERT(IsValid());
      98           0 :     return mOffset;
      99             :   }
     100           0 :   size_t NumVertices() const {
     101           0 :     return mNumVertices;
     102             :   }
     103           0 :   bool IsValid() const {
     104           0 :     return !!mBuffer;
     105             :   }
     106             : 
     107             : protected:
     108           0 :   void Init(MLGBuffer* aBuffer, ptrdiff_t aOffset, size_t aNumVertices, size_t aStride) {
     109           0 :     mBuffer = aBuffer;
     110           0 :     mOffset = aOffset;
     111           0 :     mNumVertices = aNumVertices;
     112           0 :     mStride = aStride;
     113           0 :   }
     114             : 
     115             : protected:
     116             :   RefPtr<MLGBuffer> mBuffer;
     117             :   ptrdiff_t mOffset;
     118             :   size_t mNumVertices;
     119             :   size_t mStride;
     120             : };
     121             : 
     122           0 : class ConstantBufferSection final
     123             : {
     124             :   friend class SharedConstantBuffer;
     125             : 
     126             : public:
     127           0 :   ConstantBufferSection()
     128           0 :    : mOffset(-1)
     129           0 :   {}
     130             : 
     131           0 :   uint32_t NumConstants() const {
     132           0 :     return NumConstantsForBytes(mNumBytes);
     133             :   }
     134             :   size_t NumItems() const {
     135             :     return mNumItems;
     136             :   }
     137           0 :   uint32_t Offset() const {
     138           0 :     MOZ_ASSERT(IsValid());
     139           0 :     return mOffset / 16;
     140             :   }
     141           0 :   MLGBuffer* GetBuffer() const {
     142           0 :     return mBuffer;
     143             :   }
     144           0 :   bool IsValid() const {
     145           0 :     return !!mBuffer;
     146             :   }
     147           0 :   bool HasOffset() const {
     148           0 :     return mOffset != -1;
     149             :   }
     150             : 
     151             : protected:
     152           0 :   static constexpr size_t NumConstantsForBytes(size_t aBytes) {
     153           0 :     return (aBytes + ((256 - (aBytes % 256)) % 256)) / 16;
     154             :   }
     155             : 
     156           0 :   void Init(MLGBuffer* aBuffer, ptrdiff_t aOffset, size_t aBytes, size_t aNumItems) {
     157           0 :     mBuffer = aBuffer;
     158           0 :     mOffset = aOffset;
     159           0 :     mNumBytes = aBytes;
     160           0 :     mNumItems = aNumItems;
     161           0 :   }
     162             : 
     163             : protected:
     164             :   RefPtr<MLGBuffer> mBuffer;
     165             :   ptrdiff_t mOffset;
     166             :   size_t mNumBytes;
     167             :   size_t mNumItems;
     168             : };
     169             : 
     170             : // Vertex buffers don't need special alignment.
     171             : typedef StagingBuffer<0> VertexStagingBuffer;
     172             : 
     173           0 : class SharedVertexBuffer final : public SharedBufferMLGPU
     174             : {
     175             : public:
     176             :   SharedVertexBuffer(MLGDevice* aDevice, size_t aDefaultSize);
     177             : 
     178             :   // Allocate a buffer that can be uploaded immediately.
     179           0 :   bool Allocate(VertexBufferSection* aHolder, const VertexStagingBuffer& aStaging) {
     180           0 :     return Allocate(aHolder,
     181             :                     aStaging.NumItems(),
     182             :                     aStaging.SizeOfItem(),
     183           0 :                     aStaging.GetBufferStart());
     184             :   }
     185             : 
     186             :   // Allocate a buffer that can be uploaded immediately. This is the
     187             :   // direct access version, for cases where a StagingBuffer is not
     188             :   // needed.
     189           0 :   bool Allocate(VertexBufferSection* aHolder,
     190             :                 size_t aNumItems,
     191             :                 size_t aSizeOfItem,
     192             :                 const void* aData)
     193             :   {
     194           0 :     RefPtr<MLGBuffer> buffer;
     195             :     ptrdiff_t offset;
     196           0 :     size_t bytes = aSizeOfItem * aNumItems;
     197           0 :     uint8_t* ptr = GetBufferPointer(bytes, &offset, &buffer);
     198           0 :     if (!ptr) {
     199           0 :       return false;
     200             :     }
     201             : 
     202           0 :     memcpy(ptr, aData, bytes);
     203           0 :     aHolder->Init(buffer, offset, aNumItems, aSizeOfItem);
     204           0 :     return true;
     205             :   }
     206             : 
     207             :   template <typename T>
     208             :   bool Allocate(VertexBufferSection* aHolder, const T& aItem) {
     209             :     return Allocate(aHolder, 1, sizeof(T), &aItem);
     210             :   }
     211             : };
     212             : 
     213             : // To support older Direct3D versions, we need to support one-off MLGBuffers,
     214             : // where data is uploaded immediately rather than at the end of all batch
     215             : // preparation. We achieve this through a small helper class.
     216             : //
     217             : // Note: the unmap is not inline sincce we don't include MLGDevice.h.
     218             : class MOZ_STACK_CLASS AutoBufferUploadBase
     219             : {
     220             : public:
     221           0 :   AutoBufferUploadBase() : mPtr(nullptr) {}
     222           0 :   ~AutoBufferUploadBase() {
     223           0 :     if (mBuffer) {
     224           0 :       UnmapBuffer();
     225             :     }
     226           0 :   }
     227             : 
     228           0 :   void Init(void* aPtr) {
     229           0 :     MOZ_ASSERT(!mPtr && aPtr);
     230           0 :     mPtr = aPtr;
     231           0 :   }
     232           0 :   void Init(void* aPtr, MLGDevice* aDevice, MLGBuffer* aBuffer) {
     233           0 :     MOZ_ASSERT(!mPtr && aPtr);
     234           0 :     mPtr = aPtr;
     235           0 :     mDevice = aDevice;
     236           0 :     mBuffer = aBuffer;
     237           0 :   }
     238           0 :   void* get() {
     239           0 :     return const_cast<void*>(mPtr);
     240             :   }
     241             : 
     242             : private:
     243             :   void UnmapBuffer();
     244             : 
     245             : protected:
     246             :   RefPtr<MLGDevice> mDevice;
     247             :   RefPtr<MLGBuffer> mBuffer;
     248             :   void* mPtr;
     249             : };
     250             : 
     251             : // This is a typed helper for AutoBufferUploadBase.
     252             : template <typename T>
     253           0 : class AutoBufferUpload : public AutoBufferUploadBase
     254             : {
     255             : public:
     256           0 :   AutoBufferUpload()
     257           0 :   {}
     258             : 
     259           0 :   T* operator ->() const {
     260           0 :     return reinterpret_cast<T*>(mPtr);
     261             :   }
     262             : };
     263             : 
     264           0 : class SharedConstantBuffer final : public SharedBufferMLGPU
     265             : {
     266             : public:
     267             :   SharedConstantBuffer(MLGDevice* aDevice, size_t aDefaultSize);
     268             : 
     269             :   // Allocate a buffer that can be immediately uploaded.
     270             :   bool Allocate(ConstantBufferSection* aHolder, const ConstantStagingBuffer& aStaging) {
     271             :     MOZ_ASSERT(aStaging.NumItems() * aStaging.SizeOfItem() == aStaging.NumBytes());
     272             :     return Allocate(aHolder, aStaging.NumItems(), aStaging.SizeOfItem(), aStaging.GetBufferStart());
     273             :   }
     274             : 
     275             :   // Allocate a buffer of one item that can be immediately uploaded.
     276             :   template <typename T>
     277           0 :   bool Allocate(ConstantBufferSection* aHolder, const T& aItem) {
     278           0 :     return Allocate(aHolder, 1, sizeof(aItem), &aItem);
     279             :   }
     280             : 
     281             :   // Allocate a buffer of N items that can be immediately uploaded.
     282             :   template <typename T>
     283           0 :   bool Allocate(ConstantBufferSection* aHolder, const T* aItems, size_t aNumItems) {
     284           0 :     return Allocate(aHolder, aNumItems, sizeof(T), aItems);
     285             :   }
     286             : 
     287             :   // Allocate a buffer that is uploaded after the caller has finished writing
     288             :   // to it. This should method should generally not be used unless copying T
     289             :   // is expensive, since the default immediate-upload version has an implicit
     290             :   // extra copy to the GPU. This version exposes the mapped memory directly.
     291             :   template <typename T>
     292           0 :   bool Allocate(ConstantBufferSection* aHolder, AutoBufferUpload<T>* aPtr) {
     293             :     MOZ_ASSERT(sizeof(T) % 16 == 0, "Items must be padded to 16 bytes");
     294             : 
     295           0 :     return Allocate(aHolder, aPtr, 1, sizeof(T));
     296             :   }
     297             : 
     298             : private:
     299           0 :   bool Allocate(ConstantBufferSection* aHolder,
     300             :                 size_t aNumItems,
     301             :                 size_t aSizeOfItem,
     302             :                 const void* aData)
     303             :   {
     304           0 :     AutoBufferUploadBase ptr;
     305           0 :     if (!Allocate(aHolder, &ptr, aNumItems, aSizeOfItem)) {
     306           0 :       return false;
     307             :     }
     308           0 :     memcpy(ptr.get(), aData, aNumItems * aSizeOfItem);
     309           0 :     return true;
     310             :   }
     311             : 
     312           0 :   bool Allocate(ConstantBufferSection* aHolder,
     313             :                 AutoBufferUploadBase* aPtr,
     314             :                 size_t aNumItems,
     315             :                 size_t aSizeOfItem)
     316             :   {
     317           0 :     MOZ_ASSERT(aSizeOfItem % 16 == 0, "Items must be padded to 16 bytes");
     318             : 
     319           0 :     size_t bytes = aNumItems * aSizeOfItem;
     320           0 :     if (bytes > mMaxConstantBufferBindSize) {
     321           0 :       gfxWarning() << "Attempted to allocate too many bytes into a constant buffer";
     322           0 :       return false;
     323             :     }
     324             : 
     325             : 
     326           0 :     RefPtr<MLGBuffer> buffer;
     327             :     ptrdiff_t offset;
     328           0 :     if (!GetBufferPointer(aPtr, bytes, &offset, &buffer)) {
     329           0 :       return false;
     330             :     }
     331             : 
     332           0 :     aHolder->Init(buffer, offset, bytes, aNumItems);
     333           0 :     return true;
     334             :   }
     335             : 
     336           0 :   bool GetBufferPointer(AutoBufferUploadBase* aPtr,
     337             :                         size_t aBytes,
     338             :                         ptrdiff_t* aOutOffset,
     339             :                         RefPtr<MLGBuffer>* aOutBuffer)
     340             :   {
     341           0 :     if (!mCanUseOffsetAllocation) {
     342           0 :       uint8_t* ptr = AllocateNewBuffer(aBytes, aOutOffset, aOutBuffer);
     343           0 :       if (!ptr) {
     344           0 :         return false;
     345             :       }
     346           0 :       aPtr->Init(ptr, mDevice, *aOutBuffer);
     347           0 :       return true;
     348             :     }
     349             : 
     350             :     // Align up the allocation to 256 bytes, since D3D11 requires that
     351             :     // constant buffers start at multiples of 16 elements.
     352           0 :     size_t alignedBytes = AlignUp<256>::calc(aBytes);
     353             : 
     354           0 :     uint8_t* ptr = SharedBufferMLGPU::GetBufferPointer(alignedBytes, aOutOffset, aOutBuffer);
     355           0 :     if (!ptr) {
     356           0 :       return false;
     357             :     }
     358             : 
     359           0 :     aPtr->Init(ptr);
     360           0 :     return true;
     361             :   }
     362             : 
     363             :   uint8_t* AllocateNewBuffer(size_t aBytes, ptrdiff_t* aOutOffset, RefPtr<MLGBuffer>* aOutBuffer);
     364             : 
     365             : private:
     366             :   size_t mMaxConstantBufferBindSize;
     367             : };
     368             : 
     369             : } // namespace layers
     370             : } // namespace mozilla
     371             : 
     372             : #endif // mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h

Generated by: LCOV version 1.13