Grow the persistently mapped VBO as needed
Reallocate the buffer when the average frame size is greater than half the size of the buffer.
This commit is contained in:
parent
4b3fabbfc9
commit
90dfb3ca8b
1 changed files with 57 additions and 8 deletions
|
@ -1529,6 +1529,38 @@ static void deleteAll(std::deque<BufferFence> &fences)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <size_t Count>
|
||||||
|
struct FrameSizesArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FrameSizesArray() {
|
||||||
|
m_array.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(size_t size) {
|
||||||
|
m_array[m_index] = size;
|
||||||
|
m_index = (m_index + 1) % Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t average() const {
|
||||||
|
size_t sum = 0;
|
||||||
|
for (size_t size : m_array)
|
||||||
|
sum += size;
|
||||||
|
return sum / Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<size_t, Count> m_array;
|
||||||
|
int m_index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//*********************************
|
//*********************************
|
||||||
// GLVertexBufferPrivate
|
// GLVertexBufferPrivate
|
||||||
//*********************************
|
//*********************************
|
||||||
|
@ -1566,8 +1598,10 @@ public:
|
||||||
~GLVertexBufferPrivate() {
|
~GLVertexBufferPrivate() {
|
||||||
deleteAll(fences);
|
deleteAll(fences);
|
||||||
|
|
||||||
glDeleteBuffers(1, &buffer);
|
if (buffer != 0) {
|
||||||
map = nullptr;
|
glDeleteBuffers(1, &buffer);
|
||||||
|
map = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void interleaveArrays(float *array, int dim, const float *vertices, const float *texcoords, int count);
|
void interleaveArrays(float *array, int dim, const float *vertices, const float *texcoords, int count);
|
||||||
|
@ -1600,6 +1634,7 @@ public:
|
||||||
intptr_t baseAddress;
|
intptr_t baseAddress;
|
||||||
uint8_t *map;
|
uint8_t *map;
|
||||||
std::deque<BufferFence> fences;
|
std::deque<BufferFence> fences;
|
||||||
|
FrameSizesArray<4> frameSizes;
|
||||||
VertexAttrib attrib[VertexAttributeCount];
|
VertexAttrib attrib[VertexAttributeCount];
|
||||||
Bitfield enabledArrays;
|
Bitfield enabledArrays;
|
||||||
#ifndef KWIN_HAVE_OPENGLES
|
#ifndef KWIN_HAVE_OPENGLES
|
||||||
|
@ -1696,7 +1731,7 @@ void GLVertexBufferPrivate::reallocatePersistentBuffer(size_t size)
|
||||||
glGenBuffers(1, &buffer);
|
glGenBuffers(1, &buffer);
|
||||||
|
|
||||||
// Round the size up to 64 kb
|
// Round the size up to 64 kb
|
||||||
size_t minSize = 128 * 1024;
|
size_t minSize = qMax<size_t>(frameSizes.average() * 3, 128 * 1024);
|
||||||
bufferSize = align(qMax(size, minSize), 64 * 1024);
|
bufferSize = align(qMax(size, minSize), 64 * 1024);
|
||||||
|
|
||||||
const GLbitfield storage = GL_DYNAMIC_STORAGE_BIT;
|
const GLbitfield storage = GL_DYNAMIC_STORAGE_BIT;
|
||||||
|
@ -2034,12 +2069,26 @@ void GLVertexBuffer::endOfFrame()
|
||||||
|
|
||||||
// Emit a fence if we have uploaded data
|
// Emit a fence if we have uploaded data
|
||||||
if (d->frameSize > 0) {
|
if (d->frameSize > 0) {
|
||||||
BufferFence fence;
|
d->frameSizes.push(d->frameSize);
|
||||||
fence.sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
||||||
fence.nextEnd = d->nextOffset + d->bufferSize;
|
|
||||||
|
|
||||||
d->fences.emplace_back(fence);
|
|
||||||
d->frameSize = 0;
|
d->frameSize = 0;
|
||||||
|
|
||||||
|
// Force the buffer to be reallocated at the beginning of the next frame
|
||||||
|
// if the average frame size is greater than half the size of the buffer
|
||||||
|
if (unlikely(d->frameSizes.average() > d->bufferSize / 2)) {
|
||||||
|
deleteAll(d->fences);
|
||||||
|
glDeleteBuffers(1, &d->buffer);
|
||||||
|
|
||||||
|
d->buffer = 0;
|
||||||
|
d->bufferSize = 0;
|
||||||
|
d->nextOffset = 0;
|
||||||
|
d->map = nullptr;
|
||||||
|
} else {
|
||||||
|
BufferFence fence;
|
||||||
|
fence.sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
fence.nextEnd = d->nextOffset + d->bufferSize;
|
||||||
|
|
||||||
|
d->fences.emplace_back(fence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue