From d92b0e18c1b987e60304c2e366ff374405adaab1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 30 Sep 2020 14:08:53 +0200 Subject: [PATCH] rhi: Make per-frame flags per-pass where appropriate ExternalContentsInPass becomes a per-pass flag now. Why is this beneficial? Because while Qt Quick has no choice for its render pass, not being able to guess if the application wants to do some native rendering in there, Quick 3D's render passes, all the ones that are under Quick3D's control, do not have native rendering from the application in them, and so using secondary command buffers with Vulkan is not necessary. Introduce something similar for compute and OpenGL. By knowing that none of the resources used in a pass are used with a compute pass (e.g. because we know that there are no compute passes at all) a small amount of time can be saved by skipping tracking buffers and textures because the only purpose of said tracking is to generate barriers that are relevant only to compute. Change-Id: I0eceb4774d87803c73a39db527f5707a9f4d75c1 Reviewed-by: Andy Nichols --- src/gui/rhi/qrhi.cpp | 46 ++++++++----- src/gui/rhi/qrhi_p.h | 32 +++++---- src/gui/rhi/qrhi_p_p.h | 7 +- src/gui/rhi/qrhid3d11.cpp | 7 +- src/gui/rhi/qrhid3d11_p_p.h | 7 +- src/gui/rhi/qrhigles2.cpp | 97 +++++++++++++++------------- src/gui/rhi/qrhigles2_p_p.h | 9 ++- src/gui/rhi/qrhimetal.mm | 7 +- src/gui/rhi/qrhimetal_p_p.h | 7 +- src/gui/rhi/qrhinull.cpp | 9 ++- src/gui/rhi/qrhinull_p_p.h | 7 +- src/gui/rhi/qrhivulkan.cpp | 74 +++++++++++---------- src/gui/rhi/qrhivulkan_p_p.h | 11 +++- tests/auto/gui/rhi/qrhi/tst_qrhi.cpp | 6 +- 14 files changed, 199 insertions(+), 127 deletions(-) diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 151e1268f6..0dc3082b03 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -614,11 +614,6 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general") /*! \enum QRhi::BeginFrameFlag Flag values for QRhi::beginFrame() - - \value ExternalContentsInPass Specifies that one or more render or compute - passes in this frame will call QRhiCommandBuffer::beginExternal(). Some - backends, Vulkan in particular, will fail if this flag is not set and - beginExternal() is still called. */ /*! @@ -4090,6 +4085,26 @@ QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi) \value IndexUInt32 Unsigned 32-bit (quint32) */ +/*! + \enum QRhiCommandBuffer::BeginPassFlag + Flag values for QRhi::beginPass() + + \value ExternalContent Specifies that there will be a call to + QRhiCommandBuffer::beginExternal() in this pass. Some backends, Vulkan in + particular, will fail if this flag is not set and beginExternal() is still + called. + + \value DoNotTrackResourcesForCompute Specifies that there is no need to + track resources used in this pass if the only purpose of such tracking is + to generate barriers for compute. Implies that there are no compute passes + in the frame. This is an optimization hint that may be taken into account + by certain backends, OpenGL in particular, allowing them to skip certain + operations. When this flag is set for a render pass in a frame, calling + \l{QRhiCommandBuffer::beginComputePass()}{beginComputePass()} in that frame + may lead to unexpected behavior, depending on the resource dependencies + between the render and compute passes. + */ + /*! \typedef QRhiCommandBuffer::DynamicOffset @@ -5135,9 +5150,10 @@ void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates) void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) + QRhiResourceUpdateBatch *resourceUpdates, + BeginPassFlags flags) { - m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates); + m_rhi->beginPass(this, rt, colorClearValue, depthStencilClearValue, resourceUpdates, flags); } /*! @@ -5466,9 +5482,9 @@ void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg) \note Compute is only available when the \l{QRhi::Compute}{Compute} feature is reported as supported. */ -void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates) +void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags) { - m_rhi->beginComputePass(this, resourceUpdates); + m_rhi->beginComputePass(this, resourceUpdates, flags); } /*! @@ -5543,10 +5559,10 @@ const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles() enqueue commands to the current pass' command buffer by calling graphics API functions directly. - \note This is only available when the intent was declared up front in - beginFrame(). Therefore this function must only be called when the frame - was started with specifying QRhi::ExternalContentsInPass in the flags - passed to QRhi::beginFrame(). + \note This is only available when the intent was declared upfront in + beginPass() or beginComputePass(). Therefore this function must only be + called when the pass recording was started with specifying + QRhiCommandBuffer::ExternalContent. With Vulkan or Metal one can query the native command buffer or encoder objects via nativeHandles() and enqueue commands to them. With OpenGL or @@ -5993,9 +6009,7 @@ QRhiSwapChain *QRhi::newSwapChain() A frame consists of resource updates and one or more render and compute passes. - \a flags can indicate certain special cases. For example, the fact that - QRhiCommandBuffer::beginExternal() will be called within this new frame - must be declared up front by setting the ExternalContentsInPass flag. + \a flags can indicate certain special cases. The high level pattern of rendering into a QWindow using a swapchain: diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index d3e32f2723..adbb1b61ff 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -1331,6 +1331,12 @@ public: IndexUInt32 }; + enum BeginPassFlag { + ExternalContent = 0x01, + DoNotTrackResourcesForCompute = 0x02 + }; + Q_DECLARE_FLAGS(BeginPassFlags, BeginPassFlag) + QRhiResource::Type resourceType() const override; void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates); @@ -1338,7 +1344,8 @@ public: void beginPass(QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates = nullptr); + QRhiResourceUpdateBatch *resourceUpdates = nullptr, + BeginPassFlags flags = {}); void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr); void setGraphicsPipeline(QRhiGraphicsPipeline *ps); @@ -1371,7 +1378,7 @@ public: void debugMarkEnd(); void debugMarkMsg(const QByteArray &msg); - void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr); + void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr, BeginPassFlags flags = {}); void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr); void setComputePipeline(QRhiComputePipeline *ps); void dispatch(int x, int y, int z); @@ -1384,6 +1391,8 @@ protected: QRhiCommandBuffer(QRhiImplementation *rhi); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiCommandBuffer::BeginPassFlags) + struct Q_GUI_EXPORT QRhiReadbackResult { std::function completed = nullptr; @@ -1484,7 +1493,6 @@ public: }; enum BeginFrameFlag { - ExternalContentsInPass = 0x01 }; Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag) @@ -1510,7 +1518,7 @@ public: static QRhi *create(Implementation impl, QRhiInitParams *params, - Flags flags = Flags(), + Flags flags = {}, QRhiNativeHandles *importDevice = nullptr); Implementation backend() const; @@ -1531,13 +1539,13 @@ public: QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount = 1, - QRhiRenderBuffer::Flags flags = QRhiRenderBuffer::Flags(), + QRhiRenderBuffer::Flags flags = {}, QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat); QRhiTexture *newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount = 1, - QRhiTexture::Flags flags = QRhiTexture::Flags()); + QRhiTexture::Flags flags = {}); QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, @@ -1547,16 +1555,16 @@ public: QRhiSampler::AddressMode addressW = QRhiSampler::Repeat); QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, - QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags()); + QRhiTextureRenderTarget::Flags flags = {}); QRhiSwapChain *newSwapChain(); - FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = BeginFrameFlags()); - FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = EndFrameFlags()); + FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = {}); + FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = {}); bool isRecordingFrame() const; int currentFrameSlot() const; - FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = BeginFrameFlags()); - FrameOpResult endOffscreenFrame(EndFrameFlags flags = EndFrameFlags()); + FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = {}); + FrameOpResult endOffscreenFrame(EndFrameFlags flags = {}); QRhi::FrameOpResult finish(); @@ -1576,7 +1584,7 @@ public: QMatrix4x4 clipSpaceCorrMatrix() const; - bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = QRhiTexture::Flags()) const; + bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const; bool isFeatureSupported(QRhi::Feature feature) const; int resourceLimit(ResourceLimit limit) const; diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index 1316321694..3a76e9b97b 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -109,7 +109,8 @@ public: QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) = 0; + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) = 0; virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0; virtual void setGraphicsPipeline(QRhiCommandBuffer *cb, @@ -140,7 +141,9 @@ public: virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0; virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0; - virtual void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0; + virtual void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) = 0; virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0; virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0; virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0; diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 2fe138dd55..4d00f11c84 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -1711,7 +1711,8 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags) { QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::NoPass); @@ -1822,7 +1823,9 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource enqueueResourceUpdates(cb, resourceUpdates); } -void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags) { QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QD3D11CommandBuffer::NoPass); diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index b89b6f5124..bec263e210 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -606,7 +606,8 @@ public: QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) override; + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setGraphicsPipeline(QRhiCommandBuffer *cb, @@ -638,7 +639,9 @@ public: void debugMarkEnd(QRhiCommandBuffer *cb) override; void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; - void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index ea949a8af9..02990e8c92 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1103,44 +1103,46 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind hasDynamicOffsetInSrb = true; break; case QRhiShaderResourceBinding::SampledTexture: - for (int elem = 0; elem < b->u.stex.count; ++elem) { - trackedRegisterTexture(&passResTracker, - QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex), - QRhiPassResourceTracker::TexSample, - QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); + if (cbD->passNeedsResourceTracking) { + for (int elem = 0; elem < b->u.stex.count; ++elem) { + trackedRegisterTexture(&passResTracker, + QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex), + QRhiPassResourceTracker::TexSample, + QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); + } } break; case QRhiShaderResourceBinding::ImageLoad: case QRhiShaderResourceBinding::ImageStore: case QRhiShaderResourceBinding::ImageLoadStore: - { - QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex); - QRhiPassResourceTracker::TextureAccess access; - if (b->type == QRhiShaderResourceBinding::ImageLoad) - access = QRhiPassResourceTracker::TexStorageLoad; - else if (b->type == QRhiShaderResourceBinding::ImageStore) - access = QRhiPassResourceTracker::TexStorageStore; - else - access = QRhiPassResourceTracker::TexStorageLoadStore; - trackedRegisterTexture(&passResTracker, texD, access, - QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); - } + if (cbD->passNeedsResourceTracking) { + QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex); + QRhiPassResourceTracker::TextureAccess access; + if (b->type == QRhiShaderResourceBinding::ImageLoad) + access = QRhiPassResourceTracker::TexStorageLoad; + else if (b->type == QRhiShaderResourceBinding::ImageStore) + access = QRhiPassResourceTracker::TexStorageStore; + else + access = QRhiPassResourceTracker::TexStorageLoadStore; + trackedRegisterTexture(&passResTracker, texD, access, + QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); + } break; case QRhiShaderResourceBinding::BufferLoad: case QRhiShaderResourceBinding::BufferStore: case QRhiShaderResourceBinding::BufferLoadStore: - { - QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf); - QRhiPassResourceTracker::BufferAccess access; - if (b->type == QRhiShaderResourceBinding::BufferLoad) - access = QRhiPassResourceTracker::BufStorageLoad; - else if (b->type == QRhiShaderResourceBinding::BufferStore) - access = QRhiPassResourceTracker::BufStorageStore; - else - access = QRhiPassResourceTracker::BufStorageLoadStore; - trackedRegisterBuffer(&passResTracker, bufD, access, - QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage)); - } + if (cbD->passNeedsResourceTracking) { + QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf); + QRhiPassResourceTracker::BufferAccess access; + if (b->type == QRhiShaderResourceBinding::BufferLoad) + access = QRhiPassResourceTracker::BufStorageLoad; + else if (b->type == QRhiShaderResourceBinding::BufferStore) + access = QRhiPassResourceTracker::BufStorageStore; + else + access = QRhiPassResourceTracker::BufStorageLoadStore; + trackedRegisterBuffer(&passResTracker, bufD, access, + QRhiPassResourceTracker::toPassTrackerBufferStage(b->stage)); + } break; default: break; @@ -1206,8 +1208,10 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb, cmd.args.bindVertexBuffer.binding = startBinding + i; cbD->commands.append(cmd); - trackedRegisterBuffer(&passResTracker, bufD, QRhiPassResourceTracker::BufVertexInput, - QRhiPassResourceTracker::BufVertexInputStage); + if (cbD->passNeedsResourceTracking) { + trackedRegisterBuffer(&passResTracker, bufD, QRhiPassResourceTracker::BufVertexInput, + QRhiPassResourceTracker::BufVertexInputStage); + } } if (indexBuf) { @@ -1221,8 +1225,10 @@ void QRhiGles2::setVertexInput(QRhiCommandBuffer *cb, cmd.args.bindIndexBuffer.type = indexFormat == QRhiCommandBuffer::IndexUInt16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; cbD->commands.append(cmd); - trackedRegisterBuffer(&passResTracker, ibufD, QRhiPassResourceTracker::BufIndexRead, - QRhiPassResourceTracker::BufVertexInputStage); + if (cbD->passNeedsResourceTracking) { + trackedRegisterBuffer(&passResTracker, ibufD, QRhiPassResourceTracker::BufIndexRead, + QRhiPassResourceTracker::BufVertexInputStage); + } } } @@ -1416,10 +1422,8 @@ void QRhiGles2::endExternal(QRhiCommandBuffer *cb) enqueueBindFramebuffer(cbD->currentTarget, cbD); } -QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) +QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags) { - Q_UNUSED(flags); - QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain); if (!ensureContext(swapChainD->surface)) return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError; @@ -1465,9 +1469,8 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame return QRhi::FrameOpSuccess; } -QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) +QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags) { - Q_UNUSED(flags); if (!ensureContext()) return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError; @@ -2593,6 +2596,8 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) break; case QGles2CommandBuffer::Command::BarriersForPass: { + if (!caps.compute) + break; GLbitfield barriers = 0; QRhiPassResourceTracker &tracker(cbD->passResTrackers[cmd.args.barriersForPass.trackerIndex]); // we only care about after-write, not any other accesses, and @@ -2612,7 +2617,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) if (textureAccessIsWrite(accessBeforePass)) barriers |= GL_ALL_BARRIER_BITS; } - if (barriers && caps.compute) + if (barriers) f->glMemoryBarrier(barriers); } break; @@ -3127,12 +3132,12 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, const QRhiColorAttachment &colorAtt(*it); QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture()); QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture()); - if (texD) { + if (texD && cbD->passNeedsResourceTracking) { trackedRegisterTexture(&passResTracker, texD, QRhiPassResourceTracker::TexColorOutput, QRhiPassResourceTracker::TexColorOutputStage); } - if (resolveTexD) { + if (resolveTexD && cbD->passNeedsResourceTracking) { trackedRegisterTexture(&passResTracker, resolveTexD, QRhiPassResourceTracker::TexColorOutput, QRhiPassResourceTracker::TexColorOutputStage); @@ -3140,7 +3145,7 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, // renderbuffers cannot be written in shaders (no image store) so // they do not matter here } - if (rtTex->m_desc.depthTexture()) { + if (rtTex->m_desc.depthTexture() && cbD->passNeedsResourceTracking) { trackedRegisterTexture(&passResTracker, QRHI_RES(QGles2Texture, rtTex->m_desc.depthTexture()), QRhiPassResourceTracker::TexDepthOutput, QRhiPassResourceTracker::TexDepthOutputStage); @@ -3172,7 +3177,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); @@ -3203,6 +3209,7 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, cbD->commands.append(clearCmd); cbD->recordingPass = QGles2CommandBuffer::RenderPass; + cbD->passNeedsResourceTracking = !flags.testFlag(QRhiCommandBuffer::DoNotTrackResourcesForCompute); cbD->currentTarget = rt; cbD->resetCachedState(); @@ -3249,7 +3256,9 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource enqueueResourceUpdates(cb, resourceUpdates); } -void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags) { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index c380f3bc08..95bf85f0b4 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -519,6 +519,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer int currentPassResTrackerIndex; PassType recordingPass; + bool passNeedsResourceTracking; QRhiRenderTarget *currentTarget; QRhiGraphicsPipeline *currentGraphicsPipeline; QRhiComputePipeline *currentComputePipeline; @@ -611,6 +612,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer } void resetState() { recordingPass = NoPass; + passNeedsResourceTracking = true; currentTarget = nullptr; resetCommands(); resetCachedState(); @@ -741,7 +743,8 @@ public: QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) override; + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setGraphicsPipeline(QRhiCommandBuffer *cb, @@ -773,7 +776,9 @@ public: void debugMarkEnd(QRhiCommandBuffer *cb) override; void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; - void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index a31d37c01a..4caaca4a3a 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -1898,7 +1898,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags) { QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::NoPass); @@ -2013,7 +2014,9 @@ void QRhiMetal::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource enqueueResourceUpdates(cb, resourceUpdates); } -void QRhiMetal::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +void QRhiMetal::beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags) { QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::NoPass); diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h index 58d7dec116..a8c342da25 100644 --- a/src/gui/rhi/qrhimetal_p_p.h +++ b/src/gui/rhi/qrhimetal_p_p.h @@ -379,7 +379,8 @@ public: QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) override; + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setGraphicsPipeline(QRhiCommandBuffer *cb, @@ -411,7 +412,9 @@ public: void debugMarkEnd(QRhiCommandBuffer *cb) override; void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; - void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index 4c650e68a0..86beb243c6 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -522,11 +522,13 @@ void QRhiNull::beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) { Q_UNUSED(rt); Q_UNUSED(colorClearValue); Q_UNUSED(depthStencilClearValue); + Q_UNUSED(flags); if (resourceUpdates) resourceUpdate(cb, resourceUpdates); } @@ -537,8 +539,11 @@ void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceU resourceUpdate(cb, resourceUpdates); } -void QRhiNull::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +void QRhiNull::beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) { + Q_UNUSED(flags); if (resourceUpdates) resourceUpdate(cb, resourceUpdates); } diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h index 2921d0634e..567b672b3f 100644 --- a/src/gui/rhi/qrhinull_p_p.h +++ b/src/gui/rhi/qrhinull_p_p.h @@ -237,7 +237,8 @@ public: QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) override; + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setGraphicsPipeline(QRhiCommandBuffer *cb, @@ -269,7 +270,9 @@ public: void debugMarkEnd(QRhiCommandBuffer *cb) override; void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; - void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index c0162820b6..d6b1bc0670 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1624,7 +1624,7 @@ void QRhiVulkan::releaseSwapChainResources(QRhiSwapChain *swapChain) // NB! surface and similar must remain intact } -QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) +QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags) { QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain); const int frameResIndex = swapChainD->bufferCount > 1 ? swapChainD->currentFrameSlot : 0; @@ -1724,7 +1724,6 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin } swapChainD->cbWrapper.cb = frame.cmdBuf; - swapChainD->cbWrapper.useSecondaryCb = flags.testFlag(QRhi::ExternalContentsInPass); QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]); swapChainD->rtWrapper.d.fb = image.fb; @@ -1971,7 +1970,7 @@ void QRhiVulkan::waitCommandCompletion(int frameSlot) } } -QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) +QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags) { QRhi::FrameOpResult cbres = startPrimaryCommandBuffer(&ofr.cbWrapper.cb); if (cbres != QRhi::FrameOpSuccess) @@ -1990,8 +1989,6 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi if (swapchains.count() > 1) waitCommandCompletion(currentFrameSlot); - ofr.cbWrapper.useSecondaryCb = flags.testFlag(QRhi::ExternalContentsInPass); - prepareNewFrame(&ofr.cbWrapper); ofr.active = true; @@ -2209,7 +2206,8 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) { QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass); @@ -2245,6 +2243,7 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb, } cbD->recordingPass = QVkCommandBuffer::RenderPass; + cbD->passUsesSecondaryCb = flags.testFlag(QRhiCommandBuffer::ExternalContent); cbD->currentTarget = rt; // No copy operations or image layout transitions allowed after this point @@ -2282,10 +2281,11 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb, 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->useSecondaryCb) + if (cbD->passUsesSecondaryCb) cbD->secondaryCbs.append(startSecondaryCommandBuffer(rtD)); } @@ -2294,7 +2294,7 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { VkCommandBuffer secondaryCb = cbD->secondaryCbs.last(); cbD->secondaryCbs.removeLast(); endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD); @@ -2312,7 +2312,9 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc enqueueResourceUpdates(cbD, resourceUpdates); } -void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) +void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) { QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass); @@ -2323,10 +2325,11 @@ void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch enqueueTransitionPassResources(cbD); cbD->recordingPass = QVkCommandBuffer::ComputePass; + cbD->passUsesSecondaryCb = flags.testFlag(QRhiCommandBuffer::ExternalContent); cbD->computePassState.reset(); - if (cbD->useSecondaryCb) + if (cbD->passUsesSecondaryCb) cbD->secondaryCbs.append(startSecondaryCommandBuffer()); } @@ -2335,7 +2338,7 @@ void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch * QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { VkCommandBuffer secondaryCb = cbD->secondaryCbs.last(); cbD->secondaryCbs.removeLast(); endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD); @@ -2356,7 +2359,7 @@ void QRhiVulkan::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline * Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass); if (cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation) { - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdBindPipeline(cbD->secondaryCbs.last(), VK_PIPELINE_BIND_POINT_COMPUTE, psD->pipeline); } else { QVkCommandBuffer::Command cmd; @@ -2485,7 +2488,7 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z) } } - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { VkCommandBuffer secondaryCb = cbD->secondaryCbs.last(); if (!imageBarriers.isEmpty()) { df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, @@ -3697,7 +3700,8 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD) case QVkCommandBuffer::Command::BeginRenderPass: cmd.args.beginRenderPass.desc.pClearValues = cbD->pools.clearValue.constData() + cmd.args.beginRenderPass.clearValueIndex; df->vkCmdBeginRenderPass(cbD->cb, &cmd.args.beginRenderPass.desc, - cbD->useSecondaryCb ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE); + cmd.args.beginRenderPass.useSecondaryCb ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS + : VK_SUBPASS_CONTENTS_INLINE); break; case QVkCommandBuffer::Command::EndRenderPass: df->vkCmdEndRenderPass(cbD->cb); @@ -4227,7 +4231,7 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass); if (cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation) { - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdBindPipeline(cbD->secondaryCbs.last(), VK_PIPELINE_BIND_POINT_GRAPHICS, psD->pipeline); } else { QVkCommandBuffer::Command cmd; @@ -4435,7 +4439,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin } } - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdBindDescriptorSets(cbD->secondaryCbs.last(), gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE, gfxPsD ? gfxPsD->layout : compPsD->layout, @@ -4509,7 +4513,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, QRhiPassResourceTracker::BufVertexInputStage); } - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdBindVertexBuffers(cbD->secondaryCbs.last(), uint32_t(startBinding), uint32_t(bufs.count()), bufs.constData(), ofs.constData()); } else { @@ -4545,7 +4549,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb, cbD->currentIndexOffset = indexOffset; cbD->currentIndexFormat = type; - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdBindIndexBuffer(cbD->secondaryCbs.last(), vkindexbuf, indexOffset, type); } else { QVkCommandBuffer::Command cmd; @@ -4583,7 +4587,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport vp->minDepth = viewport.minDepth(); vp->maxDepth = viewport.maxDepth(); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdSetViewport(cbD->secondaryCbs.last(), 0, 1, vp); } else { cmd.cmd = QVkCommandBuffer::Command::SetViewport; @@ -4596,7 +4600,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport s->offset.y = int32_t(y); s->extent.width = uint32_t(w); s->extent.height = uint32_t(h); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s); } else { cmd.cmd = QVkCommandBuffer::Command::SetScissor; @@ -4624,7 +4628,7 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) s->extent.width = uint32_t(w); s->extent.height = uint32_t(h); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s); } else { cmd.cmd = QVkCommandBuffer::Command::SetScissor; @@ -4637,7 +4641,7 @@ void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { float constants[] = { float(c.redF()), float(c.greenF()), float(c.blueF()), float(c.alphaF()) }; df->vkCmdSetBlendConstants(cbD->secondaryCbs.last(), constants); } else { @@ -4656,7 +4660,7 @@ void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdSetStencilReference(cbD->secondaryCbs.last(), VK_STENCIL_FRONT_AND_BACK, refValue); } else { QVkCommandBuffer::Command cmd; @@ -4672,7 +4676,7 @@ void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount, QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdDraw(cbD->secondaryCbs.last(), vertexCount, instanceCount, firstVertex, firstInstance); } else { QVkCommandBuffer::Command cmd; @@ -4691,7 +4695,7 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass); - if (cbD->useSecondaryCb) { + if (cbD->passUsesSecondaryCb) { df->vkCmdDrawIndexed(cbD->secondaryCbs.last(), indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); } else { @@ -4716,7 +4720,7 @@ void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); - if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) { + if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) { marker.pMarkerName = name.constData(); vkCmdDebugMarkerBegin(cbD->secondaryCbs.last(), &marker); } else { @@ -4735,7 +4739,7 @@ void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb) return; QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); - if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) { + if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) { vkCmdDebugMarkerEnd(cbD->secondaryCbs.last()); } else { QVkCommandBuffer::Command cmd; @@ -4754,7 +4758,7 @@ void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); - if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) { + if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) { marker.pMarkerName = msg.constData(); vkCmdDebugMarkerInsert(cbD->secondaryCbs.last(), &marker); } else { @@ -4812,9 +4816,9 @@ void QRhiVulkan::beginExternal(QRhiCommandBuffer *cb) if (cbD->inExternal) return; - if (!cbD->useSecondaryCb) { + if (!cbD->passUsesSecondaryCb) { qWarning("beginExternal() within a pass is only supported with secondary command buffers. " - "This can be enabled by passing QRhi::ExternalContentsInPass to beginFrame()."); + "This can be enabled by passing QRhiCommandBuffer::ExternalContent to beginPass()."); return; } @@ -6615,10 +6619,14 @@ const QRhiNativeHandles *QVkCommandBuffer::nativeHandles() // secondary command buffer (typically the one started by beginExternal(), // in case we are between beginExternal - endExternal inside a pass). - if (useSecondaryCb && !secondaryCbs.isEmpty()) - nativeHandlesStruct.commandBuffer = secondaryCbs.last(); - else + if (recordingPass == QVkCommandBuffer::NoPass) { nativeHandlesStruct.commandBuffer = cb; + } else { + if (passUsesSecondaryCb && !secondaryCbs.isEmpty()) + nativeHandlesStruct.commandBuffer = secondaryCbs.last(); + else + nativeHandlesStruct.commandBuffer = cb; + } return &nativeHandlesStruct; } diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index c590039bc1..a352f3c2f2 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -329,7 +329,6 @@ struct QVkCommandBuffer : public QRhiCommandBuffer const QRhiNativeHandles *nativeHandles(); VkCommandBuffer cb = VK_NULL_HANDLE; // primary - bool useSecondaryCb = false; QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct; enum PassType { @@ -340,6 +339,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer void resetState() { recordingPass = NoPass; + passUsesSecondaryCb = false; currentTarget = nullptr; secondaryCbs.clear(); @@ -365,6 +365,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer } PassType recordingPass; + bool passUsesSecondaryCb; QRhiRenderTarget *currentTarget; QRhiGraphicsPipeline *currentGraphicsPipeline; QRhiComputePipeline *currentComputePipeline; @@ -468,6 +469,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer struct { VkRenderPassBeginInfo desc; int clearValueIndex; + bool useSecondaryCb; } beginRenderPass; struct { } endRenderPass; @@ -694,7 +696,8 @@ public: QRhiRenderTarget *rt, const QColor &colorClearValue, const QRhiDepthStencilClearValue &depthStencilClearValue, - QRhiResourceUpdateBatch *resourceUpdates) override; + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setGraphicsPipeline(QRhiCommandBuffer *cb, @@ -726,7 +729,9 @@ public: void debugMarkEnd(QRhiCommandBuffer *cb) override; void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; - void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; + void beginComputePass(QRhiCommandBuffer *cb, + QRhiResourceUpdateBatch *resourceUpdates, + QRhiCommandBuffer::BeginPassFlags flags) override; void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp index b6351eef45..477b98cc4e 100644 --- a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp +++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp @@ -2751,8 +2751,8 @@ void tst_QRhi::finishWithinSwapchainFrame() QScopedPointer vbuf(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices))); QVERIFY(vbuf->create()); - // exercise begin/endExternal() just a little bit, hence ExternalContentsInPass - QVERIFY(rhi->beginFrame(swapChain.data(), QRhi::ExternalContentsInPass) == QRhi::FrameOpSuccess); + // exercise begin/endExternal() just a little bit, note ExternalContent for beginPass() + QVERIFY(rhi->beginFrame(swapChain.data()) == QRhi::FrameOpSuccess); QRhiCommandBuffer *cb = swapChain->currentFrameCommandBuffer(); QRhiRenderTarget *rt = swapChain->currentFrameRenderTarget(); const QSize outputSize = swapChain->currentPixelSize(); @@ -2763,7 +2763,7 @@ void tst_QRhi::finishWithinSwapchainFrame() QRhiResourceUpdateBatch *updates = rhi->nextResourceUpdateBatch(); updates->uploadStaticBuffer(vbuf.data(), vertices); - cb->beginPass(rt, Qt::blue, { 1.0f, 0 }, updates); + cb->beginPass(rt, Qt::blue, { 1.0f, 0 }, updates, QRhiCommandBuffer::ExternalContent); // just have some commands, do not bother with draw calls cb->setGraphicsPipeline(pipeline.data());