Skip to content

Commit c8ef723

Browse files
committed
More flexible buffer pool's allocation policy
Buffer could be allocated in shared memory, or GPU memory or automatically chosen based on size Change-Id: Iab8ce9313c9ff2a7e0f062cd874d1b24a54d7de4
1 parent 810f204 commit c8ef723

File tree

5 files changed

+55
-12
lines changed

5 files changed

+55
-12
lines changed

src/libANGLE/renderer/metal/BufferMtl.mm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,17 +367,20 @@
367367
case gl::BufferUsage::DynamicRead:
368368
case gl::BufferUsage::StreamRead:
369369
maxBuffers = 1; // static/read buffer doesn't need high speed data update
370+
mBufferPool.setAlwaysUseGPUMem();
370371
break;
371372
default:
372373
// dynamic buffer, allow up to 10 update per frame/encoding without
373374
// waiting for GPU.
374375
if (adjustedSize <= kDynamicBufferPoolMaxBufSize)
375376
{
376377
maxBuffers = 10;
378+
mBufferPool.setAlwaysUseSharedMem();
377379
}
378380
else
379381
{
380382
maxBuffers = 1;
383+
mBufferPool.setAlwaysUseGPUMem();
381384
}
382385
break;
383386
}

src/libANGLE/renderer/metal/mtl_buffer_pool.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ class ContextMtl;
2020
namespace mtl
2121
{
2222

23+
enum class BufferPoolMemPolicy
24+
{
25+
AlwaysSharedMem, // Always allocate buffer in shared memory, useful for dynamic small buffer
26+
AlwaysGPUMem, // Always allocate buffer in GPU dedicated memory.
27+
Auto, // Auto allocate buffer in shared memory if it is small. GPU otherwise.
28+
};
29+
2330
// A buffer pool is conceptually an infinitely long buffer. Each time you write to the buffer,
2431
// you will always write to a previously unused portion. After a series of writes, you must flush
2532
// the buffer data to the device. Buffer lifetime currently assumes that each new allocation will
@@ -39,7 +46,7 @@ class BufferPool
3946
// - alwaysUseSharedMem: indicate the allocated buffers should be in shared memory or not.
4047
// If this flag is false. Buffer pool will automatically use shared mem if buffer size is small.
4148
BufferPool(bool alwaysAllocNewBuffer = false);
42-
BufferPool(bool alwaysAllocNewBuffer, bool alwaysUseSharedMem);
49+
BufferPool(bool alwaysAllocNewBuffer, BufferPoolMemPolicy memPolicy);
4350
~BufferPool();
4451

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

82-
// Set whether all subsequent allocated buffers should always use shared memory or not
83-
void setAlwaysUseSharedMem(bool e) { mAlwaysUseSharedMem = e; }
89+
void setMemoryPolicy(BufferPoolMemPolicy policy) { mMemPolicy = policy; }
90+
91+
// Set all subsequent allocated buffers should always use shared memory
92+
void setAlwaysUseSharedMem() { setMemoryPolicy(BufferPoolMemPolicy::AlwaysSharedMem); }
93+
94+
// Set all subsequent allocated buffers should always use GPU memory
95+
void setAlwaysUseGPUMem() { setMemoryPolicy(BufferPoolMemPolicy::AlwaysGPUMem); }
8496

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

99112
size_t mBuffersAllocated;
100113
size_t mMaxBuffers;
114+
BufferPoolMemPolicy mMemPolicy = BufferPoolMemPolicy::Auto;
101115
bool mAlwaysAllocateNewBuffer;
102-
bool mAlwaysUseSharedMem;
103116
};
104117

105118
} // namespace mtl

src/libANGLE/renderer/metal/mtl_buffer_pool.mm

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,23 @@
2020
namespace
2121
{
2222
// The max size of a buffer that will be allocated in shared memory
23-
constexpr size_t kSharedMemBufferMaxBufSize = 128 * 1024;
23+
constexpr size_t kSharedMemBufferMaxBufSizeHint = 128 * 1024;
2424
}
2525

2626
// BufferPool implementation.
27-
BufferPool::BufferPool(bool alwaysAllocNewBuffer) : BufferPool(alwaysAllocNewBuffer, false) {}
28-
BufferPool::BufferPool(bool alwaysAllocNewBuffer, bool alwaysUseSharedMem)
27+
BufferPool::BufferPool(bool alwaysAllocNewBuffer)
28+
: BufferPool(alwaysAllocNewBuffer, BufferPoolMemPolicy::Auto)
29+
{}
30+
BufferPool::BufferPool(bool alwaysAllocNewBuffer, BufferPoolMemPolicy policy)
2931
: mInitialSize(0),
3032
mBuffer(nullptr),
3133
mNextAllocationOffset(0),
3234
mSize(0),
3335
mAlignment(1),
3436
mBuffersAllocated(0),
3537
mMaxBuffers(0),
36-
mAlwaysAllocateNewBuffer(alwaysAllocNewBuffer),
37-
mAlwaysUseSharedMem(alwaysUseSharedMem)
38+
mMemPolicy(policy),
39+
mAlwaysAllocateNewBuffer(alwaysAllocNewBuffer)
3840

3941
{}
4042

@@ -65,7 +67,7 @@
6567
{
6668
continue;
6769
}
68-
bool useSharedMem = mAlwaysUseSharedMem || mSize <= kSharedMemBufferMaxBufSize;
70+
bool useSharedMem = shouldAllocateInSharedMem();
6971
if (IsError(buffer->reset(contextMtl, useSharedMem, mSize, nullptr)))
7072
{
7173
mBufferFreeList.clear();
@@ -90,6 +92,19 @@
9092

9193
BufferPool::~BufferPool() {}
9294

95+
bool BufferPool::shouldAllocateInSharedMem() const
96+
{
97+
switch (mMemPolicy)
98+
{
99+
case BufferPoolMemPolicy::AlwaysSharedMem:
100+
return true;
101+
case BufferPoolMemPolicy::AlwaysGPUMem:
102+
return false;
103+
default:
104+
return mSize <= kSharedMemBufferMaxBufSizeHint;
105+
}
106+
}
107+
93108
angle::Result BufferPool::allocateNewBuffer(ContextMtl *contextMtl)
94109
{
95110
if (mMaxBuffers > 0 && mBuffersAllocated >= mMaxBuffers)
@@ -120,7 +135,7 @@
120135
return angle::Result::Continue;
121136
}
122137

123-
bool useSharedMem = mAlwaysUseSharedMem || mSize <= kSharedMemBufferMaxBufSize;
138+
bool useSharedMem = shouldAllocateInSharedMem();
124139
ANGLE_TRY(Buffer::MakeBuffer(contextMtl, useSharedMem, mSize, nullptr, &mBuffer));
125140

126141
ASSERT(mBuffer);
@@ -225,7 +240,12 @@
225240
for (auto &toRelease : mInFlightBuffers)
226241
{
227242
// If the dynamic buffer was resized we cannot reuse the retained buffer.
228-
if (toRelease->size() < mSize)
243+
if (toRelease->size() < mSize
244+
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
245+
// Also release buffer if it was allocated in different policy
246+
|| toRelease->useSharedMem() != shouldAllocateInSharedMem()
247+
#endif
248+
)
229249
{
230250
toRelease = nullptr;
231251
mBuffersAllocated--;

src/libANGLE/renderer/metal/mtl_resources.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class Buffer final : public Resource,
238238
void unmap(ContextMtl *context, size_t offsetWritten, size_t sizeWritten);
239239

240240
size_t size() const;
241+
bool useSharedMem() const;
241242

242243
// Explicitly sync content between CPU and GPU
243244
void syncContent(ContextMtl *context, mtl::BlitCommandEncoder *encoder);

src/libANGLE/renderer/metal/mtl_resources.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,5 +661,11 @@ void EnsureContentSynced(ContextMtl *context, const std::shared_ptr<T> &resource
661661
{
662662
return get().length;
663663
}
664+
665+
bool Buffer::useSharedMem() const
666+
{
667+
return get().storageMode == MTLStorageModeShared;
668+
}
669+
664670
}
665671
}

0 commit comments

Comments
 (0)