rhi: Make res. update batch buffer op list more bounded
Make the behavior more bounded, by disallowing keeping large sets of buffer data for reuse. The idea being that once I uploaded say the Sponza model (e.g. 10 MB of vertex data merged into one blob), it is not beneficial to keep that huge allocation since the total size of the data from per-frame buffer changes will be in a whole different (smaller) league typically, and the chance of another (single) buffer update that utilizes the whole 10 MB on its own is rather small. Have a simple (and cheap to execute) rule that no batch keeps more than 1 MB of QRhiBufferData (in total, regardless how many buffer operations it contained/contains). If the limit is exceeded, we clear(). The catch is that even without doing the 1 MB check, there is a high chance that the Sponza model data will be gone in a few frames eventually, due to implicit sharing and how the QRhi backends and Qt Quick(3D) work and shuffle their resource update batch requests and submissions. So for many applications this is expected to change nothing when it comes to their memory consumption profile. Expand the comments further. Change-Id: I93061d073b43e747a0772a3119ebdb89bed02ae0 Reviewed-by: Andy Nichols <andy.nichols@qt.io> (cherry picked from commit bc2c09a182c2bc80c307e7e71e0f12c1c31edc3d) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
e4bd5c631a
commit
7d64c858b5
@ -9334,13 +9334,14 @@ void QRhiResourceUpdateBatchPrivate::free()
|
||||
{
|
||||
Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
|
||||
|
||||
quint32 bufferDataTotal = 0;
|
||||
quint32 bufferLargeAllocTotal = 0;
|
||||
for (const BufferOp &op : std::as_const(bufferOps)) {
|
||||
bufferDataTotal += op.data.size();
|
||||
bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
|
||||
}
|
||||
|
||||
if (rhi->rubLogEnabled) {
|
||||
quint32 bufferDataTotal = 0;
|
||||
quint32 bufferLargeAllocTotal = 0;
|
||||
for (const BufferOp &op : std::as_const(bufferOps)) {
|
||||
bufferDataTotal += op.data.size();
|
||||
bufferLargeAllocTotal += op.data.largeAlloc(); // alloc when > 1 KB
|
||||
}
|
||||
qDebug() << "[rub] release to pool upd.batch #" << poolIndex
|
||||
<< "/ bufferOps active" << activeBufferOpCount
|
||||
<< "of" << bufferOps.count()
|
||||
@ -9362,10 +9363,19 @@ void QRhiResourceUpdateBatchPrivate::free()
|
||||
// at least. Only trimOpList() goes for the more aggressive route with squeeze.
|
||||
textureOps.clear();
|
||||
|
||||
// bufferOps is not touched, to allow reusing allocations (incl. in the
|
||||
// elements' QRhiBufferData) as much as possible when this batch is used
|
||||
// again in the future, which is important for performance, in particular
|
||||
// with Qt Quick.
|
||||
// bufferOps is not touched in many cases, to allow reusing allocations
|
||||
// (incl. in the elements' QRhiBufferData) as much as possible when this
|
||||
// batch is used again in the future, which is important for performance, in
|
||||
// particular with Qt Quick where it is easy for scenes to produce lots of,
|
||||
// typically small buffer changes on every frame.
|
||||
//
|
||||
// However, ensure that even in the unlikely case of having the max number
|
||||
// of batches (64) created in resUpdPool, no more than 64 MB in total is
|
||||
// used up by buffer data just to help future reuse. For simplicity, if
|
||||
// there is more than 1 MB data -> clear. Applications with frequent, huge
|
||||
// buffer updates probably have other bottlenecks anyway.
|
||||
if (bufferLargeAllocTotal > 1024 * 1024)
|
||||
bufferOps.clear();
|
||||
}
|
||||
|
||||
void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
|
||||
|
Loading…
x
Reference in New Issue
Block a user