Skip to content

Commit

Permalink
More flexible buffer pool's allocation policy
Browse files Browse the repository at this point in the history
Buffer could be allocated in shared memory, or GPU memory
or automatically chosen based on size

Change-Id: Iab8ce9313c9ff2a7e0f062cd874d1b24a54d7de4
  • Loading branch information
kakashidinho committed Feb 29, 2020
1 parent 810f204 commit c8ef723
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 12 deletions.
3 changes: 3 additions & 0 deletions src/libANGLE/renderer/metal/BufferMtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,20 @@
case gl::BufferUsage::DynamicRead:
case gl::BufferUsage::StreamRead:
maxBuffers = 1; // static/read buffer doesn't need high speed data update
mBufferPool.setAlwaysUseGPUMem();
break;
default:
// dynamic buffer, allow up to 10 update per frame/encoding without
// waiting for GPU.
if (adjustedSize <= kDynamicBufferPoolMaxBufSize)
{
maxBuffers = 10;
mBufferPool.setAlwaysUseSharedMem();
}
else
{
maxBuffers = 1;
mBufferPool.setAlwaysUseGPUMem();
}
break;
}
Expand Down
21 changes: 17 additions & 4 deletions src/libANGLE/renderer/metal/mtl_buffer_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ class ContextMtl;
namespace mtl
{

enum class BufferPoolMemPolicy
{
AlwaysSharedMem, // Always allocate buffer in shared memory, useful for dynamic small buffer
AlwaysGPUMem, // Always allocate buffer in GPU dedicated memory.
Auto, // Auto allocate buffer in shared memory if it is small. GPU otherwise.
};

// A buffer pool is conceptually an infinitely long buffer. Each time you write to the buffer,
// you will always write to a previously unused portion. After a series of writes, you must flush
// the buffer data to the device. Buffer lifetime currently assumes that each new allocation will
Expand All @@ -39,7 +46,7 @@ class BufferPool
// - alwaysUseSharedMem: indicate the allocated buffers should be in shared memory or not.
// If this flag is false. Buffer pool will automatically use shared mem if buffer size is small.
BufferPool(bool alwaysAllocNewBuffer = false);
BufferPool(bool alwaysAllocNewBuffer, bool alwaysUseSharedMem);
BufferPool(bool alwaysAllocNewBuffer, BufferPoolMemPolicy memPolicy);
~BufferPool();

// Init is called after the buffer creation so that the alignment can be specified later.
Expand Down Expand Up @@ -79,10 +86,16 @@ class BufferPool
// buffer or not. Default is false.
void setAlwaysAllocateNewBuffer(bool e) { mAlwaysAllocateNewBuffer = e; }

// Set whether all subsequent allocated buffers should always use shared memory or not
void setAlwaysUseSharedMem(bool e) { mAlwaysUseSharedMem = e; }
void setMemoryPolicy(BufferPoolMemPolicy policy) { mMemPolicy = policy; }

// Set all subsequent allocated buffers should always use shared memory
void setAlwaysUseSharedMem() { setMemoryPolicy(BufferPoolMemPolicy::AlwaysSharedMem); }

// Set all subsequent allocated buffers should always use GPU memory
void setAlwaysUseGPUMem() { setMemoryPolicy(BufferPoolMemPolicy::AlwaysGPUMem); }

private:
bool shouldAllocateInSharedMem() const;
void reset();
angle::Result allocateNewBuffer(ContextMtl *contextMtl);
void destroyBufferList(ContextMtl *contextMtl, std::vector<BufferRef> *buffers);
Expand All @@ -98,8 +111,8 @@ class BufferPool

size_t mBuffersAllocated;
size_t mMaxBuffers;
BufferPoolMemPolicy mMemPolicy = BufferPoolMemPolicy::Auto;
bool mAlwaysAllocateNewBuffer;
bool mAlwaysUseSharedMem;
};

} // namespace mtl
Expand Down
36 changes: 28 additions & 8 deletions src/libANGLE/renderer/metal/mtl_buffer_pool.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@
namespace
{
// The max size of a buffer that will be allocated in shared memory
constexpr size_t kSharedMemBufferMaxBufSize = 128 * 1024;
constexpr size_t kSharedMemBufferMaxBufSizeHint = 128 * 1024;
}

