From 9192d156d110f49cc4b6348b73c121886242767c Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sat, 1 Aug 2026 08:09:49 -0400 Subject: [PATCH] [Fix] (DirectVulkan): ReadPixels materializes pending clears before resolving the blit binding ResolveColorBlitBinding cached a RenderbufferResource*/TextureResource* (trackedLayout) before the pending-clear materialization step ran. For an attachment that had never been part of any render pass yet (e.g. a GL_NONE draw buffer slot read back via an explicit glReadBuffer), the materialize call was the first thing to touch its resource, and creating that entry in the UnorderedMap (FastSTL, open-addressing) can rehash and invalidate every previously-taken pointer into the map - including the one just cached. The read then saw a stale VK_IMAGE_LAYOUT_UNDEFINED and silently bailed (via a compiled-out MGLOG_E in release builds), leaving the client buffer untouched. Reordering so the clear is materialized first, then the binding resolved, guarantees the pointer reflects the final resource state. Fixes KHR-GL3{0,1,2,3}.draw_buffers.draw_buffers_1. --- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 976c9676..e41cd580 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -6982,11 +6982,14 @@ void main() { } const Bool readIsDefaultFbo = readFbo->IsDefaultFramebuffer(); - BlitImageBinding srcBinding{}; - if (!ResolveColorBlitBinding(*readFbo, true, m_imageIndexAcquired, m_swapchainObject, *m_textureManager, - *m_renderPassManager, srcBinding)) { - return; - } + // Materialize any pending clear on the read-buffer attachment BEFORE resolving the + // blit binding below: for a renderbuffer/texture that has never been part of any + // render pass yet (e.g. a GL_NONE draw buffer slot whose attachment is only ever + // touched via an explicit glReadBuffer), materializing lazily creates its backing + // Vulkan resource for the first time. UnorderedMap (FastSTL, open-addressing) may + // rehash on that insertion, invalidating any RenderbufferResource*/TextureResource* + // obtained beforehand - so ResolveColorBlitBinding's cached `trackedLayout` pointer + // must be taken AFTER this, never before it. if (!readIsDefaultFbo) { const auto& sourceAttachment = readFbo->GetAttachment(readFbo->GetReadBuffer()); auto sourceTexture = sourceAttachment.GetTexture(); @@ -7004,6 +7007,12 @@ void main() { } } + BlitImageBinding srcBinding{}; + if (!ResolveColorBlitBinding(*readFbo, true, m_imageIndexAcquired, m_swapchainObject, *m_textureManager, + *m_renderPassManager, srcBinding)) { + return; + } + const VkImageLayout srcOriginalLayout = readIsDefaultFbo ? m_swapchainObject.GetImageLayout(m_imageIndexAcquired) : *srcBinding.trackedLayout;