[Fix] (DirectGLES): apply the read buffer when one FBO is bound as both draw and read

- SyncCurrentFBO skips the READ-target pass when the same GL FBO is bound as
  both draw and read (the common GL_FRAMEBUFFER case), but the read buffer
  (glReadBuffer) is only applied inside SyncToBackend's READ path — so the skip
  silently dropped every glReadBuffer change, leaving the backend read buffer
  stuck at COLOR_ATTACHMENT0.
- Extract the read-buffer application into BackendFramebufferObject::
  SyncReadBufferToBackend and invoke it from the skip branch (target == Read)
  as well as from SyncToBackend, so reads always target the right attachment.
- Bind the backend FBO as READ inside the helper before glReadBuffer, since the
  skip path only bound it as DRAW.
- Fixes KHR-GL3x.draw_buffers.draw_buffers_1 (reading COLOR_ATTACHMENT1 while
  the FBO stays GL_FRAMEBUFFER-bound returned attachment 0's value); the render
  was already correct, only the readback resolved the wrong attachment.
This commit is contained in:
2026-07-21 12:18:55 -04:00
parent 3049c4b82b
commit bc2d698b3e
3 changed files with 40 additions and 10 deletions
@@ -531,6 +531,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (currentFBO.get() == lastUpdatedFBO) {
MGLOG_D("Draw FBO and read FBO are the same, skipping sync.");
// The attachment/draw-buffer work was already done for this GL FBO as the DRAW
// target, but the read buffer (glReadBuffer) is READ-target-specific and would
// be dropped by this skip. Apply it so reads target the right attachment (e.g.
// KHR-GL33.draw_buffers reads each COLOR_ATTACHMENT while the FBO stays bound as
// GL_FRAMEBUFFER — without this every glReadBuffer is a no-op and all reads hit
// COLOR_ATTACHMENT0).
if (target == FramebufferTarget::Read) {
const auto& syncedFBOIt = g_backendFramebufferObjects.find(currentFBO.get());
if (syncedFBOIt != g_backendFramebufferObjects.end() && syncedFBOIt->second) {
syncedFBOIt->second->SyncReadBufferToBackend(currentFBO);
}
}
g_fboSyncedObjectVersions[SizeT(target)] = objectVersion;
g_fboSyncedObjects[SizeT(target)] = currentPtr;
continue;