// BufferPool implementation.
BufferPool::BufferPool(bool alwaysAllocNewBuffer) : BufferPool(alwaysAllocNewBuffer, false) {}
BufferPool::BufferPool(bool alwaysAllocNewBuffer, bool alwaysUseSharedMem)
BufferPool::BufferPool(bool alwaysAllocNewBuffer)
: BufferPool(alwaysAllocNewBuffer, BufferPoolMemPolicy::Auto)
{}
BufferPool::BufferPool(bool alwaysAllocNewBuffer, BufferPoolMemPolicy policy)
: mInitialSize(0),
mBuffer(nullptr),
mNextAllocationOffset(0),
mSize(0),
mAlignment(1),
mBuffersAllocated(0),
mMaxBuffers(0),
mAlwaysAllocateNewBuffer(alwaysAllocNewBuffer),
mAlwaysUseSharedMem(alwaysUseSharedMem)
mMemPolicy(policy),
mAlwaysAllocateNewBuffer(alwaysAllocNewBuffer)

{}

Expand Down Expand Up @@ -65,7 +67,7 @@
{
continue;
}
bool useSharedMem = mAlwaysUseSharedMem || mSize <= kSharedMemBufferMaxBufSize;
bool useSharedMem = shouldAllocateInSharedMem();
if (IsError(buffer->reset(contextMtl, useSharedMem, mSize, nullptr)))
{
mBufferFreeList.clear();
Expand All @@ -90,6 +92,19 @@

BufferPool::~BufferPool() {}

bool BufferPool::shouldAllocateInSharedMem() const
{
switch (mMemPolicy)
{
case BufferPoolMemPolicy::AlwaysSharedMem:
return true;
case BufferPoolMemPolicy::AlwaysGPUMem:
return false;
default:
return mSize <= kSharedMemBufferMaxBufSizeHint;
}
}

angle::Result BufferPool::allocateNewBuffer(ContextMtl *contextMtl)
{
if (mMaxBuffers > 0 && mBuffersAllocated >= mMaxBuffers)
Expand Down Expand Up @@ -120,7 +135,7 @@
return angle::Result::Continue;
}

bool useSharedMem = mAlwaysUseSharedMem || mSize <= kSharedMemBufferMaxBufSize;
bool useSharedMem = shouldAllocateInSharedMem();
ANGLE_TRY(Buffer::MakeBuffer(contextMtl, useSharedMem, mSize, nullptr, &mBuffer));

ASSERT(mBuffer);
Expand Down Expand Up @@ -225,7 +240,12 @@
for (auto &toRelease : mInFlightBuffers)
{
// If the dynamic buffer was resized we cannot reuse the retained buffer.
if (toRelease->size() < mSize)
if (toRelease->size() < mSize
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
// Also release buffer if it was allocated in different policy
|| toRelease->useSharedMem() != shouldAllocateInSharedMem()
#endif
)
{
toRelease = nullptr;
mBuffersAllocated--;
Expand Down
1 change: 1 addition & 0 deletions src/libANGLE/renderer/metal/mtl_resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ class Buffer final : public Resource,
void unmap(ContextMtl *context, size_t offsetWritten, size_t sizeWritten);

size_t size() const;
bool useSharedMem() const;

// Explicitly sync content between CPU and GPU
void syncContent(ContextMtl *context, mtl::BlitCommandEncoder *encoder);
Expand Down
6 changes: 6 additions & 0 deletions src/libANGLE/renderer/metal/mtl_resources.mm
Original file line number Diff line number Diff line change
Expand Up @@ -661,5 +661,11 @@ void EnsureContentSynced(ContextMtl *context, const std::shared_ptr<T> &resource
{
return get().length;
}

bool Buffer::useSharedMem() const
{
return get().storageMode == MTLStorageModeShared;
}

}
}

0 comments on commit c8ef723

Please sign in to comment.