diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2020-09-29 17:38:26 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2020-09-30 10:39:59 +0200 |
commit | 2f879062a5ce9e78c1e257924bcdc5ac95cba465 (patch) | |
tree | 34222dd886c8608d4ea7190763a67827f598e321 /src/gui/rhi/qrhi_p_p.h | |
parent | 0836db2330c0542d91fe61935e97d3369db93156 (diff) |
rhi: Manage buffer data without QBA
Use a simple and straightforward container that only does what
we need here.
Change-Id: I1a81b53a58bc91d533e3d7df5471a1362046825d
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/gui/rhi/qrhi_p_p.h')
-rw-r--r-- | src/gui/rhi/qrhi_p_p.h | 115 |
1 files changed, 79 insertions, 36 deletions
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index 3b68b5d078..1316321694 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -277,6 +277,80 @@ bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, return true; } +struct QRhiBufferDataPrivate +{ + Q_DISABLE_COPY_MOVE(QRhiBufferDataPrivate) + QRhiBufferDataPrivate() { } + ~QRhiBufferDataPrivate() { delete[] largeData; } + int ref = 1; + int size = 0; + int largeAlloc = 0; + char *largeData = nullptr; + static constexpr int SMALL_DATA_SIZE = 1024; + char data[SMALL_DATA_SIZE]; +}; + +// no detach-with-contents, no atomic refcount, no shrink +class QRhiBufferData +{ +public: + QRhiBufferData() = default; + ~QRhiBufferData() + { + if (d && !--d->ref) + delete d; + } + QRhiBufferData(const QRhiBufferData &other) + : d(other.d) + { + if (d) + d->ref += 1; + } + QRhiBufferData &operator=(const QRhiBufferData &other) + { + if (d == other.d) + return *this; + if (other.d) + other.d->ref += 1; + if (d && !--d->ref) + delete d; + d = other.d; + return *this; + } + const char *constData() const + { + return d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->data : d->largeData; + } + int size() const + { + return d->size; + } + void assign(const char *s, int size) + { + if (!d) { + d = new QRhiBufferDataPrivate; + } else if (d->ref != 1) { + d->ref -= 1; + d = new QRhiBufferDataPrivate; + } + d->size = size; + if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) { + memcpy(d->data, s, size); + } else { + if (d->largeAlloc < size) { + delete[] d->largeData; + d->largeAlloc = size; + d->largeData = new char[size]; + } + memcpy(d->largeData, s, size); + } + } +private: + QRhiBufferDataPrivate *d = nullptr; +}; + +Q_DECLARE_TYPEINFO(QRhiBufferData, Q_MOVABLE_TYPE); + class QRhiResourceUpdateBatchPrivate { public: @@ -289,8 +363,7 @@ public: Type type; QRhiBuffer *buf; int offset; - QByteArray data; - int dataSize; // the real number of currently used bytes in data, not the same as data.size() + QRhiBufferData data; int readSize; QRhiBufferReadbackResult *result; @@ -301,8 +374,7 @@ public: op.buf = buf; op.offset = offset; const int effectiveSize = size ? size : buf->size(); - op.data = QByteArray(reinterpret_cast<const char *>(data), effectiveSize); - op.dataSize = effectiveSize; + op.data.assign(reinterpret_cast<const char *>(data), effectiveSize); return op; } @@ -312,28 +384,7 @@ public: op->buf = buf; op->offset = offset; const int effectiveSize = size ? size : buf->size(); - - // Why the isDetached check? Simply because the cost of detaching - // with a larger allocation may be a lot higher than creating a new - // deep copy bytearray with our (potentially lot smaller) data. - // This reduces the benefits with certain backends (e.g. Vulkan) - // that hold on to the data (implicit sharing!) of host visible - // buffers for the current and next frame (assuming 2 frames in - // flight), but it is still an improvement (enabled by - // nextResourceUpdateBatch's shuffling when choosing a free batch - // from the pool). For other backends (e.g. D3D11) this can reduce - // mallocs (caused by creating new deep copy bytearrays) almost - // completely after a few frames (assuming of course that no - // dynamic elements with larger buffer data appear). - - if (op->data.isDetached()) { - if (op->data.size() < effectiveSize) - op->data.resize(effectiveSize); - memcpy(op->data.data(), data, effectiveSize); - } else { - op->data = QByteArray(reinterpret_cast<const char *>(data), effectiveSize); - } - op->dataSize = effectiveSize; + op->data.assign(reinterpret_cast<const char *>(data), effectiveSize); } static BufferOp staticUpload(QRhiBuffer *buf, int offset, int size, const void *data) @@ -343,8 +394,7 @@ public: op.buf = buf; op.offset = offset; const int effectiveSize = size ? size : buf->size(); - op.data = QByteArray(reinterpret_cast<const char *>(data), effectiveSize); - op.dataSize = effectiveSize; + op.data.assign(reinterpret_cast<const char *>(data), effectiveSize); return op; } @@ -354,14 +404,7 @@ public: op->buf = buf; op->offset = offset; const int effectiveSize = size ? size : buf->size(); - if (op->data.isDetached()) { - if (op->data.size() < effectiveSize) - op->data.resize(effectiveSize); - memcpy(op->data.data(), data, effectiveSize); - } else { - op->data = QByteArray(reinterpret_cast<const char *>(data), effectiveSize); - } - op->dataSize = effectiveSize; + op->data.assign(reinterpret_cast<const char *>(data), effectiveSize); } static BufferOp read(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result) |