mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 05:38:31 +09:00
[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:
@@ -531,6 +531,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
if (currentFBO.get() == lastUpdatedFBO) {
|
if (currentFBO.get() == lastUpdatedFBO) {
|
||||||
MGLOG_D("Draw FBO and read FBO are the same, skipping sync.");
|
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_fboSyncedObjectVersions[SizeT(target)] = objectVersion;
|
||||||
g_fboSyncedObjects[SizeT(target)] = currentPtr;
|
g_fboSyncedObjects[SizeT(target)] = currentPtr;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -2535,6 +2535,28 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BackendFramebufferObject::SyncReadBufferToBackend(
|
||||||
|
const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject) {
|
||||||
|
if (!stateFBOObject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto frontendReadBuf = stateFBOObject->GetReadBuffer();
|
||||||
|
if (frontendReadBuf == m_frontendReadBuffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_frontendReadBuffer = frontendReadBuf;
|
||||||
|
|
||||||
|
GLenum glBackendReadBuffer = GetBackendAttachmentType(frontendReadBuf);
|
||||||
|
if (m_backendReadBuffer != glBackendReadBuffer) {
|
||||||
|
m_backendReadBuffer = glBackendReadBuffer;
|
||||||
|
// glReadBuffer targets whatever FBO is bound to GL_READ_FRAMEBUFFER. When this is
|
||||||
|
// reached from SyncCurrentFBO's "same FBO as draw" skip path the backend FBO was
|
||||||
|
// only bound as DRAW, so bind it as READ first to route the read buffer correctly.
|
||||||
|
Bind(FramebufferTarget::Read);
|
||||||
|
g_GLESFuncs.glReadBuffer(glBackendReadBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BackendFramebufferObject::SyncToBackend(
|
void BackendFramebufferObject::SyncToBackend(
|
||||||
const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject, FramebufferTarget asTarget) {
|
const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject, FramebufferTarget asTarget) {
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
@@ -2616,16 +2638,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
// 2. Remap read buffer. glReadBuffer writes the READ-bound FBO's state, so
|
// 2. Remap read buffer. glReadBuffer writes the READ-bound FBO's state, so
|
||||||
// only apply (and stamp the memo) when this object is bound as READ.
|
// only apply (and stamp the memo) when this object is bound as READ.
|
||||||
auto frontendReadBuf = stateFBOObject->GetReadBuffer();
|
if (asTarget == FramebufferTarget::Read) {
|
||||||
if (frontendReadBuf != m_frontendReadBuffer && asTarget == FramebufferTarget::Read) {
|
SyncReadBufferToBackend(stateFBOObject);
|
||||||
m_frontendReadBuffer = frontendReadBuf;
|
|
||||||
|
|
||||||
GLenum glBackendReadBuffer = GetBackendAttachmentType(frontendReadBuf);
|
|
||||||
|
|
||||||
if (m_backendReadBuffer != glBackendReadBuffer) {
|
|
||||||
m_backendReadBuffer = glBackendReadBuffer;
|
|
||||||
g_GLESFuncs.glReadBuffer(glBackendReadBuffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------- Attach texture to backend FBO -----------------------
|
// -------------------- Attach texture to backend FBO -----------------------
|
||||||
|
|||||||
@@ -375,6 +375,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
BackendFramebufferObject();
|
BackendFramebufferObject();
|
||||||
void SyncToBackend(const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject,
|
void SyncToBackend(const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject,
|
||||||
FramebufferTarget asTarget);
|
FramebufferTarget asTarget);
|
||||||
|
// Apply only this FBO's read buffer (glReadBuffer) to the backend. Split out so it can
|
||||||
|
// still run when SyncCurrentFBO skips the READ-target sync because the same GL FBO is
|
||||||
|
// bound as both draw and read (otherwise glReadBuffer changes would be silently dropped).
|
||||||
|
void SyncReadBufferToBackend(const SharedPtr<MG_State::GLState::FramebufferObject>& stateFBOObject);
|
||||||
void InvalidateSyncedState();
|
void InvalidateSyncedState();
|
||||||
Uint GetBackendFramebufferId() const { return m_backendFBOId; }
|
Uint GetBackendFramebufferId() const { return m_backendFBOId; }
|
||||||
void Bind(FramebufferTarget target) const;
|
void Bind(FramebufferTarget target) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user