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>
This commit is contained in:
parent
0836db2330
commit
2f879062a5
@ -277,6 +277,80 @@ bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T,
|
|||||||
return true;
|
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
|
class QRhiResourceUpdateBatchPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -289,8 +363,7 @@ public:
|
|||||||
Type type;
|
Type type;
|
||||||
QRhiBuffer *buf;
|
QRhiBuffer *buf;
|
||||||
int offset;
|
int offset;
|
||||||
QByteArray data;
|
QRhiBufferData data;
|
||||||
int dataSize; // the real number of currently used bytes in data, not the same as data.size()
|
|
||||||
int readSize;
|
int readSize;
|
||||||
QRhiBufferReadbackResult *result;
|
QRhiBufferReadbackResult *result;
|
||||||
|
|
||||||
@ -301,8 +374,7 @@ public:
|
|||||||
op.buf = buf;
|
op.buf = buf;
|
||||||
op.offset = offset;
|
op.offset = offset;
|
||||||
const int effectiveSize = size ? size : buf->size();
|
const int effectiveSize = size ? size : buf->size();
|
||||||
op.data = QByteArray(reinterpret_cast<const char *>(data), effectiveSize);
|
op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||||
op.dataSize = effectiveSize;
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,28 +384,7 @@ public:
|
|||||||
op->buf = buf;
|
op->buf = buf;
|
||||||
op->offset = offset;
|
op->offset = offset;
|
||||||
const int effectiveSize = size ? size : buf->size();
|
const int effectiveSize = size ? size : buf->size();
|
||||||
|
op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferOp staticUpload(QRhiBuffer *buf, int offset, int size, const void *data)
|
static BufferOp staticUpload(QRhiBuffer *buf, int offset, int size, const void *data)
|
||||||
@ -343,8 +394,7 @@ public:
|
|||||||
op.buf = buf;
|
op.buf = buf;
|
||||||
op.offset = offset;
|
op.offset = offset;
|
||||||
const int effectiveSize = size ? size : buf->size();
|
const int effectiveSize = size ? size : buf->size();
|
||||||
op.data = QByteArray(reinterpret_cast<const char *>(data), effectiveSize);
|
op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||||
op.dataSize = effectiveSize;
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,14 +404,7 @@ public:
|
|||||||
op->buf = buf;
|
op->buf = buf;
|
||||||
op->offset = offset;
|
op->offset = offset;
|
||||||
const int effectiveSize = size ? size : buf->size();
|
const int effectiveSize = size ? size : buf->size();
|
||||||
if (op->data.isDetached()) {
|
op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BufferOp read(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
|
static BufferOp read(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
|
||||||
|
@ -1418,17 +1418,17 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||||||
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
|
if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
|
||||||
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
|
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
|
||||||
memcpy(bufD->dynBuf + u.offset, u.data.constData(), size_t(u.dataSize));
|
memcpy(bufD->dynBuf + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
bufD->hasPendingDynamicUpdates = true;
|
bufD->hasPendingDynamicUpdates = true;
|
||||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
|
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
|
||||||
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
|
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
||||||
Q_ASSERT(u.offset + u.dataSize <= bufD->m_size);
|
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
|
||||||
QD3D11CommandBuffer::Command cmd;
|
QD3D11CommandBuffer::Command cmd;
|
||||||
cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes;
|
cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes;
|
||||||
cmd.args.updateSubRes.dst = bufD->buffer;
|
cmd.args.updateSubRes.dst = bufD->buffer;
|
||||||
cmd.args.updateSubRes.dstSubRes = 0;
|
cmd.args.updateSubRes.dstSubRes = 0;
|
||||||
cmd.args.updateSubRes.src = cbD->retainData(u.data);
|
cmd.args.updateSubRes.src = cbD->retainBufferData(u.data);
|
||||||
cmd.args.updateSubRes.srcRowPitch = 0;
|
cmd.args.updateSubRes.srcRowPitch = 0;
|
||||||
// Specify the region (even when offset is 0 and all data is provided)
|
// Specify the region (even when offset is 0 and all data is provided)
|
||||||
// since the ID3D11Buffer's size is rounded up to be a multiple of 256
|
// since the ID3D11Buffer's size is rounded up to be a multiple of 256
|
||||||
@ -1437,7 +1437,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||||||
box.left = UINT(u.offset);
|
box.left = UINT(u.offset);
|
||||||
box.top = box.front = 0;
|
box.top = box.front = 0;
|
||||||
box.back = box.bottom = 1;
|
box.back = box.bottom = 1;
|
||||||
box.right = UINT(u.offset + u.dataSize); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
|
box.right = UINT(u.offset + u.data.size()); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
|
||||||
cmd.args.updateSubRes.hasDstBox = true;
|
cmd.args.updateSubRes.hasDstBox = true;
|
||||||
cmd.args.updateSubRes.dstBox = box;
|
cmd.args.updateSubRes.dstBox = box;
|
||||||
cbD->commands.append(cmd);
|
cbD->commands.append(cmd);
|
||||||
|
@ -473,6 +473,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||||
|
|
||||||
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
||||||
|
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
||||||
QVarLengthArray<QImage, 4> imageRetainPool;
|
QVarLengthArray<QImage, 4> imageRetainPool;
|
||||||
|
|
||||||
// relies heavily on implicit sharing (no copies of the actual data will be made)
|
// relies heavily on implicit sharing (no copies of the actual data will be made)
|
||||||
@ -480,6 +481,10 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
dataRetainPool.append(data);
|
dataRetainPool.append(data);
|
||||||
return reinterpret_cast<const uchar *>(dataRetainPool.last().constData());
|
return reinterpret_cast<const uchar *>(dataRetainPool.last().constData());
|
||||||
}
|
}
|
||||||
|
const uchar *retainBufferData(const QRhiBufferData &data) {
|
||||||
|
bufferDataRetainPool.append(data);
|
||||||
|
return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
|
||||||
|
}
|
||||||
const uchar *retainImage(const QImage &image) {
|
const uchar *retainImage(const QImage &image) {
|
||||||
imageRetainPool.append(image);
|
imageRetainPool.append(image);
|
||||||
return imageRetainPool.last().constBits();
|
return imageRetainPool.last().constBits();
|
||||||
@ -487,6 +492,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
void resetCommands() {
|
void resetCommands() {
|
||||||
commands.clear();
|
commands.clear();
|
||||||
dataRetainPool.clear();
|
dataRetainPool.clear();
|
||||||
|
bufferDataRetainPool.clear();
|
||||||
imageRetainPool.clear();
|
imageRetainPool.clear();
|
||||||
}
|
}
|
||||||
void resetState() {
|
void resetState() {
|
||||||
|
@ -1697,7 +1697,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||||||
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
|
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
|
||||||
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
|
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
|
||||||
memcpy(bufD->ubuf + u.offset, u.data.constData(), size_t(u.dataSize));
|
memcpy(bufD->ubuf + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
} else {
|
} else {
|
||||||
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
|
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
|
||||||
QGles2CommandBuffer::Command cmd;
|
QGles2CommandBuffer::Command cmd;
|
||||||
@ -1705,16 +1705,16 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||||||
cmd.args.bufferSubData.target = bufD->targetForDataOps;
|
cmd.args.bufferSubData.target = bufD->targetForDataOps;
|
||||||
cmd.args.bufferSubData.buffer = bufD->buffer;
|
cmd.args.bufferSubData.buffer = bufD->buffer;
|
||||||
cmd.args.bufferSubData.offset = u.offset;
|
cmd.args.bufferSubData.offset = u.offset;
|
||||||
cmd.args.bufferSubData.size = u.dataSize;
|
cmd.args.bufferSubData.size = u.data.size();
|
||||||
cmd.args.bufferSubData.data = cbD->retainData(u.data);
|
cmd.args.bufferSubData.data = cbD->retainBufferData(u.data);
|
||||||
cbD->commands.append(cmd);
|
cbD->commands.append(cmd);
|
||||||
}
|
}
|
||||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
|
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
|
||||||
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
|
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
||||||
Q_ASSERT(u.offset + u.dataSize <= bufD->m_size);
|
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
|
||||||
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
|
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
|
||||||
memcpy(bufD->ubuf + u.offset, u.data.constData(), size_t(u.dataSize));
|
memcpy(bufD->ubuf + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
} else {
|
} else {
|
||||||
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
|
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
|
||||||
QGles2CommandBuffer::Command cmd;
|
QGles2CommandBuffer::Command cmd;
|
||||||
@ -1722,8 +1722,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||||||
cmd.args.bufferSubData.target = bufD->targetForDataOps;
|
cmd.args.bufferSubData.target = bufD->targetForDataOps;
|
||||||
cmd.args.bufferSubData.buffer = bufD->buffer;
|
cmd.args.bufferSubData.buffer = bufD->buffer;
|
||||||
cmd.args.bufferSubData.offset = u.offset;
|
cmd.args.bufferSubData.offset = u.offset;
|
||||||
cmd.args.bufferSubData.size = u.dataSize;
|
cmd.args.bufferSubData.size = u.data.size();
|
||||||
cmd.args.bufferSubData.data = cbD->retainData(u.data);
|
cmd.args.bufferSubData.data = cbD->retainBufferData(u.data);
|
||||||
cbD->commands.append(cmd);
|
cbD->commands.append(cmd);
|
||||||
}
|
}
|
||||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
|
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
|
||||||
|
@ -578,6 +578,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
|
|||||||
} computePassState;
|
} computePassState;
|
||||||
|
|
||||||
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
||||||
|
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
||||||
QVarLengthArray<QImage, 4> imageRetainPool;
|
QVarLengthArray<QImage, 4> imageRetainPool;
|
||||||
|
|
||||||
// relies heavily on implicit sharing (no copies of the actual data will be made)
|
// relies heavily on implicit sharing (no copies of the actual data will be made)
|
||||||
@ -585,6 +586,10 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
|
|||||||
dataRetainPool.append(data);
|
dataRetainPool.append(data);
|
||||||
return dataRetainPool.last().constData();
|
return dataRetainPool.last().constData();
|
||||||
}
|
}
|
||||||
|
const uchar *retainBufferData(const QRhiBufferData &data) {
|
||||||
|
bufferDataRetainPool.append(data);
|
||||||
|
return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
|
||||||
|
}
|
||||||
const void *retainImage(const QImage &image) {
|
const void *retainImage(const QImage &image) {
|
||||||
imageRetainPool.append(image);
|
imageRetainPool.append(image);
|
||||||
return imageRetainPool.last().constBits();
|
return imageRetainPool.last().constBits();
|
||||||
@ -592,6 +597,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
|
|||||||
void resetCommands() {
|
void resetCommands() {
|
||||||
commands.clear();
|
commands.clear();
|
||||||
dataRetainPool.clear();
|
dataRetainPool.clear();
|
||||||
|
bufferDataRetainPool.clear();
|
||||||
imageRetainPool.clear();
|
imageRetainPool.clear();
|
||||||
|
|
||||||
passResTrackers.clear();
|
passResTrackers.clear();
|
||||||
|
@ -1703,10 +1703,10 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
|
|||||||
// basically the same. So go through the same pendingUpdates machinery.
|
// basically the same. So go through the same pendingUpdates machinery.
|
||||||
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
|
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
||||||
Q_ASSERT(u.offset + u.dataSize <= bufD->m_size);
|
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
|
||||||
for (int i = 0, ie = bufD->d->slotted ? QMTL_FRAMES_IN_FLIGHT : 1; i != ie; ++i)
|
for (int i = 0, ie = bufD->d->slotted ? QMTL_FRAMES_IN_FLIGHT : 1; i != ie; ++i)
|
||||||
bufD->d->pendingUpdates[i].append(
|
bufD->d->pendingUpdates[i].append(
|
||||||
QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(u.buf, u.offset, u.dataSize, u.data.constData()));
|
QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(u.buf, u.offset, u.data.size(), u.data.constData()));
|
||||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
|
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
|
||||||
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
|
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
|
||||||
executeBufferHostWritesForCurrentFrame(bufD);
|
executeBufferHostWritesForCurrentFrame(bufD);
|
||||||
@ -1868,11 +1868,11 @@ void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot)
|
|||||||
int changeEnd = -1;
|
int changeEnd = -1;
|
||||||
for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) {
|
for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) {
|
||||||
Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
|
Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
|
||||||
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.dataSize));
|
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
if (changeBegin == -1 || u.offset < changeBegin)
|
if (changeBegin == -1 || u.offset < changeBegin)
|
||||||
changeBegin = u.offset;
|
changeBegin = u.offset;
|
||||||
if (changeEnd == -1 || u.offset + u.dataSize > changeEnd)
|
if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
|
||||||
changeEnd = u.offset + u.dataSize;
|
changeEnd = u.offset + u.data.size();
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
if (changeBegin >= 0 && bufD->d->managed)
|
if (changeBegin >= 0 && bufD->d->managed)
|
||||||
|
@ -465,7 +465,7 @@ void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
|
|||||||
|| u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload)
|
|| u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload)
|
||||||
{
|
{
|
||||||
QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
|
QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
|
||||||
memcpy(bufD->data.data() + u.offset, u.data.constData(), size_t(u.dataSize));
|
memcpy(bufD->data.data() + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
|
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
|
||||||
QRhiBufferReadbackResult *result = u.result;
|
QRhiBufferReadbackResult *result = u.result;
|
||||||
result->data.resize(u.readSize);
|
result->data.resize(u.readSize);
|
||||||
|
@ -2929,11 +2929,11 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
|
|||||||
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
|
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
|
||||||
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
|
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
|
||||||
bufD->pendingDynamicUpdates[i].append({ u.offset, u.dataSize, u.data });
|
bufD->pendingDynamicUpdates[i].append({ u.offset, u.data });
|
||||||
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
|
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
|
||||||
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
|
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
|
||||||
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
|
||||||
Q_ASSERT(u.offset + u.dataSize <= bufD->m_size);
|
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
|
||||||
|
|
||||||
if (!bufD->stagingBuffers[currentFrameSlot]) {
|
if (!bufD->stagingBuffers[currentFrameSlot]) {
|
||||||
VkBufferCreateInfo bufferInfo;
|
VkBufferCreateInfo bufferInfo;
|
||||||
@ -2967,9 +2967,9 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
|
|||||||
qWarning("Failed to map buffer: %d", err);
|
qWarning("Failed to map buffer: %d", err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), size_t(u.dataSize));
|
memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
vmaUnmapMemory(toVmaAllocator(allocator), a);
|
vmaUnmapMemory(toVmaAllocator(allocator), a);
|
||||||
vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(u.offset), VkDeviceSize(u.dataSize));
|
vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(u.offset), VkDeviceSize(u.data.size()));
|
||||||
|
|
||||||
trackedBufferBarrier(cbD, bufD, 0,
|
trackedBufferBarrier(cbD, bufD, 0,
|
||||||
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||||
@ -2978,7 +2978,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
|
|||||||
memset(©Info, 0, sizeof(copyInfo));
|
memset(©Info, 0, sizeof(copyInfo));
|
||||||
copyInfo.srcOffset = VkDeviceSize(u.offset);
|
copyInfo.srcOffset = VkDeviceSize(u.offset);
|
||||||
copyInfo.dstOffset = VkDeviceSize(u.offset);
|
copyInfo.dstOffset = VkDeviceSize(u.offset);
|
||||||
copyInfo.size = VkDeviceSize(u.dataSize);
|
copyInfo.size = VkDeviceSize(u.data.size());
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.cmd = QVkCommandBuffer::Command::CopyBuffer;
|
cmd.cmd = QVkCommandBuffer::Command::CopyBuffer;
|
||||||
@ -3429,11 +3429,11 @@ void QRhiVulkan::executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot)
|
|||||||
int changeBegin = -1;
|
int changeBegin = -1;
|
||||||
int changeEnd = -1;
|
int changeEnd = -1;
|
||||||
for (const QVkBuffer::DynamicUpdate &u : qAsConst(bufD->pendingDynamicUpdates[slot])) {
|
for (const QVkBuffer::DynamicUpdate &u : qAsConst(bufD->pendingDynamicUpdates[slot])) {
|
||||||
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.size));
|
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
|
||||||
if (changeBegin == -1 || u.offset < changeBegin)
|
if (changeBegin == -1 || u.offset < changeBegin)
|
||||||
changeBegin = u.offset;
|
changeBegin = u.offset;
|
||||||
if (changeEnd == -1 || u.offset + u.size > changeEnd)
|
if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
|
||||||
changeEnd = u.offset + u.size;
|
changeEnd = u.offset + u.data.size();
|
||||||
}
|
}
|
||||||
vmaUnmapMemory(toVmaAllocator(allocator), a);
|
vmaUnmapMemory(toVmaAllocator(allocator), a);
|
||||||
if (changeBegin >= 0)
|
if (changeBegin >= 0)
|
||||||
|
@ -82,8 +82,7 @@ struct QVkBuffer : public QRhiBuffer
|
|||||||
QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
|
QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
|
||||||
struct DynamicUpdate {
|
struct DynamicUpdate {
|
||||||
int offset;
|
int offset;
|
||||||
int size;
|
QRhiBufferData data;
|
||||||
QByteArray data;
|
|
||||||
};
|
};
|
||||||
QVarLengthArray<DynamicUpdate, 16> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT];
|
QVarLengthArray<DynamicUpdate, 16> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT];
|
||||||
VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
|
VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
|
||||||
@ -98,6 +97,8 @@ struct QVkBuffer : public QRhiBuffer
|
|||||||
friend class QRhiVulkan;
|
friend class QRhiVulkan;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_TYPEINFO(QVkBuffer::DynamicUpdate, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
struct QVkTexture;
|
struct QVkTexture;
|
||||||
|
|
||||||
struct QVkRenderBuffer : public QRhiRenderBuffer
|
struct QVkRenderBuffer : public QRhiRenderBuffer
|
||||||
|
Loading…
Reference in New Issue
Block a user