diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp index 82241b87..ac11c599 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkRenderPassManager.cpp @@ -979,6 +979,52 @@ namespace MobileGL::MG_Backend::DirectVulkan { subpassDesc.preserveAttachmentCount = 0; subpassDesc.pPreserveAttachments = nullptr; + // External subpass dependencies. Without them there is NO execution/memory + // dependency between consecutive render passes (or a pass and a transfer) + // touching the same attachments when the image layout does not change — the + // layout-transition helper no-ops on identical layouts and no other barrier + // exists. Tile-based GPUs then race tile loads against the previous pass's + // stores (multi-pass FBO chains like MC 26.3's OIT flicker on Adreno). + // Conservative both-ways dependencies: prior writes (attachment output, + // depth/stencil, transfer, shader) are made visible to this pass's loads, + // and this pass's attachment writes to subsequent sampling/transfer/loads. + VkSubpassDependency subpassDependencies[2]; + subpassDependencies[0] = {}; + subpassDependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + subpassDependencies[0].dstSubpass = 0; + subpassDependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT; + subpassDependencies[0].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + subpassDependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + subpassDependencies[0].dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_SHADER_READ_BIT; + subpassDependencies[0].dependencyFlags = 0; + subpassDependencies[1] = {}; + subpassDependencies[1].srcSubpass = 0; + subpassDependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + subpassDependencies[1].srcStageMask = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + subpassDependencies[1].srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + subpassDependencies[1].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_TRANSFER_BIT; + subpassDependencies[1].dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + subpassDependencies[1].dependencyFlags = 0; + // Render Pass VkRenderPassCreateInfo renderPassCreateInfo; renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; @@ -988,8 +1034,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { renderPassCreateInfo.pAttachments = attachmentDescriptions.data(); renderPassCreateInfo.subpassCount = 1; renderPassCreateInfo.pSubpasses = &subpassDesc; - renderPassCreateInfo.dependencyCount = 0; - renderPassCreateInfo.pDependencies = nullptr; + renderPassCreateInfo.dependencyCount = 2; + renderPassCreateInfo.pDependencies = subpassDependencies; VkRenderPass renderPass = VK_NULL_HANDLE; VK_VERIFY(vkCreateRenderPass(m_device, &renderPassCreateInfo, nullptr, &renderPass));