From 0461c535fcb26ea231ee8645e67ef2e8d4429e95 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Oct 2020 19:29:00 +0200 Subject: rhi: Further reduce copying in the command buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2e2ff5f4b8aa91d0accb01108a5199b98c371455 Reviewed-by: Christian Strømme --- src/gui/rhi/qrhi_p_p.h | 32 ++++++++++++ src/gui/rhi/qrhid3d11.cpp | 116 +++++++++++++++++-------------------------- src/gui/rhi/qrhid3d11_p_p.h | 16 +++--- src/gui/rhi/qrhigles2.cpp | 114 +++++++++++++++--------------------------- src/gui/rhi/qrhigles2_p_p.h | 14 +++--- src/gui/rhi/qrhivulkan.cpp | 99 ++++++++++++++---------------------- src/gui/rhi/qrhivulkan_p_p.h | 7 ++- 7 files changed, 170 insertions(+), 228 deletions(-) (limited to 'src/gui/rhi') diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index 491f0c6f26..8a85227bae 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -655,6 +655,38 @@ private: Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_MOVABLE_TYPE); +template +class QRhiBackendCommandList +{ +public: + QRhiBackendCommandList() = default; + ~QRhiBackendCommandList() { delete v; } + inline void reset() { p = 0; } + inline bool isEmpty() const { return p == 0; } + inline T &get() { + if (p == a) { + a += GROW; + T *nv = new T[a]; + if (v) { + memcpy(nv, v, p * sizeof(T)); + delete[] v; + } + v = nv; + } + return v[p++]; + } + inline void unget() { --p; } + inline T *cbegin() const { return v; } + inline T *cend() const { return v + p; } + inline T *begin() { return v; } + inline T *end() { return v + p; } +private: + Q_DISABLE_COPY(QRhiBackendCommandList) + T *v = nullptr; + int a = 0; + int p = 0; +}; + QT_END_NAMESPACE #endif diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index ce954c9fe0..0db32e794f 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -649,10 +649,9 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline cbD->currentComputePipeline = nullptr; cbD->currentPipelineGeneration = psD->generation; - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::BindGraphicsPipeline; cmd.args.bindGraphicsPipeline.ps = psD; - cbD->commands.append(cmd); } } @@ -778,7 +777,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } cbD->currentSrbGeneration = srbD->generation; - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::BindShaderResources; cmd.args.bindShaderResources.srb = srbD; // dynamic offsets have to be applied at the time of executing the bind @@ -786,7 +785,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind cmd.args.bindShaderResources.offsetOnlyChange = !srbChanged && !srbRebuilt && !srbUpdate && srbD->hasDynamicOffset; cmd.args.bindShaderResources.dynamicOffsetCount = 0; if (srbD->hasDynamicOffset) { - if (dynamicOffsetCount < QD3D11CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT) { + if (dynamicOffsetCount < QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT) { cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount; uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs; for (int i = 0; i < dynamicOffsetCount; ++i) { @@ -799,11 +798,9 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } } else { qWarning("Too many dynamic offsets (%d, max is %d)", - dynamicOffsetCount, QD3D11CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT); + dynamicOffsetCount, QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT); } } - - cbD->commands.append(cmd); } } @@ -832,13 +829,13 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, } if (needsBindVBuf) { - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::BindVertexBuffers; cmd.args.bindVertexBuffers.startSlot = startBinding; - if (bindingCount > QD3D11CommandBuffer::Command::MAX_VERTEX_BUFFER_BINDING_COUNT) { + if (bindingCount > QD3D11CommandBuffer::MAX_VERTEX_BUFFER_BINDING_COUNT) { qWarning("Too many vertex buffer bindings (%d, max is %d)", - bindingCount, QD3D11CommandBuffer::Command::MAX_VERTEX_BUFFER_BINDING_COUNT); - bindingCount = QD3D11CommandBuffer::Command::MAX_VERTEX_BUFFER_BINDING_COUNT; + bindingCount, QD3D11CommandBuffer::MAX_VERTEX_BUFFER_BINDING_COUNT); + bindingCount = QD3D11CommandBuffer::MAX_VERTEX_BUFFER_BINDING_COUNT; } cmd.args.bindVertexBuffers.slotCount = bindingCount; QD3D11GraphicsPipeline *psD = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); @@ -850,7 +847,6 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, cmd.args.bindVertexBuffers.offsets[i] = bindings[i].second; cmd.args.bindVertexBuffers.strides[i] = inputLayout.bindingAt(i)->stride(); } - cbD->commands.append(cmd); } if (indexBuf) { @@ -869,12 +865,11 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb, cbD->currentIndexOffset = indexOffset; cbD->currentIndexFormat = dxgiFormat; - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::BindIndexBuffer; cmd.args.bindIndexBuffer.buffer = ibufD->buffer; cmd.args.bindIndexBuffer.offset = indexOffset; cmd.args.bindIndexBuffer.format = dxgiFormat; - cbD->commands.append(cmd); } } } @@ -886,21 +881,19 @@ void QRhiD3D11::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) Q_ASSERT(cbD->currentTarget); const QSize outputSize = cbD->currentTarget->pixelSize(); - QD3D11CommandBuffer::Command cmd; - cmd.cmd = QD3D11CommandBuffer::Command::Viewport; - // d3d expects top-left, QRhiViewport is bottom-left float x, y, w, h; if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h)) return; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); + cmd.cmd = QD3D11CommandBuffer::Command::Viewport; cmd.args.viewport.x = x; cmd.args.viewport.y = y; cmd.args.viewport.w = w; cmd.args.viewport.h = h; cmd.args.viewport.d0 = viewport.minDepth(); cmd.args.viewport.d1 = viewport.maxDepth(); - cbD->commands.append(cmd); } void QRhiD3D11::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) @@ -910,19 +903,17 @@ void QRhiD3D11::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) Q_ASSERT(cbD->currentTarget); const QSize outputSize = cbD->currentTarget->pixelSize(); - QD3D11CommandBuffer::Command cmd; - cmd.cmd = QD3D11CommandBuffer::Command::Scissor; - // d3d expects top-left, QRhiScissor is bottom-left int x, y, w, h; if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h)) return; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); + cmd.cmd = QD3D11CommandBuffer::Command::Scissor; cmd.args.scissor.x = x; cmd.args.scissor.y = y; cmd.args.scissor.w = w; cmd.args.scissor.h = h; - cbD->commands.append(cmd); } void QRhiD3D11::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) @@ -930,14 +921,13 @@ void QRhiD3D11::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::BlendConstants; cmd.args.blendConstants.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); cmd.args.blendConstants.c[0] = float(c.redF()); cmd.args.blendConstants.c[1] = float(c.greenF()); cmd.args.blendConstants.c[2] = float(c.blueF()); cmd.args.blendConstants.c[3] = float(c.alphaF()); - cbD->commands.append(cmd); } void QRhiD3D11::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) @@ -945,11 +935,10 @@ void QRhiD3D11::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::StencilRef; cmd.args.stencilRef.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); cmd.args.stencilRef.ref = refValue; - cbD->commands.append(cmd); } void QRhiD3D11::draw(QRhiCommandBuffer *cb, quint32 vertexCount, @@ -958,14 +947,13 @@ void QRhiD3D11::draw(QRhiCommandBuffer *cb, quint32 vertexCount, QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::Draw; cmd.args.draw.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); cmd.args.draw.vertexCount = vertexCount; cmd.args.draw.instanceCount = instanceCount; cmd.args.draw.firstVertex = firstVertex; cmd.args.draw.firstInstance = firstInstance; - cbD->commands.append(cmd); } void QRhiD3D11::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, @@ -974,7 +962,7 @@ void QRhiD3D11::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::RenderPass); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::DrawIndexed; cmd.args.drawIndexed.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline); cmd.args.drawIndexed.indexCount = indexCount; @@ -982,7 +970,6 @@ void QRhiD3D11::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, cmd.args.drawIndexed.firstIndex = firstIndex; cmd.args.drawIndexed.vertexOffset = vertexOffset; cmd.args.drawIndexed.firstInstance = firstInstance; - cbD->commands.append(cmd); } void QRhiD3D11::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) @@ -991,10 +978,9 @@ void QRhiD3D11::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) return; QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::DebugMarkBegin; qstrncpy(cmd.args.debugMark.s, name.constData(), sizeof(cmd.args.debugMark.s)); - cbD->commands.append(cmd); } void QRhiD3D11::debugMarkEnd(QRhiCommandBuffer *cb) @@ -1003,9 +989,8 @@ void QRhiD3D11::debugMarkEnd(QRhiCommandBuffer *cb) return; QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::DebugMarkEnd; - cbD->commands.append(cmd); } void QRhiD3D11::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) @@ -1014,10 +999,9 @@ void QRhiD3D11::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) return; QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::DebugMarkMsg; qstrncpy(cmd.args.debugMark.s, msg.constData(), sizeof(cmd.args.debugMark.s)); - cbD->commands.append(cmd); } const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb) @@ -1040,10 +1024,9 @@ void QRhiD3D11::endExternal(QRhiCommandBuffer *cb) Q_ASSERT(cbD->commands.isEmpty()); cbD->resetCachedState(); if (cbD->currentTarget) { // could be compute, no rendertarget then - QD3D11CommandBuffer::Command fbCmd; + QD3D11CommandBuffer::Command &fbCmd(cbD->commands.get()); fbCmd.cmd = QD3D11CommandBuffer::Command::SetRenderTarget; fbCmd.args.setRenderTarget.rt = cbD->currentTarget; - cbD->commands.append(fbCmd); } } @@ -1340,12 +1323,11 @@ void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cb box.front = 0; // back, right, bottom are exclusive box.back = 1; - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes; cmd.args.updateSubRes.dst = texD->tex; cmd.args.updateSubRes.dstSubRes = subres; - bool cmdValid = true; if (!subresDesc.image().isNull()) { QImage img = subresDesc.image(); QSize size = img.size(); @@ -1404,10 +1386,8 @@ void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cb cmd.args.updateSubRes.srcRowPitch = bpl; } else { qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level); - cmdValid = false; + cbD->commands.unget(); } - if (cmdValid) - cbD->commands.append(cmd); } void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) @@ -1427,7 +1407,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf); Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic); Q_ASSERT(u.offset + u.data.size() <= bufD->m_size); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::UpdateSubRes; cmd.args.updateSubRes.dst = bufD->buffer; cmd.args.updateSubRes.dstSubRes = 0; @@ -1443,7 +1423,6 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate 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.dstBox = box; - cbD->commands.append(cmd); } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) { QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf); if (bufD->m_type == QRhiBuffer::Dynamic) { @@ -1466,7 +1445,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate } QRHI_PROF_F(newReadbackBuffer(qint64(qintptr(readback.stagingBuf)), bufD, readback.byteSize)); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes; cmd.args.copySubRes.dst = readback.stagingBuf; cmd.args.copySubRes.dstSubRes = 0; @@ -1481,7 +1460,6 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate box.back = box.bottom = 1; box.right = UINT(u.offset + u.readSize); cmd.args.copySubRes.srcBox = box; - cbD->commands.append(cmd); activeBufferReadbacks.append(readback); } @@ -1517,7 +1495,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate srcBox.right = srcBox.left + UINT(copySize.width()); srcBox.bottom = srcBox.top + UINT(copySize.height()); srcBox.back = 1; - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes; cmd.args.copySubRes.dst = dstD->tex; cmd.args.copySubRes.dstSubRes = dstSubRes; @@ -1527,7 +1505,6 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate cmd.args.copySubRes.srcSubRes = srcSubRes; cmd.args.copySubRes.hasSrcBox = true; cmd.args.copySubRes.srcBox = srcBox; - cbD->commands.append(cmd); } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) { TextureReadback readback; readback.desc = u.rb; @@ -1557,14 +1534,13 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate if (swapChainD->sampleDesc.Count > 1) { // Unlike with textures, reading back a multisample swapchain image // has to be supported. Insert a resolve. - QD3D11CommandBuffer::Command rcmd; + QD3D11CommandBuffer::Command &rcmd(cbD->commands.get()); rcmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes; rcmd.args.resolveSubRes.dst = swapChainD->backBufferTex; rcmd.args.resolveSubRes.dstSubRes = 0; rcmd.args.resolveSubRes.src = swapChainD->msaaTex[swapChainD->currentFrameSlot]; rcmd.args.resolveSubRes.srcSubRes = 0; rcmd.args.resolveSubRes.format = swapChainD->colorFormat; - cbD->commands.append(rcmd); } src = swapChainD->backBufferTex; dxgiFormat = swapChainD->colorFormat; @@ -1597,7 +1573,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate texD ? static_cast(texD) : static_cast(swapChainD), byteSize)); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes; cmd.args.copySubRes.dst = stagingTex; cmd.args.copySubRes.dstSubRes = 0; @@ -1606,7 +1582,6 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate cmd.args.copySubRes.src = src; cmd.args.copySubRes.srcSubRes = subres; cmd.args.copySubRes.hasSrcBox = false; - cbD->commands.append(cmd); readback.stagingTex = stagingTex; readback.byteSize = byteSize; @@ -1617,10 +1592,9 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate activeTextureReadbacks.append(readback); } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::GenMips) { Q_ASSERT(u.dst->flags().testFlag(QRhiTexture::UsedWithGenerateMips)); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::GenMip; cmd.args.genMip.srv = QRHI_RES(QD3D11Texture, u.dst)->srv; - cbD->commands.append(cmd); } } @@ -1732,14 +1706,13 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb, wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents); } - QD3D11CommandBuffer::Command fbCmd; - fbCmd.cmd = QD3D11CommandBuffer::Command::ResetShaderResources; - cbD->commands.append(fbCmd); + cbD->commands.get().cmd = QD3D11CommandBuffer::Command::ResetShaderResources; + + QD3D11CommandBuffer::Command &fbCmd(cbD->commands.get()); fbCmd.cmd = QD3D11CommandBuffer::Command::SetRenderTarget; fbCmd.args.setRenderTarget.rt = rt; - cbD->commands.append(fbCmd); - QD3D11CommandBuffer::Command clearCmd; + QD3D11CommandBuffer::Command &clearCmd(cbD->commands.get()); clearCmd.cmd = QD3D11CommandBuffer::Command::Clear; clearCmd.args.clear.rt = rt; clearCmd.args.clear.mask = 0; @@ -1754,7 +1727,6 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb, clearCmd.args.clear.c[3] = float(colorClearValue.alphaF()); clearCmd.args.clear.d = depthStencilClearValue.depthClearValue(); clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue(); - cbD->commands.append(clearCmd); cbD->recordingPass = QD3D11CommandBuffer::RenderPass; cbD->currentTarget = rt; @@ -1780,7 +1752,7 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource QD3D11Texture *srcTexD = QRHI_RES(QD3D11Texture, colorAtt.texture()); QD3D11RenderBuffer *srcRbD = QRHI_RES(QD3D11RenderBuffer, colorAtt.renderBuffer()); Q_ASSERT(srcTexD || srcRbD); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes; cmd.args.resolveSubRes.dst = dstTexD->tex; cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()), @@ -1791,14 +1763,17 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) { qWarning("Resolve source (%d) and destination (%d) formats do not match", int(srcTexD->dxgiFormat), int(dstTexD->dxgiFormat)); + cbD->commands.unget(); continue; } if (srcTexD->sampleDesc.Count <= 1) { qWarning("Cannot resolve a non-multisample texture"); + cbD->commands.unget(); continue; } if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) { qWarning("Resolve source and destination sizes do not match"); + cbD->commands.unget(); continue; } } else { @@ -1806,16 +1781,17 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) { qWarning("Resolve source (%d) and destination (%d) formats do not match", int(srcRbD->dxgiFormat), int(dstTexD->dxgiFormat)); + cbD->commands.unget(); continue; } if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) { qWarning("Resolve source and destination sizes do not match"); + cbD->commands.unget(); continue; } } cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1); cmd.args.resolveSubRes.format = dstTexD->dxgiFormat; - cbD->commands.append(cmd); } } @@ -1836,9 +1812,8 @@ void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb, if (resourceUpdates) enqueueResourceUpdates(cb, resourceUpdates); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::ResetShaderResources; - cbD->commands.append(cmd); cbD->recordingPass = QD3D11CommandBuffer::ComputePass; @@ -1868,10 +1843,9 @@ void QRhiD3D11::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *p cbD->currentComputePipeline = psD; cbD->currentPipelineGeneration = psD->generation; - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::BindComputePipeline; cmd.args.bindComputePipeline.ps = psD; - cbD->commands.append(cmd); } } @@ -1880,12 +1854,11 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::ComputePass); - QD3D11CommandBuffer::Command cmd; + QD3D11CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QD3D11CommandBuffer::Command::Dispatch; cmd.args.dispatch.x = UINT(x); cmd.args.dispatch.y = UINT(y); cmd.args.dispatch.z = UINT(z); - cbD->commands.append(cmd); } static inline QPair mapBinding(int binding, @@ -2214,7 +2187,7 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, const uint *dynOfsPairs, int dynOfsPairCount, bool offsetOnlyChange) { - UINT offsets[QD3D11CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT]; + UINT offsets[QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT]; if (srbD->vsubufsPresent) { for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) { @@ -2448,7 +2421,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain * } } - for (const QD3D11CommandBuffer::Command &cmd : qAsConst(cbD->commands)) { + for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) { + const QD3D11CommandBuffer::Command &cmd(*it); switch (cmd.cmd) { case QD3D11CommandBuffer::Command::ResetShaderResources: resetShaderResources(); diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 1572751e6c..ff62327bdf 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -326,6 +326,10 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer ~QD3D11CommandBuffer(); void destroy() override; + // these must be kept at a reasonably low value otherwise sizeof Command explodes + static const int MAX_DYNAMIC_OFFSET_COUNT = 8; + static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8; + struct Command { enum Cmd { ResetShaderResources, @@ -354,13 +358,9 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 }; Cmd cmd; - // these must be kept at a reasonably low value otherwise sizeof Command explodes - static const int MAX_DYNAMIC_OFFSET_COUNT = 8; - static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8; - // QRhi*/QD3D11* references should be kept at minimum (so no // QRhiTexture/Buffer/etc. pointers). - union { + union Args { struct { QRhiRenderTarget *rt; } setRenderTarget; @@ -470,7 +470,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer ComputePass }; - QVarLengthArray commands; + QRhiBackendCommandList commands; PassType recordingPass; QRhiRenderTarget *currentTarget; QRhiGraphicsPipeline *currentGraphicsPipeline; @@ -503,7 +503,7 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer return imageRetainPool.last().constBits(); } void resetCommands() { - commands.clear(); + commands.reset(); dataRetainPool.clear(); bufferDataRetainPool.clear(); imageRetainPool.clear(); @@ -532,8 +532,6 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer } }; -Q_DECLARE_TYPEINFO(QD3D11CommandBuffer::Command, Q_MOVABLE_TYPE); - struct QD3D11SwapChain : public QRhiSwapChain { QD3D11SwapChain(QRhiImplementation *rhi); diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 39f03a784f..785c341a0f 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1072,10 +1072,9 @@ void QRhiGles2::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline cbD->currentComputePipeline = nullptr; cbD->currentPipelineGeneration = psD->generation; - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BindGraphicsPipeline; cmd.args.bindGraphicsPipeline.ps = ps; - cbD->commands.append(cmd); } } @@ -1151,9 +1150,7 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb); - const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation; - - if (srbChanged || srbRebuilt || srbD->hasDynamicOffset) { + if (srbChanged || cbD->currentSrbGeneration != srbD->generation || srbD->hasDynamicOffset) { if (gfxPsD) { cbD->currentGraphicsSrb = srb; cbD->currentComputeSrb = nullptr; @@ -1163,14 +1160,14 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } cbD->currentSrbGeneration = srbD->generation; - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BindShaderResources; cmd.args.bindShaderResources.maybeGraphicsPs = gfxPsD; cmd.args.bindShaderResources.maybeComputePs = compPsD; cmd.args.bindShaderResources.srb = srb; cmd.args.bindShaderResources.dynamicOffsetCount = 0; if (srbD->hasDynamicOffset) { - if (dynamicOffsetCount < QGles2CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT) { + if (dynamicOffsetCount < QGles2CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT) { cmd.args.bindShaderResources.dynamicOffsetCount = dynamicOffsetCount; uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs; for (int i = 0; i < dynamicOffsetCount; ++i) { @@ -1180,10 +1177,9 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } } else { qWarning("Too many dynamic offsets (%d, max is %d)", - dynamicOffsetCount, QGles2CommandBuffer::Command::MAX_DYNAMIC_OFFSET_COUNT); + dynamicOffsetCount, QGles2CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT); } } - cbD->commands.append(cmd); } } @@ -1201,13 +1197,12 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb, QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, buf); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer)); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BindVertexBuffer; cmd.args.bindVertexBuffer.ps = cbD->currentGraphicsPipeline; cmd.args.bindVertexBuffer.buffer = bufD->buffer; cmd.args.bindVertexBuffer.offset = ofs; cmd.args.bindVertexBuffer.binding = startBinding + i; - cbD->commands.append(cmd); if (cbD->passNeedsResourceTracking) { trackedRegisterBuffer(&passResTracker, bufD, QRhiPassResourceTracker::BufVertexInput, @@ -1219,12 +1214,11 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb, QGles2Buffer *ibufD = QRHI_RES(QGles2Buffer, indexBuf); Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer)); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BindIndexBuffer; cmd.args.bindIndexBuffer.buffer = ibufD->buffer; cmd.args.bindIndexBuffer.offset = indexOffset; cmd.args.bindIndexBuffer.type = indexFormat == QRhiCommandBuffer::IndexUInt16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - cbD->commands.append(cmd); if (cbD->passNeedsResourceTracking) { trackedRegisterBuffer(&passResTracker, ibufD, QRhiPassResourceTracker::BufIndexRead, @@ -1238,20 +1232,19 @@ void QRhiGles2::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - QGles2CommandBuffer::Command cmd; - cmd.cmd = QGles2CommandBuffer::Command::Viewport; const std::array r = viewport.viewport(); // A negative width or height is an error. A negative x or y is not. if (r[2] < 0.0f || r[3] < 0.0f) return; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); + cmd.cmd = QGles2CommandBuffer::Command::Viewport; cmd.args.viewport.x = r[0]; cmd.args.viewport.y = r[1]; cmd.args.viewport.w = r[2]; cmd.args.viewport.h = r[3]; cmd.args.viewport.d0 = viewport.minDepth(); cmd.args.viewport.d1 = viewport.maxDepth(); - cbD->commands.append(cmd); } void QRhiGles2::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) @@ -1259,18 +1252,17 @@ void QRhiGles2::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - QGles2CommandBuffer::Command cmd; - cmd.cmd = QGles2CommandBuffer::Command::Scissor; const std::array r = scissor.scissor(); // A negative width or height is an error. A negative x or y is not. if (r[2] < 0 || r[3] < 0) return; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); + cmd.cmd = QGles2CommandBuffer::Command::Scissor; cmd.args.scissor.x = r[0]; cmd.args.scissor.y = r[1]; cmd.args.scissor.w = r[2]; cmd.args.scissor.h = r[3]; - cbD->commands.append(cmd); } void QRhiGles2::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) @@ -1278,13 +1270,12 @@ void QRhiGles2::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BlendConstants; cmd.args.blendConstants.r = float(c.redF()); cmd.args.blendConstants.g = float(c.greenF()); cmd.args.blendConstants.b = float(c.blueF()); cmd.args.blendConstants.a = float(c.alphaF()); - cbD->commands.append(cmd); } void QRhiGles2::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) @@ -1292,11 +1283,10 @@ void QRhiGles2::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::StencilRef; cmd.args.stencilRef.ref = refValue; cmd.args.stencilRef.ps = cbD->currentGraphicsPipeline; - cbD->commands.append(cmd); } void QRhiGles2::draw(QRhiCommandBuffer *cb, quint32 vertexCount, @@ -1305,14 +1295,13 @@ void QRhiGles2::draw(QRhiCommandBuffer *cb, quint32 vertexCount, QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::Draw; cmd.args.draw.ps = cbD->currentGraphicsPipeline; cmd.args.draw.vertexCount = vertexCount; cmd.args.draw.firstVertex = firstVertex; cmd.args.draw.instanceCount = instanceCount; cmd.args.draw.baseInstance = firstInstance; - cbD->commands.append(cmd); } void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, @@ -1321,7 +1310,7 @@ void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::DrawIndexed; cmd.args.drawIndexed.ps = cbD->currentGraphicsPipeline; cmd.args.drawIndexed.indexCount = indexCount; @@ -1329,7 +1318,6 @@ void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, cmd.args.drawIndexed.instanceCount = instanceCount; cmd.args.drawIndexed.baseInstance = firstInstance; cmd.args.drawIndexed.baseVertex = vertexOffset; - cbD->commands.append(cmd); } void QRhiGles2::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) @@ -1364,11 +1352,10 @@ const QRhiNativeHandles *QRhiGles2::nativeHandles(QRhiCommandBuffer *cb) return nullptr; } -static void addBoundaryCommand(QGles2CommandBuffer *cbD, QGles2CommandBuffer::Command::Cmd type) +static inline void addBoundaryCommand(QGles2CommandBuffer *cbD, QGles2CommandBuffer::Command::Cmd type) { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = type; - cbD->commands.append(cmd); } void QRhiGles2::beginExternal(QRhiCommandBuffer *cb) @@ -1388,10 +1375,9 @@ void QRhiGles2::beginExternal(QRhiCommandBuffer *cb) if (cbD->recordingPass == QGles2CommandBuffer::ComputePass && !cbD->computePassState.writtenResources.isEmpty()) { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::Barrier; cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; - cbD->commands.append(cmd); } executeCommandBuffer(cbD); @@ -1551,10 +1537,9 @@ void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *buf // correctly (prevAccess is overwritten so we won't have proper // tracking across multiple passes) so setting all barrier bits will do // for now. - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::Barrier; cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; - cbD->commands.append(cmd); } bufD->usageState.access = access; @@ -1568,10 +1553,9 @@ void QRhiGles2::trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *tex return; if (textureAccessIsWrite(prevAccess)) { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::Barrier; cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; - cbD->commands.append(cmd); } texD->usageState.access = access; @@ -1589,7 +1573,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb if (!subresDesc.image().isNull()) { QImage img = subresDesc.image(); QSize size = img.size(); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::SubImage; if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) { const QPoint sp = subresDesc.sourceTopLeft(); @@ -1609,14 +1593,13 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb cmd.args.subImage.gltype = texD->gltype; cmd.args.subImage.rowStartAlign = 4; cmd.args.subImage.data = cbD->retainImage(img); - cbD->commands.append(cmd); } else if (!rawData.isEmpty() && isCompressed) { if (!texD->compressedAtlasBuilt && (texD->flags() & QRhiTexture::UsedAsCompressedAtlas)) { // Create on first upload since glCompressedTexImage2D cannot take nullptr data quint32 byteSize = 0; compressedFormatInfo(texD->m_format, texD->m_pixelSize, nullptr, &byteSize, nullptr); QByteArray zeroBuf(byteSize, 0); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::CompressedImage; cmd.args.compressedImage.target = texD->target; cmd.args.compressedImage.texture = texD->texture; @@ -1627,14 +1610,13 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb cmd.args.compressedImage.h = texD->m_pixelSize.height(); cmd.args.compressedImage.size = byteSize; cmd.args.compressedImage.data = cbD->retainData(zeroBuf); - cbD->commands.append(cmd); texD->compressedAtlasBuilt = true; } const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize) : subresDesc.sourceSize(); if (texD->specified || texD->compressedAtlasBuilt) { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::CompressedSubImage; cmd.args.compressedSubImage.target = texD->target; cmd.args.compressedSubImage.texture = texD->texture; @@ -1647,9 +1629,8 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb cmd.args.compressedSubImage.glintformat = texD->glintformat; cmd.args.compressedSubImage.size = rawData.size(); cmd.args.compressedSubImage.data = cbD->retainData(rawData); - cbD->commands.append(cmd); } else { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::CompressedImage; cmd.args.compressedImage.target = texD->target; cmd.args.compressedImage.texture = texD->texture; @@ -1660,14 +1641,13 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb cmd.args.compressedImage.h = size.height(); cmd.args.compressedImage.size = rawData.size(); cmd.args.compressedImage.data = cbD->retainData(rawData); - cbD->commands.append(cmd); } } else if (!rawData.isEmpty()) { const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize) : subresDesc.sourceSize(); quint32 bpl = 0; textureFormatInfo(texD->m_format, size, &bpl, nullptr); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::SubImage; cmd.args.subImage.target = texD->target; cmd.args.subImage.texture = texD->texture; @@ -1684,7 +1664,6 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb // row starts, but our raw data here does not. cmd.args.subImage.rowStartAlign = (bpl & 3) ? 1 : 4; cmd.args.subImage.data = cbD->retainData(rawData); - cbD->commands.append(cmd); } else { qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level); } @@ -1704,14 +1683,13 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate memcpy(bufD->data + u.offset, u.data.constData(), size_t(u.data.size())); } else { trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BufferSubData; cmd.args.bufferSubData.target = bufD->targetForDataOps; cmd.args.bufferSubData.buffer = bufD->buffer; cmd.args.bufferSubData.offset = u.offset; cmd.args.bufferSubData.size = u.data.size(); cmd.args.bufferSubData.data = cbD->retainBufferData(u.data); - cbD->commands.append(cmd); } } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) { QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf); @@ -1721,14 +1699,13 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate memcpy(bufD->data + u.offset, u.data.constData(), size_t(u.data.size())); } else { trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BufferSubData; cmd.args.bufferSubData.target = bufD->targetForDataOps; cmd.args.bufferSubData.buffer = bufD->buffer; cmd.args.bufferSubData.offset = u.offset; cmd.args.bufferSubData.size = u.data.size(); cmd.args.bufferSubData.data = cbD->retainBufferData(u.data); - cbD->commands.append(cmd); } } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) { QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf); @@ -1738,14 +1715,13 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate if (u.result->completed) u.result->completed(); } else { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::GetBufferSubData; cmd.args.getBufferSubData.result = u.result; cmd.args.getBufferSubData.target = bufD->targetForDataOps; cmd.args.getBufferSubData.buffer = bufD->buffer; cmd.args.getBufferSubData.offset = u.offset; cmd.args.getBufferSubData.size = u.readSize; - cbD->commands.append(cmd); } } } @@ -1780,7 +1756,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate const GLenum dstFaceTargetBase = dstD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : dstD->target; - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::CopyTex; cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + uint(u.desc.sourceLayer()); @@ -1798,10 +1774,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate cmd.args.copyTex.w = copySize.width(); cmd.args.copyTex.h = copySize.height(); - - cbD->commands.append(cmd); } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::ReadPixels; cmd.args.readPixels.result = u.result; QGles2Texture *texD = QRHI_RES(QGles2Texture, u.rb.texture()); @@ -1818,15 +1792,13 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate cmd.args.readPixels.readTarget = faceTargetBase + uint(u.rb.layer()); cmd.args.readPixels.level = u.rb.level(); } - cbD->commands.append(cmd); } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::GenMips) { QGles2Texture *texD = QRHI_RES(QGles2Texture, u.dst); trackedImageBarrier(cbD, texD, QGles2Texture::AccessFramebuffer); - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::GenMip; cmd.args.genMip.target = texD->target; cmd.args.genMip.texture = texD->texture; - cbD->commands.append(cmd); } } @@ -2166,7 +2138,8 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) bool enabledAttribArrays[TRACKED_ATTRIB_COUNT]; memset(enabledAttribArrays, 0, sizeof(enabledAttribArrays)); - for (const QGles2CommandBuffer::Command &cmd : qAsConst(cbD->commands)) { + for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) { + const QGles2CommandBuffer::Command &cmd(*it); switch (cmd.cmd) { case QGles2CommandBuffer::Command::BeginFrame: if (caps.coreProfile) { @@ -3194,7 +3167,7 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2RenderTargetData *rtD = nullptr; QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]); - QGles2CommandBuffer::Command fbCmd; + QGles2CommandBuffer::Command &fbCmd(cbD->commands.get()); fbCmd.cmd = QGles2CommandBuffer::Command::BindFramebuffer; switch (rt->resourceType()) { @@ -3250,7 +3223,6 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, } fbCmd.args.bindFramebuffer.srgb = rtD->srgbUpdateAndBlend; - cbD->commands.append(fbCmd); return rtD; } @@ -3259,10 +3231,9 @@ void QRhiGles2::enqueueBarriersForPass(QGles2CommandBuffer *cbD) { cbD->passResTrackers.append(QRhiPassResourceTracker()); cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass; cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex; - cbD->commands.append(cmd); } void QRhiGles2::beginPass(QRhiCommandBuffer *cb, @@ -3285,7 +3256,7 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, bool wantsColorClear, wantsDsClear; QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear); - QGles2CommandBuffer::Command clearCmd; + QGles2CommandBuffer::Command &clearCmd(cbD->commands.get()); clearCmd.cmd = QGles2CommandBuffer::Command::Clear; clearCmd.args.clear.mask = 0; if (rtD->colorAttCount && wantsColorClear) @@ -3298,7 +3269,6 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, clearCmd.args.clear.c[3] = float(colorClearValue.alphaF()); clearCmd.args.clear.d = depthStencilClearValue.depthClearValue(); clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue(); - cbD->commands.append(clearCmd); cbD->recordingPass = QGles2CommandBuffer::RenderPass; cbD->passNeedsResourceTracking = !flags.testFlag(QRhiCommandBuffer::DoNotTrackResourcesForCompute); @@ -3325,7 +3295,7 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource qWarning("Resolve source (%dx%d) and target (%dx%d) size does not match", rbD->pixelSize().width(), rbD->pixelSize().height(), size.width(), size.height()); } - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer; cmd.args.blitFromRb.renderbuffer = rbD->renderbuffer; cmd.args.blitFromRb.w = size.width(); @@ -3336,7 +3306,6 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource cmd.args.blitFromRb.target = faceTargetBase + uint(colorAtt.resolveLayer()); cmd.args.blitFromRb.texture = colorTexD->texture; cmd.args.blitFromRb.dstLevel = colorAtt.resolveLevel(); - cbD->commands.append(cmd); } } } @@ -3388,10 +3357,9 @@ void QRhiGles2::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *p cbD->currentComputePipeline = ps; cbD->currentPipelineGeneration = psD->generation; - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::BindComputePipeline; cmd.args.bindComputePipeline.ps = ps; - cbD->commands.append(cmd); } } @@ -3478,19 +3446,17 @@ void QRhiGles2::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) } if (barriers) { - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::Barrier; cmd.args.barrier.barriers = barriers; - cbD->commands.append(cmd); } } - QGles2CommandBuffer::Command cmd; + QGles2CommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QGles2CommandBuffer::Command::Dispatch; cmd.args.dispatch.x = GLuint(x); cmd.args.dispatch.y = GLuint(y); cmd.args.dispatch.z = GLuint(z); - cbD->commands.append(cmd); } static inline GLenum toGlShaderType(QRhiShaderStage::Type type) diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 6ce3786445..a231740c66 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -315,6 +315,9 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer ~QGles2CommandBuffer(); void destroy() override; + // keep at a reasonably low value otherwise sizeof Command explodes + static const int MAX_DYNAMIC_OFFSET_COUNT = 8; + struct Command { enum Cmd { BeginFrame, @@ -348,12 +351,9 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer }; Cmd cmd; - // keep at a reasonably low value otherwise sizeof Command explodes - static const int MAX_DYNAMIC_OFFSET_COUNT = 8; - // QRhi*/QGles2* references should be kept at minimum (so no // QRhiTexture/Buffer/etc. pointers). - union { + union Args { struct { float x, y, w, h; float d0, d1; @@ -526,7 +526,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer ComputePass }; - QVarLengthArray commands; + QRhiBackendCommandList commands; QVarLengthArray passResTrackers; int currentPassResTrackerIndex; @@ -614,7 +614,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer return imageRetainPool.last().constBits(); } void resetCommands() { - commands.clear(); + commands.reset(); dataRetainPool.clear(); bufferDataRetainPool.clear(); imageRetainPool.clear(); @@ -642,8 +642,6 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer } }; -Q_DECLARE_TYPEINFO(QGles2CommandBuffer::Command, Q_MOVABLE_TYPE); - inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) { diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index fc539c03a9..f867781d8b 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -2204,10 +2204,9 @@ void QRhiVulkan::endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkComm if (err != VK_SUCCESS) qWarning("Failed to end secondary command buffer: %d", err); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::ExecuteSecondary; cmd.args.executeSecondary.cb = cb; - cbD->commands.append(cmd); QRhiVulkan::DeferredReleaseEntry e; e.type = QRhiVulkan::DeferredReleaseEntry::SecondaryCommandBuffer; @@ -2291,13 +2290,12 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb, } rpBeginInfo.clearValueCount = uint32_t(cvs.count()); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BeginRenderPass; cmd.args.beginRenderPass.desc = rpBeginInfo; cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.count(); cmd.args.beginRenderPass.useSecondaryCb = cbD->passUsesSecondaryCb; cbD->pools.clearValue.append(cvs.constData(), cvs.count()); - cbD->commands.append(cmd); if (cbD->passUsesSecondaryCb) cbD->activeSecondaryCbStack.append(startSecondaryCommandBuffer(rtD)); @@ -2315,9 +2313,8 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc cbD->resetCachedState(); } - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::EndRenderPass; - cbD->commands.append(cmd); cbD->recordingPass = QVkCommandBuffer::NoPass; cbD->currentTarget = nullptr; @@ -2376,11 +2373,10 @@ void QRhiVulkan::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline * if (cbD->passUsesSecondaryCb) { df->vkCmdBindPipeline(cbD->activeSecondaryCbStack.last(), VK_PIPELINE_BIND_POINT_COMPUTE, psD->pipeline); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BindPipeline; cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; cmd.args.bindPipeline.pipeline = psD->pipeline; - cbD->commands.append(cmd); } cbD->currentGraphicsPipeline = nullptr; @@ -2518,30 +2514,29 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) } df->vkCmdDispatch(secondaryCb, uint32_t(x), uint32_t(y), uint32_t(z)); } else { - QVkCommandBuffer::Command cmd; if (!imageBarriers.isEmpty()) { + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::ImageBarrier; cmd.args.imageBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; cmd.args.imageBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; cmd.args.imageBarrier.count = imageBarriers.count(); cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count(); cbD->pools.imageBarrier.append(imageBarriers.constData(), imageBarriers.count()); - cbD->commands.append(cmd); } if (!bufferBarriers.isEmpty()) { + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BufferBarrier; cmd.args.bufferBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; cmd.args.bufferBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; cmd.args.bufferBarrier.count = bufferBarriers.count(); cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.count(); cbD->pools.bufferBarrier.append(bufferBarriers.constData(), bufferBarriers.count()); - cbD->commands.append(cmd); } + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::Dispatch; cmd.args.dispatch.x = x; cmd.args.dispatch.y = y; cmd.args.dispatch.z = z; - cbD->commands.append(cmd); } } @@ -2741,14 +2736,13 @@ void QRhiVulkan::trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, in bufMemBarrier.buffer = bufD->buffers[slot]; bufMemBarrier.size = VK_WHOLE_SIZE; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BufferBarrier; cmd.args.bufferBarrier.srcStageMask = s.stage; cmd.args.bufferBarrier.dstStageMask = stage; cmd.args.bufferBarrier.count = 1; cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.count(); cbD->pools.bufferBarrier.append(bufMemBarrier); - cbD->commands.append(cmd); s.access = access; s.stage = stage; @@ -2784,14 +2778,13 @@ void QRhiVulkan::trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD, if (!srcStage) srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::ImageBarrier; cmd.args.imageBarrier.srcStageMask = srcStage; cmd.args.imageBarrier.dstStageMask = stage; cmd.args.imageBarrier.count = 1; cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count(); cbD->pools.imageBarrier.append(barrier); - cbD->commands.append(cmd); s.layout = layout; s.access = access; @@ -2820,14 +2813,13 @@ void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image, barrier.dstAccessMask = dstAccess; barrier.image = image; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::ImageBarrier; cmd.args.imageBarrier.srcStageMask = srcStage; cmd.args.imageBarrier.dstStageMask = dstStage; cmd.args.imageBarrier.count = 1; cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count(); cbD->pools.imageBarrier.append(barrier); - cbD->commands.append(cmd); } VkDeviceSize QRhiVulkan::subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const @@ -3000,12 +2992,11 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat copyInfo.dstOffset = VkDeviceSize(u.offset); copyInfo.size = VkDeviceSize(u.data.size()); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::CopyBuffer; cmd.args.copyBuffer.src = bufD->stagingBuffers[currentFrameSlot]; cmd.args.copyBuffer.dst = bufD->buffers[0]; cmd.args.copyBuffer.desc = copyInfo; - cbD->commands.append(cmd); // Where's the barrier for read-after-write? (assuming the common case // of binding this buffer as vertex/index, or, less likely, as uniform @@ -3080,12 +3071,11 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat copyInfo.srcOffset = VkDeviceSize(u.offset); copyInfo.size = VkDeviceSize(u.readSize); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::CopyBuffer; cmd.args.copyBuffer.src = bufD->buffers[0]; cmd.args.copyBuffer.dst = readback.stagingBuf; cmd.args.copyBuffer.desc = copyInfo; - cbD->commands.append(cmd); bufD->lastActiveFrameSlot = currentFrameSlot; @@ -3155,7 +3145,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat trackedImageBarrier(cbD, utexD, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::CopyBufferToImage; cmd.args.copyBufferToImage.src = utexD->stagingBuffers[currentFrameSlot]; cmd.args.copyBufferToImage.dst = utexD->image; @@ -3163,7 +3153,6 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat cmd.args.copyBufferToImage.count = copyInfos.count(); cmd.args.copyBufferToImage.bufferImageCopyIndex = cbD->pools.bufferImageCopy.count(); cbD->pools.bufferImageCopy.append(copyInfos.constData(), copyInfos.count()); - cbD->commands.append(cmd); // no reuse of staging, this is intentional QRhiVulkan::DeferredReleaseEntry e; @@ -3219,14 +3208,13 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat trackedImageBarrier(cbD, dstD, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::CopyImage; cmd.args.copyImage.src = srcD->image; cmd.args.copyImage.srcLayout = srcD->usageState.layout; cmd.args.copyImage.dst = dstD->image; cmd.args.copyImage.dstLayout = dstD->usageState.layout; cmd.args.copyImage.desc = region; - cbD->commands.append(cmd); srcD->lastActiveFrameSlot = dstD->lastActiveFrameSlot = currentFrameSlot; } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) { @@ -3300,13 +3288,12 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat if (texD) { trackedImageBarrier(cbD, texD, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::CopyImageToBuffer; cmd.args.copyImageToBuffer.src = texD->image; cmd.args.copyImageToBuffer.srcLayout = texD->usageState.layout; cmd.args.copyImageToBuffer.dst = readback.stagingBuf; cmd.args.copyImageToBuffer.desc = copyDesc; - cbD->commands.append(cmd); } else { // use the swapchain image QVkSwapChain::ImageResources &imageRes(swapChainD->imageRes[swapChainD->currentImageIndex]); @@ -3325,13 +3312,12 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat imageRes.lastUse = QVkSwapChain::ImageResources::ScImageUseTransferSource; } - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::CopyImageToBuffer; cmd.args.copyImageToBuffer.src = image; cmd.args.copyImageToBuffer.srcLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; cmd.args.copyImageToBuffer.dst = readback.stagingBuf; cmd.args.copyImageToBuffer.desc = copyDesc; - cbD->commands.append(cmd); } activeTextureReadbacks.append(readback); @@ -3394,7 +3380,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat region.dstOffsets[1].y = qMax(1, h >> 1); region.dstOffsets[1].z = 1; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BlitImage; cmd.args.blitImage.src = utexD->image; cmd.args.blitImage.srcLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; @@ -3402,7 +3388,6 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat cmd.args.blitImage.dstLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; cmd.args.blitImage.filter = VK_FILTER_LINEAR; cmd.args.blitImage.desc = region; - cbD->commands.append(cmd); w >>= 1; h >>= 1; @@ -3665,17 +3650,17 @@ void QRhiVulkan::enqueueTransitionPassResources(QVkCommandBuffer *cbD) cbD->passResTrackers.append(QRhiPassResourceTracker()); cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::TransitionPassResources; cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.count() - 1; - cbD->commands.append(cmd); } void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD) { Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass); - for (QVkCommandBuffer::Command &cmd : cbD->commands) { + for (auto it = cbD->commands.begin(), end = cbD->commands.end(); it != end; ++it) { + QVkCommandBuffer::Command &cmd(*it); switch (cmd.cmd) { case QVkCommandBuffer::Command::CopyBuffer: df->vkCmdCopyBuffer(cbD->cb, cmd.args.copyBuffer.src, cmd.args.copyBuffer.dst, @@ -4264,11 +4249,10 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline if (cbD->passUsesSecondaryCb) { df->vkCmdBindPipeline(cbD->activeSecondaryCbStack.last(), VK_PIPELINE_BIND_POINT_GRAPHICS, psD->pipeline); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BindPipeline; cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; cmd.args.bindPipeline.pipeline = psD->pipeline; - cbD->commands.append(cmd); } cbD->currentGraphicsPipeline = ps; @@ -4461,7 +4445,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin uint32_t(dynOfs.count()), dynOfs.count() ? dynOfs.constData() : nullptr); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BindDescriptorSet; cmd.args.bindDescriptorSet.bindPoint = gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE; @@ -4470,7 +4454,6 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin cmd.args.bindDescriptorSet.dynamicOffsetCount = dynOfs.count(); cmd.args.bindDescriptorSet.dynamicOffsetIndex = cbD->pools.dynamicOffset.count(); cbD->pools.dynamicOffset.append(dynOfs.constData(), dynOfs.count()); - cbD->commands.append(cmd); } if (gfxPsD) { @@ -4531,7 +4514,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, df->vkCmdBindVertexBuffers(cbD->activeSecondaryCbStack.last(), uint32_t(startBinding), uint32_t(bufs.count()), bufs.constData(), ofs.constData()); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BindVertexBuffer; cmd.args.bindVertexBuffer.startBinding = startBinding; cmd.args.bindVertexBuffer.count = bufs.count(); @@ -4539,7 +4522,6 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, cbD->pools.vertexBuffer.append(bufs.constData(), bufs.count()); cmd.args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->pools.vertexBufferOffset.count(); cbD->pools.vertexBufferOffset.append(ofs.constData(), ofs.count()); - cbD->commands.append(cmd); } } @@ -4566,12 +4548,11 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, if (cbD->passUsesSecondaryCb) { df->vkCmdBindIndexBuffer(cbD->activeSecondaryCbStack.last(), vkindexbuf, indexOffset, type); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::BindIndexBuffer; cmd.args.bindIndexBuffer.buf = vkindexbuf; cmd.args.bindIndexBuffer.ofs = indexOffset; cmd.args.bindIndexBuffer.type = type; - cbD->commands.append(cmd); } trackedRegisterBuffer(&passResTracker, ibufD, slot, @@ -4592,7 +4573,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h)) return; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); VkViewport *vp = &cmd.args.setViewport.viewport; vp->x = x; vp->y = y; @@ -4603,12 +4584,13 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport if (cbD->passUsesSecondaryCb) { df->vkCmdSetViewport(cbD->activeSecondaryCbStack.last(), 0, 1, vp); + cbD->commands.unget(); } else { cmd.cmd = QVkCommandBuffer::Command::SetViewport; - cbD->commands.append(cmd); } if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) { + QVkCommandBuffer::Command &cmd(cbD->commands.get()); VkRect2D *s = &cmd.args.setScissor.scissor; s->offset.x = int32_t(x); s->offset.y = int32_t(y); @@ -4616,9 +4598,9 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport s->extent.height = uint32_t(h); if (cbD->passUsesSecondaryCb) { df->vkCmdSetScissor(cbD->activeSecondaryCbStack.last(), 0, 1, s); + cbD->commands.unget(); } else { cmd.cmd = QVkCommandBuffer::Command::SetScissor; - cbD->commands.append(cmd); } } } @@ -4635,7 +4617,7 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h)) return; - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); VkRect2D *s = &cmd.args.setScissor.scissor; s->offset.x = x; s->offset.y = y; @@ -4644,9 +4626,9 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) if (cbD->passUsesSecondaryCb) { df->vkCmdSetScissor(cbD->activeSecondaryCbStack.last(), 0, 1, s); + cbD->commands.unget(); } else { cmd.cmd = QVkCommandBuffer::Command::SetScissor; - cbD->commands.append(cmd); } } @@ -4659,13 +4641,12 @@ void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) float constants[] = { float(c.redF()), float(c.greenF()), float(c.blueF()), float(c.alphaF()) }; df->vkCmdSetBlendConstants(cbD->activeSecondaryCbStack.last(), constants); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::SetBlendConstants; cmd.args.setBlendConstants.c[0] = float(c.redF()); cmd.args.setBlendConstants.c[1] = float(c.greenF()); cmd.args.setBlendConstants.c[2] = float(c.blueF()); cmd.args.setBlendConstants.c[3] = float(c.alphaF()); - cbD->commands.append(cmd); } } @@ -4677,10 +4658,9 @@ void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) if (cbD->passUsesSecondaryCb) { df->vkCmdSetStencilReference(cbD->activeSecondaryCbStack.last(), VK_STENCIL_FRONT_AND_BACK, refValue); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::SetStencilRef; cmd.args.setStencilRef.ref = refValue; - cbD->commands.append(cmd); } } @@ -4693,13 +4673,12 @@ void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount, if (cbD->passUsesSecondaryCb) { df->vkCmdDraw(cbD->activeSecondaryCbStack.last(), vertexCount, instanceCount, firstVertex, firstInstance); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::Draw; cmd.args.draw.vertexCount = vertexCount; cmd.args.draw.instanceCount = instanceCount; cmd.args.draw.firstVertex = firstVertex; cmd.args.draw.firstInstance = firstInstance; - cbD->commands.append(cmd); } } @@ -4713,14 +4692,13 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, df->vkCmdDrawIndexed(cbD->activeSecondaryCbStack.last(), indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::DrawIndexed; cmd.args.drawIndexed.indexCount = indexCount; cmd.args.drawIndexed.instanceCount = instanceCount; cmd.args.drawIndexed.firstIndex = firstIndex; cmd.args.drawIndexed.vertexOffset = vertexOffset; cmd.args.drawIndexed.firstInstance = firstInstance; - cbD->commands.append(cmd); } } @@ -4738,12 +4716,11 @@ void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) marker.pMarkerName = name.constData(); vkCmdDebugMarkerBegin(cbD->activeSecondaryCbStack.last(), &marker); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::DebugMarkerBegin; cmd.args.debugMarkerBegin.marker = marker; cmd.args.debugMarkerBegin.markerNameIndex = cbD->pools.debugMarkerData.count(); cbD->pools.debugMarkerData.append(name); - cbD->commands.append(cmd); } } @@ -4756,9 +4733,8 @@ void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb) if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) { vkCmdDebugMarkerEnd(cbD->activeSecondaryCbStack.last()); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::DebugMarkerEnd; - cbD->commands.append(cmd); } } @@ -4776,12 +4752,11 @@ void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) marker.pMarkerName = msg.constData(); vkCmdDebugMarkerInsert(cbD->activeSecondaryCbStack.last(), &marker); } else { - QVkCommandBuffer::Command cmd; + QVkCommandBuffer::Command &cmd(cbD->commands.get()); cmd.cmd = QVkCommandBuffer::Command::DebugMarkerInsert; cmd.args.debugMarkerInsert.marker = marker; cmd.args.debugMarkerInsert.markerNameIndex = cbD->pools.debugMarkerData.count(); cbD->pools.debugMarkerData.append(msg); - cbD->commands.append(cmd); } } diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index 5819e303c3..d3f42957b1 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -543,12 +543,13 @@ struct QVkCommandBuffer : public QRhiCommandBuffer } executeSecondary; } args; }; - QVarLengthArray commands; + + QRhiBackendCommandList commands; QVarLengthArray passResTrackers; int currentPassResTrackerIndex; void resetCommands() { - commands.clear(); + commands.reset(); resetPools(); passResTrackers.clear(); @@ -580,8 +581,6 @@ struct QVkCommandBuffer : public QRhiCommandBuffer friend class QRhiVulkan; }; -Q_DECLARE_TYPEINFO(QVkCommandBuffer::Command, Q_MOVABLE_TYPE); - struct QVkSwapChain : public QRhiSwapChain { QVkSwapChain(QRhiImplementation *rhi); -- cgit v1.2.3