1 // 2 // Copyright 2019 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // mtl_buffer_pool.h: 7 // Defines class interface for BufferPool, managing a pool of mtl::Buffer 8 // 9 10 #ifndef LIBANGLE_RENDERER_METAL_MTL_BUFFER_POOL_H_ 11 #define LIBANGLE_RENDERER_METAL_MTL_BUFFER_POOL_H_ 12 13 #include "libANGLE/renderer/metal/mtl_resources.h" 14 15 namespace rx 16 { 17 18 class ContextMtl; 19 20 namespace mtl 21 { 22 23 // A buffer pool is conceptually an infinitely long buffer. Each time you write to the buffer, 24 // you will always write to a previously unused portion. After a series of writes, you must flush 25 // the buffer data to the device. Buffer lifetime currently assumes that each new allocation will 26 // last as long or longer than each prior allocation. 27 // 28 // Buffer pool is used to implement a variety of data streaming operations in Metal, such 29 // as for immediate vertex array and element array data, and other dynamic data. 30 // 31 // Internally buffer pool keeps a collection of mtl::Buffer. When we write past the end of a 32 // currently active mtl::Buffer we keep it until it is no longer in use. We then mark it available 33 // for future allocations in a free list. 34 class BufferPool 35 { 36 public: 37 // alwaysAllocNewBuffer=true will always allocate new buffer or reuse free buffer on allocate(), 38 // regardless of whether current buffer still has unused portion or not. 39 BufferPool(bool alwaysAllocNewBuffer = false); 40 ~BufferPool(); 41 42 // Init is called after the buffer creation so that the alignment can be specified later. 43 void initialize(ContextMtl *contextMtl, 44 size_t initialSize, 45 size_t alignment, 46 size_t maxBuffers = 0); 47 48 // This call will allocate a new region at the end of the buffer. It internally may trigger 49 // a new buffer to be created (which is returned in the optional parameter 50 // `newBufferAllocatedOut`). The new region will be in the returned buffer at given offset. If 51 // a memory pointer is given, the buffer will be automatically map()ed. 52 angle::Result allocate(ContextMtl *contextMtl, 53 size_t sizeInBytes, 54 uint8_t **ptrOut = nullptr, 55 BufferRef *bufferOut = nullptr, 56 size_t *offsetOut = nullptr, 57 bool *newBufferAllocatedOut = nullptr); 58 59 // After a sequence of writes, call commit to ensure the data is visible to the device. 60 angle::Result commit(ContextMtl *contextMtl); 61 62 // This releases all the buffers that have been allocated since this was last called. 63 void releaseInFlightBuffers(ContextMtl *contextMtl); 64 65 // This frees resources immediately. 66 void destroy(ContextMtl *contextMtl); 67 getCurrentBuffer()68 const BufferRef &getCurrentBuffer() { return mBuffer; } 69 getAlignment()70 size_t getAlignment() { return mAlignment; } 71 void updateAlignment(ContextMtl *contextMtl, size_t alignment); 72 73 // Set whether allocate() will always allocate new buffer or attempting to append to previous 74 // buffer or not. Default is false. setAlwaysAllocateNewBuffer(bool e)75 void setAlwaysAllocateNewBuffer(bool e) { mAlwaysAllocateNewBuffer = e; } 76 77 private: 78 void reset(); 79 angle::Result allocateNewBuffer(ContextMtl *contextMtl); 80 void destroyBufferList(ContextMtl *contextMtl, std::vector<BufferRef> *buffers); 81 82 size_t mInitialSize; 83 BufferRef mBuffer; 84 uint32_t mNextAllocationOffset; 85 size_t mSize; 86 size_t mAlignment; 87 88 std::vector<BufferRef> mInFlightBuffers; 89 std::vector<BufferRef> mBufferFreeList; 90 91 size_t mBuffersAllocated; 92 size_t mMaxBuffers; 93 bool mAlwaysAllocateNewBuffer; 94 }; 95 96 } // namespace mtl 97 } // namespace rx 98 99 #endif /* LIBANGLE_RENDERER_METAL_MTL_BUFFER_POOL_H_ */ 100