[Chore] (MG_Backend/DirectVulkan): move ClearAttachmentsOnActiveRenderPass to VulkanRenderer

This commit is contained in:
2026-03-03 14:59:03 +08:00
parent 20e2768f27
commit 0ae36b71f5
4 changed files with 66 additions and 23 deletions
@@ -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 = {
@@ -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 {
@@ -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<Uint32>(activeRenderPass->extent.x()),
static_cast<Uint32>(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
@@ -78,6 +78,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void Shutdown();
void SetupDraw(FrameContext::FrameData& frame, GLenum mode, Flags<DrawSetupAspect> 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<VkBufferObject> m_frameVertexUploadBuffers;
Vector<VkDeviceSize> m_frameVertexUploadHeads;
Vector<VkBufferObject> m_frameIndexUploadBuffers;