1*8975f5c5SAndroid Build Coastguard Worker // 2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2022 The ANGLE Project Authors. All rights reserved. 3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker // 6*8975f5c5SAndroid Build Coastguard Worker // RingBufferAllocator.h: 7*8975f5c5SAndroid Build Coastguard Worker // Classes used to implement ring buffer allocators. 8*8975f5c5SAndroid Build Coastguard Worker // 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Worker #ifndef COMMON_RING_BUFFER_ALLOCATOR_H_ 11*8975f5c5SAndroid Build Coastguard Worker #define COMMON_RING_BUFFER_ALLOCATOR_H_ 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Worker #include "angleutils.h" 14*8975f5c5SAndroid Build Coastguard Worker #include "common/SimpleMutex.h" 15*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h" 16*8975f5c5SAndroid Build Coastguard Worker 17*8975f5c5SAndroid Build Coastguard Worker #include <atomic> 18*8975f5c5SAndroid Build Coastguard Worker 19*8975f5c5SAndroid Build Coastguard Worker namespace angle 20*8975f5c5SAndroid Build Coastguard Worker { 21*8975f5c5SAndroid Build Coastguard Worker 22*8975f5c5SAndroid Build Coastguard Worker static constexpr uint32_t kMinRingBufferAllocationCapacity = 1024; 23*8975f5c5SAndroid Build Coastguard Worker static constexpr uint32_t kDefaultDecaySpeedFactor = 10; 24*8975f5c5SAndroid Build Coastguard Worker 25*8975f5c5SAndroid Build Coastguard Worker // Only called from RingBufferAllocator::allocate(). Other function may also change the fragment. 26*8975f5c5SAndroid Build Coastguard Worker class RingBufferAllocateListener 27*8975f5c5SAndroid Build Coastguard Worker { 28*8975f5c5SAndroid Build Coastguard Worker public: 29*8975f5c5SAndroid Build Coastguard Worker virtual void onRingBufferNewFragment() = 0; 30*8975f5c5SAndroid Build Coastguard Worker virtual void onRingBufferFragmentEnd() = 0; 31*8975f5c5SAndroid Build Coastguard Worker 32*8975f5c5SAndroid Build Coastguard Worker protected: 33*8975f5c5SAndroid Build Coastguard Worker ~RingBufferAllocateListener() = default; 34*8975f5c5SAndroid Build Coastguard Worker }; 35*8975f5c5SAndroid Build Coastguard Worker 36*8975f5c5SAndroid Build Coastguard Worker class RingBufferAllocatorCheckPoint final 37*8975f5c5SAndroid Build Coastguard Worker { 38*8975f5c5SAndroid Build Coastguard Worker public: reset()39*8975f5c5SAndroid Build Coastguard Worker void reset() { *this = {}; } valid()40*8975f5c5SAndroid Build Coastguard Worker bool valid() const { return (mReleasePtr != nullptr); } 41*8975f5c5SAndroid Build Coastguard Worker 42*8975f5c5SAndroid Build Coastguard Worker private: 43*8975f5c5SAndroid Build Coastguard Worker friend class RingBufferAllocator; 44*8975f5c5SAndroid Build Coastguard Worker uint64_t mBufferId = 0; 45*8975f5c5SAndroid Build Coastguard Worker uint8_t *mReleasePtr = nullptr; 46*8975f5c5SAndroid Build Coastguard Worker }; 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker class RingBufferAllocatorBuffer final 49*8975f5c5SAndroid Build Coastguard Worker { 50*8975f5c5SAndroid Build Coastguard Worker public: 51*8975f5c5SAndroid Build Coastguard Worker static constexpr uint32_t kBaseOffset = alignof(std::max_align_t); 52*8975f5c5SAndroid Build Coastguard Worker resize(uint32_t size)53*8975f5c5SAndroid Build Coastguard Worker void resize(uint32_t size) { mStorage.resize(size + kBaseOffset); } data()54*8975f5c5SAndroid Build Coastguard Worker uint8_t *data() { return mStorage.data() + kBaseOffset; } 55*8975f5c5SAndroid Build Coastguard Worker decClamped(uint8_t * ptr,uint32_t offset)56*8975f5c5SAndroid Build Coastguard Worker uint8_t *decClamped(uint8_t *ptr, uint32_t offset) const 57*8975f5c5SAndroid Build Coastguard Worker { 58*8975f5c5SAndroid Build Coastguard Worker ASSERT(ptr >= mStorage.data() + kBaseOffset && ptr <= mStorage.data() + mStorage.size()); 59*8975f5c5SAndroid Build Coastguard Worker return ptr - std::min(offset, static_cast<uint32_t>(ptr - mStorage.data())); 60*8975f5c5SAndroid Build Coastguard Worker } 61*8975f5c5SAndroid Build Coastguard Worker getId()62*8975f5c5SAndroid Build Coastguard Worker uint64_t getId() const { return mId; } resetId()63*8975f5c5SAndroid Build Coastguard Worker void resetId() { mId = 0; } incrementId()64*8975f5c5SAndroid Build Coastguard Worker void incrementId() { ++mId; } 65*8975f5c5SAndroid Build Coastguard Worker isEmpty()66*8975f5c5SAndroid Build Coastguard Worker bool isEmpty() const { return mStorage.empty(); } 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Worker private: 69*8975f5c5SAndroid Build Coastguard Worker uint64_t mId = 0; 70*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> mStorage; 71*8975f5c5SAndroid Build Coastguard Worker }; 72*8975f5c5SAndroid Build Coastguard Worker 73*8975f5c5SAndroid Build Coastguard Worker class RingBufferAllocator final : angle::NonCopyable 74*8975f5c5SAndroid Build Coastguard Worker { 75*8975f5c5SAndroid Build Coastguard Worker public: 76*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocator() = default; 77*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocator(RingBufferAllocator &&other); 78*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocator &operator=(RingBufferAllocator &&other); 79*8975f5c5SAndroid Build Coastguard Worker 80*8975f5c5SAndroid Build Coastguard Worker void reset(); valid()81*8975f5c5SAndroid Build Coastguard Worker bool valid() const { return (getPointer() != nullptr); } 82*8975f5c5SAndroid Build Coastguard Worker 83*8975f5c5SAndroid Build Coastguard Worker void setListener(RingBufferAllocateListener *listener); 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Worker void setDecaySpeedFactor(uint32_t decaySpeedFactor); 86*8975f5c5SAndroid Build Coastguard Worker 87*8975f5c5SAndroid Build Coastguard Worker void setFragmentReserve(uint32_t reserve); 88*8975f5c5SAndroid Build Coastguard Worker allocate(uint32_t size)89*8975f5c5SAndroid Build Coastguard Worker uint8_t *allocate(uint32_t size) 90*8975f5c5SAndroid Build Coastguard Worker { 91*8975f5c5SAndroid Build Coastguard Worker ASSERT(valid()); 92*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_LIKELY(mFragmentEndR - mDataEnd >= static_cast<ptrdiff_t>(size))) 93*8975f5c5SAndroid Build Coastguard Worker { 94*8975f5c5SAndroid Build Coastguard Worker uint8_t *const result = mDataEnd; 95*8975f5c5SAndroid Build Coastguard Worker mDataEnd = result + size; 96*8975f5c5SAndroid Build Coastguard Worker return result; 97*8975f5c5SAndroid Build Coastguard Worker } 98*8975f5c5SAndroid Build Coastguard Worker return allocateInNewFragment(size); 99*8975f5c5SAndroid Build Coastguard Worker } 100*8975f5c5SAndroid Build Coastguard Worker getPointer()101*8975f5c5SAndroid Build Coastguard Worker uint8_t *getPointer() const { return mDataEnd; } getFragmentSize()102*8975f5c5SAndroid Build Coastguard Worker uint32_t getFragmentSize() const 103*8975f5c5SAndroid Build Coastguard Worker { 104*8975f5c5SAndroid Build Coastguard Worker ASSERT(mFragmentEnd >= mDataEnd); 105*8975f5c5SAndroid Build Coastguard Worker return static_cast<uint32_t>(mFragmentEnd - mDataEnd); 106*8975f5c5SAndroid Build Coastguard Worker } 107*8975f5c5SAndroid Build Coastguard Worker 108*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocatorCheckPoint getReleaseCheckPoint() const; 109*8975f5c5SAndroid Build Coastguard Worker void release(const RingBufferAllocatorCheckPoint &checkPoint); 110*8975f5c5SAndroid Build Coastguard Worker 111*8975f5c5SAndroid Build Coastguard Worker private: 112*8975f5c5SAndroid Build Coastguard Worker void release(uint8_t *releasePtr); 113*8975f5c5SAndroid Build Coastguard Worker uint32_t getNumAllocatedInBuffer() const; 114*8975f5c5SAndroid Build Coastguard Worker void resetPointers(); 115*8975f5c5SAndroid Build Coastguard Worker 116*8975f5c5SAndroid Build Coastguard Worker uint8_t *allocateInNewFragment(uint32_t size); 117*8975f5c5SAndroid Build Coastguard Worker void resize(uint32_t newCapacity); 118*8975f5c5SAndroid Build Coastguard Worker 119*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocateListener *mListener = nullptr; 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker std::vector<RingBufferAllocatorBuffer> mOldBuffers; 122*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocatorBuffer mBuffer; 123*8975f5c5SAndroid Build Coastguard Worker uint8_t *mDataBegin = nullptr; 124*8975f5c5SAndroid Build Coastguard Worker uint8_t *mDataEnd = nullptr; 125*8975f5c5SAndroid Build Coastguard Worker uint8_t *mFragmentEnd = nullptr; 126*8975f5c5SAndroid Build Coastguard Worker uint8_t *mFragmentEndR = nullptr; 127*8975f5c5SAndroid Build Coastguard Worker uint32_t mFragmentReserve = 0; 128*8975f5c5SAndroid Build Coastguard Worker 129*8975f5c5SAndroid Build Coastguard Worker uint32_t mMinCapacity = 0; 130*8975f5c5SAndroid Build Coastguard Worker uint32_t mCurrentCapacity = 0; 131*8975f5c5SAndroid Build Coastguard Worker uint32_t mAllocationMargin = 0; 132*8975f5c5SAndroid Build Coastguard Worker 133*8975f5c5SAndroid Build Coastguard Worker // 1 - fastest decay speed. 134*8975f5c5SAndroid Build Coastguard Worker // 2 - 2x slower than fastest, and so on. 135*8975f5c5SAndroid Build Coastguard Worker uint32_t mDecaySpeedFactor = 0; 136*8975f5c5SAndroid Build Coastguard Worker }; 137*8975f5c5SAndroid Build Coastguard Worker 138*8975f5c5SAndroid Build Coastguard Worker class SharedRingBufferAllocatorCheckPoint final : angle::NonCopyable 139*8975f5c5SAndroid Build Coastguard Worker { 140*8975f5c5SAndroid Build Coastguard Worker public: 141*8975f5c5SAndroid Build Coastguard Worker void releaseAndUpdate(RingBufferAllocatorCheckPoint *newValue); 142*8975f5c5SAndroid Build Coastguard Worker 143*8975f5c5SAndroid Build Coastguard Worker private: 144*8975f5c5SAndroid Build Coastguard Worker friend class SharedRingBufferAllocator; 145*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocatorCheckPoint pop(); 146*8975f5c5SAndroid Build Coastguard Worker angle::SimpleMutex mMutex; 147*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocatorCheckPoint mValue; 148*8975f5c5SAndroid Build Coastguard Worker 149*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_ENABLE_ASSERTS) 150*8975f5c5SAndroid Build Coastguard Worker std::atomic<uint32_t> mRefCount{1}; 151*8975f5c5SAndroid Build Coastguard Worker #endif 152*8975f5c5SAndroid Build Coastguard Worker }; 153*8975f5c5SAndroid Build Coastguard Worker 154*8975f5c5SAndroid Build Coastguard Worker class SharedRingBufferAllocator final : angle::NonCopyable 155*8975f5c5SAndroid Build Coastguard Worker { 156*8975f5c5SAndroid Build Coastguard Worker public: 157*8975f5c5SAndroid Build Coastguard Worker SharedRingBufferAllocator(); 158*8975f5c5SAndroid Build Coastguard Worker ~SharedRingBufferAllocator(); 159*8975f5c5SAndroid Build Coastguard Worker get()160*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocator &get() { return mAllocator; } 161*8975f5c5SAndroid Build Coastguard Worker 162*8975f5c5SAndroid Build Coastguard Worker // Once shared - always shared isShared()163*8975f5c5SAndroid Build Coastguard Worker bool isShared() const { return mSharedCP != nullptr; } 164*8975f5c5SAndroid Build Coastguard Worker 165*8975f5c5SAndroid Build Coastguard Worker // Once acquired must be released with releaseAndUpdate(). 166*8975f5c5SAndroid Build Coastguard Worker SharedRingBufferAllocatorCheckPoint *acquireSharedCP(); 167*8975f5c5SAndroid Build Coastguard Worker void releaseToSharedCP(); 168*8975f5c5SAndroid Build Coastguard Worker 169*8975f5c5SAndroid Build Coastguard Worker private: 170*8975f5c5SAndroid Build Coastguard Worker RingBufferAllocator mAllocator; 171*8975f5c5SAndroid Build Coastguard Worker SharedRingBufferAllocatorCheckPoint *mSharedCP = nullptr; 172*8975f5c5SAndroid Build Coastguard Worker }; 173*8975f5c5SAndroid Build Coastguard Worker 174*8975f5c5SAndroid Build Coastguard Worker } // namespace angle 175*8975f5c5SAndroid Build Coastguard Worker 176*8975f5c5SAndroid Build Coastguard Worker #endif // COMMON_RING_BUFFER_ALLOCATOR_H_ 177