From 0ae36b71f5b3a52c720d84deed539d04345422c3 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 3 Mar 2026 14:59:03 +0800 Subject: [PATCH] [Chore] (MG_Backend/DirectVulkan): move `ClearAttachmentsOnActiveRenderPass` to VulkanRenderer --- .../Renderer/VkRenderPassManager.cpp | 7 -- .../Renderer/VkRenderPassManager.h | 4 + .../DirectVulkan/Renderer/VulkanRenderer.cpp | 74 +++++++++++++++---- .../DirectVulkan/Renderer/VulkanRenderer.h | 4 +- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp index f271927c..b5395cad 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp @@ -302,13 +302,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool VkRenderPassManager::TryClearPendingAttachmentsOnActiveRenderPass( VkCommandBuffer commandBuffer, const RenderPassEntry& compatibleRenderPassEntry) { - if (!s_activeRenderPass || !s_clearManager) { - return false; - } - if (s_activeRenderPass->compatibilityHash != compatibleRenderPassEntry.compatibilityHash) { - return false; - } - VkClearRect clearRect{}; clearRect.rect.offset = {0, 0}; clearRect.rect.extent = { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h index 2f8e6077..6451b182 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.h @@ -73,6 +73,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { vkDestroyFramebuffer(s_device, framebuffer, nullptr); } } + + Bool CompatibleWith(const RenderPassEntry& that) { + return this->compatibilityHash == that.compatibilityHash; + } }; class VkRenderPassManager { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index e9d3a941..ef0afed9 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -392,23 +392,19 @@ namespace MobileGL::MG_Backend::DirectVulkan { const auto& drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); - // Begin render pass - // TODO: properly deal with clear + // Begin render pass, and handle clear auto& renderPassEntry = m_renderPassManager->GetOrCreateRenderPass(*drawFbo, m_imageIndexAcquired); auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass(); - if (activeRenderPass != &renderPassEntry) { - if (activeRenderPass && - VkRenderPassManager::TryClearPendingAttachmentsOnActiveRenderPass(frame.commandBuffer, renderPassEntry)) { - // Keep the current compatible render pass open and clear inside it. - } else { - if (activeRenderPass) { - VkRenderPassManager::EndRenderPass(frame.commandBuffer); - } - Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry); - MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__); - } + + if (activeRenderPass && (activeRenderPass == &renderPassEntry || activeRenderPass->CompatibleWith(renderPassEntry))) { + ClearAttachmentsOnActiveRenderPass(frame.commandBuffer, renderPassEntry); } else { - // We probably already have one compatible render pass running. Keep going. + // No active render pass or active one not compatible. + // Restart a new render pass + if (activeRenderPass) + VkRenderPassManager::EndRenderPass(frame.commandBuffer); + Bool ok = VkRenderPassManager::BeginRenderPass(frame.commandBuffer, renderPassEntry); + MOBILEGL_ASSERT(ok, "%s: BeginRenderPass failed", __func__); } const auto& vao = *MG_State::pGLContext->GetBoundVertexArray(); @@ -1140,4 +1136,54 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool VulkanRenderer::IsDrawIndirectCountExtensionEnabled() const { return m_drawIndirectCountExtensionEnabled; } + + void VulkanRenderer::ClearAttachmentsOnActiveRenderPass(VkCommandBuffer commandBuffer, + const RenderPassEntry &compatibleRenderPassEntry) { + auto* activeRenderPass = VkRenderPassManager::GetActiveRenderPass(); + MOBILEGL_ASSERT(activeRenderPass, "No render pass active"); + VkClearRect clearRect{}; + clearRect.rect.offset = {0, 0}; + clearRect.rect.extent = { + static_cast(activeRenderPass->extent.x()), + static_cast(activeRenderPass->extent.y()) + }; + clearRect.baseArrayLayer = 0; + clearRect.layerCount = 1; + + for (const auto& pending : compatibleRenderPassEntry.pendingClearAttachments) { + if (!pending.texture) { + continue; + } + + ClearAttachmentPayload clearPayload{}; + if (!m_clearManager->GetPendingClear(pending.texture, clearPayload)) { + continue; + } + + VkClearAttachment clearAttachment{}; + clearAttachment.clearValue.depthStencil = {1.0f, 0}; + if (clearPayload.attachmentType >= FramebufferAttachmentType::Color0 && + clearPayload.attachmentType <= FramebufferAttachmentType::Color31) { + clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + clearAttachment.colorAttachment = pending.attachmentIndex; + clearAttachment.clearValue.color = { + clearPayload.color.x(), + clearPayload.color.y(), + clearPayload.color.z(), + clearPayload.color.w() + }; + } else if (clearPayload.attachmentType == FramebufferAttachmentType::Depth) { + clearAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + clearAttachment.clearValue.depthStencil.depth = clearPayload.depth; + } else if (clearPayload.attachmentType == FramebufferAttachmentType::Stencil) { + clearAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; + clearAttachment.clearValue.depthStencil.stencil = clearPayload.stencil; + } else { + continue; + } + + vkCmdClearAttachments(commandBuffer, 1, &clearAttachment, 1, &clearRect); + m_clearManager->PopPendingClear(pending.texture); + } + } } // namespace MobileGL::MG_Backend::DirectVulkan diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 01b4aad5..d1ad3a66 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -78,6 +78,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { void Shutdown(); void SetupDraw(FrameContext::FrameData& frame, GLenum mode, Flags aspects); + void ClearAttachmentsOnActiveRenderPass(VkCommandBuffer commandBuffer, + const RenderPassEntry& compatibleRenderPassEntry); void Clear(GLbitfield mask); void DrawArrays(const DrawArrayCmd& payload); @@ -116,8 +118,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkCommandPool m_commandPool = VK_NULL_HANDLE; - RenderPassEntry* m_activeRenderPass = nullptr; - Vector m_frameVertexUploadBuffers; Vector m_frameVertexUploadHeads; Vector m_frameIndexUploadBuffers;