[Fix] (DirectGLES): retry a failed blit's colour and depth/stencil aspects independently

This commit is contained in:
2026-08-20 04:31:22 -04:00
parent bbc7b9ca84
commit 261cfd1591
+38 -8
View File
@@ -4646,17 +4646,47 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
return; return;
} }
if (readSamples <= 0 || drawSamples > 0 || (mask & GL_COLOR_BUFFER_BIT) == 0) { // The combined call raised an error, so by GL 4.6 2.3.1 it wrote nothing at all: BOTH
return; // aspect groups still owe their copy, and each has to be retried on its own. Re-issuing
} // the depth/stencil half only as a rider on a SUCCESSFUL colour resolve dropped it
if (ResolveThenBlit(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, filter) && // silently whenever the colour half could not be emulated - and on a framebuffer whose
(mask & ~static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT)) != 0) { // only attachment is depth it never can, because the colour emulation has no attachment
DrainBlitErrors(); // to take a format from (KHR-GL33.framebuffer_blit's depth config test blits
g_GLESFuncs.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, // COLOR|DEPTH|STENCIL across depth-only framebuffers and kept reading the clear value).
mask & ~static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT), filter); const GLbitfield colourBit = mask & static_cast<GLbitfield>(GL_COLOR_BUFFER_BIT);
const GLbitfield dsBits = mask & static_cast<GLbitfield>(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// The colour group's one emulation is the multisample resolve that also converts format,
// which is the shape this names. It used to double as an early-out for the whole
// function, which is what cost a depth-only mask its single-aspect retry.
const Bool multisampleResolve = readSamples > 0 && drawSamples <= 0;
if (colourBit != 0) {
DrainBlitErrors(); DrainBlitErrors();
g_GLESFuncs.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, colourBit, filter);
if (g_GLESFuncs.glGetError() != GL_NO_ERROR) {
const Bool emulated =
multisampleResolve &&
ResolveThenBlit(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, filter);
if (!emulated) {
MGLOG_E_ONCE("BlitFramebuffer: the colour aspect was dropped - the driver rejected it on its "
"own and no emulation applies");
} }
} }
}
if (dsBits != 0) {
DrainBlitErrors();
g_GLESFuncs.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, dsBits, filter);
if (g_GLESFuncs.glGetError() != GL_NO_ERROR) {
// Nothing to fall back on yet: ResolveThenBlit is colour-only and the replicate
// pass runs in the opposite direction, so a driver that declines a multisample
// depth/stencil resolve leaves the destination holding its clear value. The log
// is the whole diagnostic - the frontend performs no validation of its own, so
// this never reaches the application as a GL error.
MGLOG_E_ONCE("BlitFramebuffer: the depth/stencil aspect was dropped - the driver rejected it on "
"its own and no emulation applies");
}
}
DrainBlitErrors();
}
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1,
GLint dstY1, GLbitfield mask, GLenum filter) { GLint dstY1, GLbitfield mask, GLenum filter) {