diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 34 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11_p_p.h | 3 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 84 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 13 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 30 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan_p_p.h | 5 |
6 files changed, 102 insertions, 67 deletions
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 9b411c5021..e978536dd7 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -873,8 +873,10 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb) void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb) { - Q_UNUSED(cb); - flushCommandBuffer(); + QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); + // no timestampSwapChain, in order to avoid timestamp mess + executeCommandBuffer(cbD); + cbD->resetCommands(); } void QRhiD3D11::endExternal(QRhiCommandBuffer *cb) @@ -1135,27 +1137,25 @@ static inline bool isDepthTextureFormat(QRhiTexture::Format format) QRhi::FrameOpResult QRhiD3D11::finish() { - if (inFrame) - flushCommandBuffer(); + if (inFrame) { + if (ofr.active) { + Q_ASSERT(!contextState.currentSwapChain); + Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass); + executeCommandBuffer(&ofr.cbWrapper); + ofr.cbWrapper.resetCommands(); + } else { + Q_ASSERT(contextState.currentSwapChain); + Q_ASSERT(contextState.currentSwapChain->cb.recordingPass == QD3D11CommandBuffer::NoPass); + executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess + contextState.currentSwapChain->cb.resetCommands(); + } + } finishActiveReadbacks(); return QRhi::FrameOpSuccess; } -void QRhiD3D11::flushCommandBuffer() -{ - if (ofr.active) { - Q_ASSERT(!contextState.currentSwapChain); - executeCommandBuffer(&ofr.cbWrapper); - ofr.cbWrapper.resetCommands(); - } else { - Q_ASSERT(contextState.currentSwapChain); - executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess - contextState.currentSwapChain->cb.resetCommands(); - } -} - void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc) { diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 3ceb055b27..096c192183 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -473,9 +473,9 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer imageRetainPool.clear(); } void resetState() { - resetCommands(); recordingPass = NoPass; currentTarget = nullptr; + resetCommands(); resetCachedState(); } void resetCachedState() { @@ -633,7 +633,6 @@ public: void sendVMemStatsToProfiler() override; void makeThreadLocalNativeContextCurrent() override; - void flushCommandBuffer(); void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 26e7fa2759..2cc489ea8b 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1094,15 +1094,36 @@ const QRhiNativeHandles *QRhiGles2::nativeHandles(QRhiCommandBuffer *cb) void QRhiGles2::beginExternal(QRhiCommandBuffer *cb) { - Q_UNUSED(cb); - flushCommandBuffer(); // also ensures the context is current + if (ofr.active) { + Q_ASSERT(!currentSwapChain); + if (!ensureContext()) + return; + } else { + Q_ASSERT(currentSwapChain); + if (!ensureContext(currentSwapChain->surface)) + return; + } + + QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); + executeCommandBuffer(cbD); + cbD->resetCommands(); } void QRhiGles2::endExternal(QRhiCommandBuffer *cb) { QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); - Q_ASSERT(cbD->commands.isEmpty()); + Q_ASSERT(cbD->commands.isEmpty() && cbD->currentPassResTrackerIndex == -1); + cbD->resetCachedState(); + + if (cbD->recordingPass != QGles2CommandBuffer::NoPass) { + // Commands that come after this point need a resource tracker and also + // a BarriersForPass command enqueued. (the ones we had from + // beginPass() are now gone since beginExternal() processed all that + // due to calling executeCommandBuffer()). + enqueueBarriersForPass(cbD); + } + if (cbD->currentTarget) enqueueBindFramebuffer(cbD->currentTarget, cbD); } @@ -1196,23 +1217,22 @@ QRhi::FrameOpResult QRhiGles2::endOffscreenFrame() QRhi::FrameOpResult QRhiGles2::finish() { - return inFrame ? flushCommandBuffer() : QRhi::FrameOpSuccess; -} - -QRhi::FrameOpResult QRhiGles2::flushCommandBuffer() -{ - if (ofr.active) { - Q_ASSERT(!currentSwapChain); - if (!ensureContext()) - return QRhi::FrameOpError; - executeCommandBuffer(&ofr.cbWrapper); - ofr.cbWrapper.resetCommands(); - } else { - Q_ASSERT(currentSwapChain); - if (!ensureContext(currentSwapChain->surface)) - return QRhi::FrameOpError; - executeCommandBuffer(¤tSwapChain->cb); - currentSwapChain->cb.resetCommands(); + if (inFrame) { + if (ofr.active) { + Q_ASSERT(!currentSwapChain); + Q_ASSERT(ofr.cbWrapper.recordingPass == QGles2CommandBuffer::NoPass); + if (!ensureContext()) + return QRhi::FrameOpError; + executeCommandBuffer(&ofr.cbWrapper); + ofr.cbWrapper.resetCommands(); + } else { + Q_ASSERT(currentSwapChain); + Q_ASSERT(currentSwapChain->cb.recordingPass == QGles2CommandBuffer::NoPass); + if (!ensureContext(currentSwapChain->surface)) + return QRhi::FrameOpError; + executeCommandBuffer(¤tSwapChain->cb); + currentSwapChain->cb.resetCommands(); + } } return QRhi::FrameOpSuccess; } @@ -2483,6 +2503,16 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt, return rtD; } +void QRhiGles2::enqueueBarriersForPass(QGles2CommandBuffer *cbD) +{ + cbD->passResTrackers.append(QRhiPassResourceTracker()); + cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass; + cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex; + cbD->commands.append(cmd); +} + void QRhiGles2::beginPass(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &colorClearValue, @@ -2497,12 +2527,7 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, // Get a new resource tracker. Then add a command that will generate // glMemoryBarrier() calls based on that tracker when submitted. - cbD->passResTrackers.append(QRhiPassResourceTracker()); - cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; - QGles2CommandBuffer::Command cmd; - cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass; - cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex; - cbD->commands.append(cmd); + enqueueBarriersForPass(cbD); bool wantsColorClear, wantsDsClear; QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear); @@ -2578,12 +2603,7 @@ void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch if (resourceUpdates) enqueueResourceUpdates(cb, resourceUpdates); - cbD->passResTrackers.append(QRhiPassResourceTracker()); - cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; - QGles2CommandBuffer::Command cmd; - cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass; - cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex; - cbD->commands.append(cmd); + enqueueBarriersForPass(cbD); cbD->recordingPass = QGles2CommandBuffer::ComputePass; diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 462ce8032c..3602d62122 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -525,19 +525,16 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer } void resetCommands() { commands.clear(); - // beginExternal() can lead to calling resetCommands() inside a pass, - // hence the condition - if (recordingPass == NoPass) { - passResTrackers.clear(); - currentPassResTrackerIndex = -1; - } dataRetainPool.clear(); imageRetainPool.clear(); + + passResTrackers.clear(); + currentPassResTrackerIndex = -1; } void resetState() { - resetCommands(); recordingPass = NoPass; currentTarget = nullptr; + resetCommands(); resetCachedState(); } void resetCachedState() { @@ -671,7 +668,6 @@ public: bool ensureContext(QSurface *surface = nullptr) const; void executeDeferredReleases(); - QRhi::FrameOpResult flushCommandBuffer(); void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access); void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access); void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD, @@ -692,6 +688,7 @@ public: const uint *dynOfsPairs, int dynOfsCount); QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD, bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr); + void enqueueBarriersForPass(QGles2CommandBuffer *cbD); int effectiveSampleCount(int sampleCount) const; bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderDescription *desc, int *glslVersionUsed); diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index a0f32252cf..0381def9f1 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1868,12 +1868,16 @@ QRhi::FrameOpResult QRhiVulkan::finish() VkCommandBuffer cb; if (ofr.active) { Q_ASSERT(!currentSwapChain); + Q_ASSERT(ofr.cbWrapper.recordingPass == QVkCommandBuffer::NoPass); recordCommandBuffer(&ofr.cbWrapper); + ofr.cbWrapper.resetCommands(); cb = ofr.cbWrapper.cb; } else { Q_ASSERT(currentSwapChain); + Q_ASSERT(currentSwapChain->cbWrapper.recordingPass == QVkCommandBuffer::NoPass); swapChainD = currentSwapChain; recordCommandBuffer(&swapChainD->cbWrapper); + swapChainD->cbWrapper.resetCommands(); cb = swapChainD->cbWrapper.cb; } QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(cb, VK_NULL_HANDLE, nullptr, nullptr); @@ -3120,17 +3124,16 @@ VkSampleCountFlagBits QRhiVulkan::effectiveSampleCount(int sampleCount) void QRhiVulkan::enqueueTransitionPassResources(QVkCommandBuffer *cbD) { cbD->passResTrackers.append(QRhiPassResourceTracker()); + cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; + QVkCommandBuffer::Command cmd; cmd.cmd = QVkCommandBuffer::Command::TransitionPassResources; cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.count() - 1; cbD->commands.append(cmd); - cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1; } void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD) { - Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass); - for (QVkCommandBuffer::Command &cmd : cbD->commands) { switch (cmd.cmd) { case QVkCommandBuffer::Command::CopyBuffer: @@ -3244,8 +3247,6 @@ void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD) break; } } - - cbD->resetCommands(); } static inline VkAccessFlags toVkAccess(QRhiPassResourceTracker::BufferAccess access) @@ -4138,13 +4139,30 @@ const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb) void QRhiVulkan::beginExternal(QRhiCommandBuffer *cb) { - Q_UNUSED(cb); + QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); + recordCommandBuffer(cbD); + cbD->resetCommands(); } void QRhiVulkan::endExternal(QRhiCommandBuffer *cb) { QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb); + Q_ASSERT(cbD->commands.isEmpty() && cbD->currentPassResTrackerIndex == -1); + cbD->resetCachedState(); + + // ### FIXME this is all broken (leads to barriers within a renderpass + // instance which (1) would need a self-dependency for the subpass and (2) is + // not what we want anyway since it then has a different sychronization scope). + // + // To be replaced with a secondary command buffer for the external content. + // + if (cbD->recordingPass != QVkCommandBuffer::NoPass) { + // Commands that come after this point need a resource tracker and the + // corresponding barriers. Note that we are inside a renderpass + // instance here and that needs a self-dependency for the subpass. + enqueueTransitionPassResources(cbD); + } } void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot) diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index e2ea8fec2a..dd9a7d4216 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -324,9 +324,9 @@ struct QVkCommandBuffer : public QRhiCommandBuffer }; void resetState() { - resetCommands(); recordingPass = NoPass; currentTarget = nullptr; + resetCommands(); resetCachedState(); } @@ -510,9 +510,10 @@ struct QVkCommandBuffer : public QRhiCommandBuffer void resetCommands() { commands.clear(); + resetPools(); + passResTrackers.clear(); currentPassResTrackerIndex = -1; - resetPools(); } void resetPools() { |