From 13e9d0df5cc7136925164cd8529fca70ddffc415 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 7 Nov 2026 08:08:48 -0400 Subject: [PATCH] [Fix] (MG_Backend/DirectVulkan): take a deferred window clear's sRGB decision at the glClear --- MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h | 7 ++++++- MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.cpp | 5 ++++- .../MG_Backend/DirectVulkan/Renderer/WireFramebuffer.cpp | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 7bc95d08..11209a6e 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -633,6 +633,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { Bool color = false; VkImageAspectFlags depthStencil = 0; ClearAttachmentPayload colorPayload{}; + // colorPayload against the window format and GL_FRAMEBUFFER_SRGB as they were at the + // glClear (PreCompensateSrgbClearColor): the standalone clear a present or another + // use of the window records later must not read that state again, after the verb. + ClearAttachmentPayload colorPayloadCompensated{}; ClearAttachmentPayload depthStencilPayload{}; Bool Pending() const { return color || depthStencil != 0; } }; @@ -642,8 +646,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { void MaterializeDefaultWirePendingClear(); void FoldDefaultWirePendingClear(RenderPassEntry& begun, Uint64& variantKey, VkClearValue* merged); // Records a clear of `area` of one wire image in a single-attachment pass of its own. + // `colorPreCompensated`: the payload already went through PreCompensateSrgbClearColor. void RecordWireImageClear(WireImage& image, VkImageAspectFlags aspect, const ClearAttachmentPayload& payload, - const VkRect2D& area, Bool textureSurface); + const VkRect2D& area, Bool textureSurface, Bool colorPreCompensated = false); static void NoteWirePendingClear(const WireImage& image, VkImageAspectFlags aspects, const VkClearValue& value); VkRenderPass WireClearVariant(RenderPassEntry& begun, Uint64 variantKey); Bool BeginWireDrawPassFolding(FrameContext::FrameData& frame, RenderPassEntry& begun, Uint64 variantKey, diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.cpp index 26de5086..69906b20 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireDraw.cpp @@ -1464,6 +1464,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { if (color) { pending.color = true; pending.colorPayload = payload; + pending.colorPayloadCompensated = payload; + PreCompensateSrgbClearColor(pending.colorPayloadCompensated, m_swapchainObject.GetSurfaceFormat().format); m_swapchainObject.SetImageContentDefined(index, true); } if (depthStencil & VK_IMAGE_ASPECT_DEPTH_BIT) pending.depthStencilPayload.depth = payload.depth; @@ -1494,7 +1496,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { image.image = m_swapchainObject.GetImage(pending.swapchainImageIndex); image.format = m_swapchainObject.GetSurfaceFormat().format; image.layout = m_swapchainObject.GetImageLayout(pending.swapchainImageIndex); - RecordWireImageClear(image, VK_IMAGE_ASPECT_COLOR_BIT, pending.colorPayload, area, false); + RecordWireImageClear(image, VK_IMAGE_ASPECT_COLOR_BIT, pending.colorPayloadCompensated, area, false, + /*colorPreCompensated=*/true); } if (pending.depthStencil && m_swapchainObject.GetDepthStencilImage(pending.swapchainImageIndex)) { image.aspect = pending.depthStencil; diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.cpp index d773d5f7..331228ba 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/WireFramebuffer.cpp @@ -1115,7 +1115,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { void VulkanRenderer::RecordWireImageClear(WireImage& image, VkImageAspectFlags aspect, const ClearAttachmentPayload& payload, const VkRect2D& area, - Bool textureSurface) { + Bool textureSurface, Bool colorPreCompensated) { const Bool color = aspect == VK_IMAGE_ASPECT_COLOR_BIT; const auto layout = color ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -1168,7 +1168,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { begin.framebuffer = fb; begin.renderArea = area; auto clearPayload = payload; - if (color) PreCompensateSrgbClearColor(clearPayload, image.format); + if (color && !colorPreCompensated) PreCompensateSrgbClearColor(clearPayload, image.format); VkClearAttachment clear{}; clear.aspectMask = aspect; clear.clearValue.color = MakeVkClearColorValue(clearPayload, false);