summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-09-22 19:21:19 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-09-23 16:59:06 +0200
commit6b52ba42865c6d298a8ddf1d735e4c3d3b3dab56 (patch)
tree6015c4f970f89af47c8ce59a25bcc0fe0d268ca2
parent230be3c4d1e53d7024064b926010131c6a83762f (diff)
rhi: Reuse buffer/texture op entries in res.update batches
More of an enabler for reusing the data in the individual entries since not clearing the QVLA does not give us much on its own. Change-Id: Ief9761f75382c3373cc2bc7b866eb59fdd8b3277 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/gui/rhi/qrhi.cpp110
-rw-r--r--src/gui/rhi/qrhi_p_p.h20
-rw-r--r--src/gui/rhi/qrhid3d11.cpp7
-rw-r--r--src/gui/rhi/qrhigles2.cpp6
-rw-r--r--src/gui/rhi/qrhimetal.mm6
-rw-r--r--src/gui/rhi/qrhinull.cpp6
-rw-r--r--src/gui/rhi/qrhivulkan.cpp6
7 files changed, 125 insertions, 36 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index a74765758c..849519cb7a 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -4694,8 +4694,9 @@ void QRhiResourceUpdateBatch::release()
/*!
Copies all queued operations from the \a other batch into this one.
- \note \a other is not changed in any way, typically it will still need a
- destroy()
+ \note \a other may no longer contain valid data after the merge operation,
+ and must not be submitted, but it will still need to be released by calling
+ release().
This allows for a convenient pattern where resource updates that are
already known during the initialization step are collected into a batch
@@ -4718,7 +4719,7 @@ void QRhiResourceUpdateBatch::release()
QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
if (initialUpdates) {
resUpdates->merge(initialUpdates);
- initialUpdates->destroy();
+ initialUpdates->release();
initialUpdates = nullptr;
}
resUpdates->updateDynamicBuffer(...);
@@ -4771,8 +4772,14 @@ bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
*/
void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
{
- if (size > 0)
- d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
+ if (size > 0) {
+ const int idx = d->activeBufferOpCount++;
+ const int opListSize = d->bufferOps.size();
+ if (idx < opListSize)
+ QRhiResourceUpdateBatchPrivate::BufferOp::changeToDynamicUpdate(&d->bufferOps[idx], buf, offset, size, data);
+ else
+ d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(buf, offset, size, data));
+ }
}
/*!
@@ -4785,8 +4792,13 @@ void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, i
*/
void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
{
- if (size > 0)
- d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
+ if (size > 0) {
+ const int idx = d->activeBufferOpCount++;
+ if (idx < d->bufferOps.size())
+ QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, offset, size, data);
+ else
+ d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, offset, size, data));
+ }
}
/*!
@@ -4795,8 +4807,13 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, in
*/
void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *data)
{
- if (buf->size() > 0)
- d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
+ if (buf->size() > 0) {
+ const int idx = d->activeBufferOpCount++;
+ if (idx < d->bufferOps.size())
+ QRhiResourceUpdateBatchPrivate::BufferOp::changeToStaticUpload(&d->bufferOps[idx], buf, 0, 0, data);
+ else
+ d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::staticUpload(buf, 0, 0, data));
+ }
}
/*!
@@ -4825,7 +4842,11 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *da
*/
void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
{
- d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
+ const int idx = d->activeBufferOpCount++;
+ if (idx < d->bufferOps.size())
+ d->bufferOps[idx] = QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result);
+ else
+ d->bufferOps.append(QRhiResourceUpdateBatchPrivate::BufferOp::read(buf, offset, size, result));
}
/*!
@@ -4837,8 +4858,13 @@ void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, int offset, int si
*/
void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
{
- if (desc.cbeginEntries() != desc.cendEntries())
- d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
+ if (desc.cbeginEntries() != desc.cendEntries()) {
+ const int idx = d->activeTextureOpCount++;
+ if (idx < d->textureOps.size())
+ d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc);
+ else
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::upload(tex, desc));
+ }
}
/*!
@@ -4863,7 +4889,11 @@ void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &imag
*/
void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
{
- d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
+ const int idx = d->activeTextureOpCount++;
+ if (idx < d->textureOps.size())
+ d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc);
+ else
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::copy(dst, src, desc));
}
/*!
@@ -4925,7 +4955,11 @@ void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, co
*/
void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
{
- d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
+ const int idx = d->activeTextureOpCount++;
+ if (idx < d->textureOps.size())
+ d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result);
+ else
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::read(rb, result));
}
/*!
@@ -4937,7 +4971,11 @@ void QRhiResourceUpdateBatch::readBackTexture(const QRhiReadbackDescription &rb,
*/
void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer)
{
- d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex, layer));
+ const int idx = d->activeTextureOpCount++;
+ if (idx < d->textureOps.size())
+ d->textureOps[idx] = QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex, layer);
+ else
+ d->textureOps.append(QRhiResourceUpdateBatchPrivate::TextureOp::genMips(tex, layer));
}
/*!
@@ -4997,8 +5035,8 @@ void QRhiResourceUpdateBatchPrivate::free()
{
Q_ASSERT(poolIndex >= 0 && rhi->resUpdPool[poolIndex] == q);
- bufferOps.clear();
- textureOps.clear();
+ activeBufferOpCount = 0;
+ activeTextureOpCount = 0;
rhi->resUpdPoolMap.clearBit(poolIndex);
poolIndex = -1;
@@ -5006,19 +5044,36 @@ void QRhiResourceUpdateBatchPrivate::free()
void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
{
- bufferOps.reserve(bufferOps.size() + other->bufferOps.size());
- for (const BufferOp &op : qAsConst(other->bufferOps))
- bufferOps.append(op);
+ int combinedSize = activeBufferOpCount + other->activeBufferOpCount;
+ if (bufferOps.size() < combinedSize)
+ bufferOps.resize(combinedSize);
+ for (int i = activeBufferOpCount; i < combinedSize; ++i)
+ bufferOps[i] = std::move(other->bufferOps[i - activeBufferOpCount]);
+ activeBufferOpCount += other->activeBufferOpCount;
- textureOps.reserve(textureOps.size() + other->textureOps.size());
- for (const TextureOp &op : qAsConst(other->textureOps))
- textureOps.append(op);
+ combinedSize = activeTextureOpCount + other->activeTextureOpCount;
+ if (textureOps.size() < combinedSize)
+ textureOps.resize(combinedSize);
+ for (int i = activeTextureOpCount; i < combinedSize; ++i)
+ textureOps[i] = std::move(other->textureOps[i - activeTextureOpCount]);
+ activeTextureOpCount += other->activeTextureOpCount;
}
bool QRhiResourceUpdateBatchPrivate::hasOptimalCapacity() const
{
- return bufferOps.count() < BUFFER_OPS_STATIC_ALLOC - 16
- && textureOps.count() < TEXTURE_OPS_STATIC_ALLOC - 16;
+ return activeBufferOpCount < BUFFER_OPS_STATIC_ALLOC - 16
+ && activeTextureOpCount < TEXTURE_OPS_STATIC_ALLOC - 16;
+}
+
+void QRhiResourceUpdateBatchPrivate::trimOpLists()
+{
+ Q_ASSERT(poolIndex == -1); // must not be in use
+
+ activeBufferOpCount = 0;
+ bufferOps.clear();
+
+ activeTextureOpCount = 0;
+ textureOps.clear();
}
/*!
@@ -5723,6 +5778,11 @@ QRhiProfiler *QRhi::profiler()
void QRhi::releaseCachedResources()
{
d->releaseCachedResources();
+
+ for (QRhiResourceUpdateBatch *u : d->resUpdPool) {
+ if (u->d->poolIndex < 0)
+ u->d->trimOpLists();
+ }
}
/*!
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index 7fadcfcc1e..a7d8a40bf9 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -302,6 +302,14 @@ public:
return op;
}
+ static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, int offset, int size, const void *data)
+ {
+ op->type = DynamicUpdate;
+ op->buf = buf;
+ op->offset = offset;
+ op->data = QByteArray(reinterpret_cast<const char *>(data), size ? size : buf->size());
+ }
+
static BufferOp staticUpload(QRhiBuffer *buf, int offset, int size, const void *data)
{
BufferOp op = {};
@@ -312,6 +320,14 @@ public:
return op;
}
+ static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, int offset, int size, const void *data)
+ {
+ op->type = StaticUpload;
+ op->buf = buf;
+ op->offset = offset;
+ op->data = QByteArray(reinterpret_cast<const char *>(data), size ? size : buf->size());
+ }
+
static BufferOp read(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
{
BufferOp op = {};
@@ -383,8 +399,11 @@ public:
}
};
+ int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
static const int BUFFER_OPS_STATIC_ALLOC = 1024;
QVarLengthArray<BufferOp, BUFFER_OPS_STATIC_ALLOC> bufferOps;
+
+ int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
static const int TEXTURE_OPS_STATIC_ALLOC = 256;
QVarLengthArray<TextureOp, TEXTURE_OPS_STATIC_ALLOC> textureOps;
@@ -395,6 +414,7 @@ public:
void free();
void merge(QRhiResourceUpdateBatchPrivate *other);
bool hasOptimalCapacity() const;
+ void trimOpLists();
static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
};
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index f3ddc7aac4..3b14b77ce1 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -1413,7 +1413,8 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : ud->bufferOps) {
+ for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
@@ -1485,8 +1486,8 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
u.result->completed();
}
}
-
- for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.dst);
for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 39c01b1144..190d506f9a 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -1681,7 +1681,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : ud->bufferOps) {
+ for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
@@ -1735,7 +1736,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
}
}
- for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, u.dst);
for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index a770c72a99..55adaa4d54 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1691,7 +1691,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : ud->bufferOps) {
+ for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
@@ -1729,7 +1730,8 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
}
};
- for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QMetalTexture *utexD = QRHI_RES(QMetalTexture, u.dst);
qsizetype stagingSize = 0;
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index 48fca4e212..94d24c33a9 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -459,7 +459,8 @@ void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
{
Q_UNUSED(cb);
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : ud->bufferOps) {
+ for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate
|| u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload)
{
@@ -474,7 +475,8 @@ void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
result->completed();
}
}
- for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
if (u.dst->format() == QRhiTexture::RGBA8)
simulateTextureUpload(u);
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 64609671ab..9ac8ef70ee 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -2923,7 +2923,8 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : ud->bufferOps) {
+ for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
@@ -3073,7 +3074,8 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
}
}
- for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
+ for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QVkTexture *utexD = QRHI_RES(QVkTexture, u.dst);
// batch into a single staging buffer and a single CopyBufferToImage with multiple copyInfos