From 2d7fc7a1527211fb9e41310b3ea75ba6d61cee8d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 26 Aug 2019 15:19:59 +0200 Subject: rhi: vulkan: Expose the VkRenderPass via the usual mechanisms Qt Quick in turn will expose it via QSGRendererInterface. Essential when adding custom Vulkan rendering into a Qt Quick application because the custom pipeline state objects will need to reference a VkRenderPass. Change-Id: Idf4092cfc3937830fb8123164081059b0d8d030e Reviewed-by: Andy Nichols --- src/gui/rhi/qrhivulkan_p_p.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/gui/rhi/qrhivulkan_p_p.h') diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index 31e0eaa585..e2ea8fec2a 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -171,9 +171,11 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor QVkRenderPassDescriptor(QRhiImplementation *rhi); ~QVkRenderPassDescriptor(); void release() override; + const QRhiNativeHandles *nativeHandles() override; VkRenderPass rp = VK_NULL_HANDLE; bool ownsRp = false; + QRhiVulkanRenderPassNativeHandles nativeHandlesStruct; int lastActiveFrameSlot = -1; }; -- cgit v1.2.3 From 4e97c4061e0ac7d885e62cfaf9ab7eb1918906f1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 26 Aug 2019 16:10:31 +0200 Subject: rhi: Attempt to fix up the logic around beginExternal() Mainly for Vulkan where it lacked the recording of the still queued commands. Uncovered by Qt Quick examples that integrate custom Vulkan rendering. This still has an issue that needs to be tackled separately. (we probably will switch to using a dedicated secondary command buffer with RENDER_PASS_CONTINUE_BIT for the external commands, and then just have a vkCmdExecuteCommands in our own queue instead of recording everything in beginExternal). The possibility of losing glMemoryBarrier() calls due to begin/endExternal() with the OpenGL backend is fixed too. The logic here mirrors Vulkan to some extent except that we do not have a concept of (and so the trouble with) renderpass instances. Clean up around the implementations of finish() as well. Attempting to share code via a "flushCommandBuffer" function is admirable but is not worth it since some semantics are different. (finish() cannot be called within a begin/endPass, unlike begin/endExternal). Change-Id: I5137db598d6a40d484e53678f5c919abf750d9ed Reviewed-by: Andy Nichols --- src/gui/rhi/qrhivulkan_p_p.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/gui/rhi/qrhivulkan_p_p.h') 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() { -- cgit v1.2.3 From 2602209f545ea3873f0dc880c258669a508d283a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 27 Aug 2019 12:49:38 +0200 Subject: rhi: vulkan: Introduce secondary command buffer usage As an option. Must opt in via setting ExternalContentsInPass in the flags for beginFrame(). It is somewhat unfortunate to require declaring this up front, but forcing using secondary command buffers always, even though beginExternal() may not be used in many applications, would be an overkill. Change-Id: I8d52bcab40c96f89f140c4c7877b6c459925e3c7 Reviewed-by: Andy Nichols --- src/gui/rhi/qrhivulkan_p_p.h | 50 +++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'src/gui/rhi/qrhivulkan_p_p.h') diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index dd9a7d4216..962a1b8eb7 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -309,13 +309,11 @@ struct QVkCommandBuffer : public QRhiCommandBuffer ~QVkCommandBuffer(); void release() override; - VkCommandBuffer cb = VK_NULL_HANDLE; - QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct; + const QRhiNativeHandles *nativeHandles(); - const QRhiNativeHandles *nativeHandles() { - nativeHandlesStruct.commandBuffer = cb; - return &nativeHandlesStruct; - } + VkCommandBuffer cb = VK_NULL_HANDLE; // primary + bool useSecondaryCb = false; + QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct; enum PassType { NoPass, @@ -326,6 +324,9 @@ struct QVkCommandBuffer : public QRhiCommandBuffer void resetState() { recordingPass = NoPass; currentTarget = nullptr; + + secondaryCbs.clear(); + resetCommands(); resetCachedState(); } @@ -343,6 +344,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer currentIndexFormat = VK_INDEX_TYPE_UINT16; memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers)); memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets)); + inExternal = false; } PassType recordingPass; @@ -360,6 +362,8 @@ struct QVkCommandBuffer : public QRhiCommandBuffer static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32; VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT]; quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + QVarLengthArray secondaryCbs; + bool inExternal; struct Command { enum Cmd { @@ -386,7 +390,8 @@ struct QVkCommandBuffer : public QRhiCommandBuffer DebugMarkerEnd, DebugMarkerInsert, TransitionPassResources, - Dispatch + Dispatch, + ExecuteSecondary }; Cmd cmd; @@ -495,6 +500,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer } debugMarkerEnd; struct { VkDebugMarkerMarkerInfoEXT marker; + int markerNameIndex; } debugMarkerInsert; struct { int trackerIndex; @@ -502,6 +508,9 @@ struct QVkCommandBuffer : public QRhiCommandBuffer struct { int x, y, z; } dispatch; + struct { + VkCommandBuffer cb; + } executeSecondary; } args; }; QVector commands; @@ -522,7 +531,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer pools.dynamicOffset.clear(); pools.vertexBuffer.clear(); pools.vertexBufferOffset.clear(); - pools.debugMarkerName.clear(); + pools.debugMarkerData.clear(); } struct { @@ -531,7 +540,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer QVarLengthArray dynamicOffset; QVarLengthArray vertexBuffer; QVarLengthArray vertexBufferOffset; - QVarLengthArray debugMarkerName; + QVarLengthArray debugMarkerData; } pools; friend class QRhiVulkan; @@ -595,7 +604,7 @@ struct QVkSwapChain : public QRhiSwapChain bool imageAcquired = false; bool imageSemWaitable = false; quint32 imageIndex = 0; - VkCommandBuffer cmdBuf = VK_NULL_HANDLE; + VkCommandBuffer cmdBuf = VK_NULL_HANDLE; // primary VkFence cmdFence = VK_NULL_HANDLE; bool cmdFenceWaitable = false; int timestampQueryIndex = -1; @@ -640,8 +649,8 @@ public: QRhiSwapChain *createSwapChain() override; QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override; QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; - QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override; - QRhi::FrameOpResult endOffscreenFrame() override; + QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override; + QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override; QRhi::FrameOpResult finish() override; void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; @@ -730,9 +739,12 @@ public: VkShaderModule createShader(const QByteArray &spirv); void prepareNewFrame(QRhiCommandBuffer *cb); - QRhi::FrameOpResult startCommandBuffer(VkCommandBuffer *cb); - QRhi::FrameOpResult endAndSubmitCommandBuffer(VkCommandBuffer cb, VkFence cmdFence, - VkSemaphore *waitSem, VkSemaphore *signalSem); + VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD = nullptr); + void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD); + void deferredReleaseSecondaryCommandBuffer(VkCommandBuffer cb); + QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb); + QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence, + VkSemaphore *waitSem, VkSemaphore *signalSem); void waitCommandCompletion(int frameSlot); VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const; using BufferImageCopyList = QVarLengthArray; @@ -743,7 +755,7 @@ public: void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates); void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD); void enqueueTransitionPassResources(QVkCommandBuffer *cbD); - void recordCommandBuffer(QVkCommandBuffer *cbD); + void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD); void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, QVkBuffer *bufD, int slot, @@ -859,7 +871,8 @@ public: Sampler, TextureRenderTarget, RenderPass, - StagingBuffer + StagingBuffer, + CommandBuffer }; Type type; int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1 @@ -906,6 +919,9 @@ public: VkBuffer stagingBuffer; QVkAlloc stagingAllocation; } stagingBuffer; + struct { + VkCommandBuffer cb; + } commandBuffer; }; }; QVector releaseQueue; -- cgit v1.2.3