mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 13:48:30 +09:00
[Fix] (MG_Backend/DirectGLES): re-implement FBO sync, attachment remapping
This commit is contained in:
@@ -998,44 +998,26 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
RenderStateImpl::SyncRenderState();
|
RenderStateImpl::SyncRenderState();
|
||||||
|
|
||||||
BindCurrentFBO(FramebufferTarget::Draw);
|
BindCurrentFBO(FramebufferTarget::Draw);
|
||||||
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
// auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
// MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
||||||
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
// if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
||||||
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
// MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
auto backendFBO = backendFBOIt->second;
|
// auto backendFBO = backendFBOIt->second;
|
||||||
|
|
||||||
GLint realDrawbuffer = drawbuffer;
|
GLint realDrawbuffer = drawbuffer;
|
||||||
|
|
||||||
if (buffer == GL_COLOR) {
|
if (buffer == GL_COLOR) {
|
||||||
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
// auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
||||||
|
|
||||||
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||||
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
// since `drawbuffer` indicates an index into draw buffer array,
|
||||||
|
// using GL value directly is OK.
|
||||||
if (attachmentType == FramebufferAttachmentType::None) {
|
|
||||||
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bool found = false;
|
|
||||||
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
|
||||||
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
|
||||||
realDrawbuffer = i;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (buffer == GL_DEPTH || buffer == GL_STENCIL) {
|
} else if (buffer == GL_DEPTH || buffer == GL_STENCIL) {
|
||||||
if (drawbuffer != 0) {
|
if (drawbuffer != 0) {
|
||||||
MGLOG_W("Depth/stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
|
MGLOG_W("Depth/stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
|
||||||
@@ -1051,44 +1033,44 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
RenderStateImpl::SyncRenderState();
|
RenderStateImpl::SyncRenderState();
|
||||||
|
|
||||||
BindCurrentFBO(FramebufferTarget::Draw);
|
BindCurrentFBO(FramebufferTarget::Draw);
|
||||||
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
// auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
// MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
||||||
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
// if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
||||||
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
// MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
auto backendFBO = backendFBOIt->second;
|
// auto backendFBO = backendFBOIt->second;
|
||||||
|
|
||||||
GLint realDrawbuffer = drawbuffer;
|
GLint realDrawbuffer = drawbuffer;
|
||||||
|
|
||||||
if (buffer == GL_COLOR) {
|
if (buffer == GL_COLOR) {
|
||||||
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
// auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
||||||
|
|
||||||
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||||
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
// FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
||||||
|
|
||||||
if (attachmentType == FramebufferAttachmentType::None) {
|
// if (attachmentType == FramebufferAttachmentType::None) {
|
||||||
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
// MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Bool found = false;
|
// Bool found = false;
|
||||||
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
// for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
||||||
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
// if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
||||||
realDrawbuffer = i;
|
// realDrawbuffer = i;
|
||||||
found = true;
|
// found = true;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!found) {
|
// if (!found) {
|
||||||
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
// MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
} else if (buffer == GL_STENCIL) {
|
} else if (buffer == GL_STENCIL) {
|
||||||
if (drawbuffer != 0) {
|
if (drawbuffer != 0) {
|
||||||
MGLOG_W("Stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
|
MGLOG_W("Stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
|
||||||
@@ -1105,44 +1087,44 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
RenderStateImpl::SyncRenderState();
|
RenderStateImpl::SyncRenderState();
|
||||||
|
|
||||||
BindCurrentFBO(FramebufferTarget::Draw);
|
BindCurrentFBO(FramebufferTarget::Draw);
|
||||||
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
// auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
// MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
|
||||||
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
// if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
|
||||||
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
// MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
auto backendFBO = backendFBOIt->second;
|
// auto backendFBO = backendFBOIt->second;
|
||||||
|
|
||||||
GLint realDrawbuffer = drawbuffer;
|
GLint realDrawbuffer = drawbuffer;
|
||||||
|
|
||||||
if (buffer == GL_COLOR) {
|
if (buffer == GL_COLOR) {
|
||||||
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
// auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
|
||||||
|
|
||||||
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
|
||||||
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
// FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
|
||||||
|
|
||||||
if (attachmentType == FramebufferAttachmentType::None) {
|
// if (attachmentType == FramebufferAttachmentType::None) {
|
||||||
MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
// MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Bool found = false;
|
// Bool found = false;
|
||||||
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
// for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
|
||||||
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
// if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
|
||||||
realDrawbuffer = i;
|
// realDrawbuffer = i;
|
||||||
found = true;
|
// found = true;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!found) {
|
// if (!found) {
|
||||||
MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
// MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast<int>(attachmentType));
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
} else {
|
} else {
|
||||||
MGLOG_E("ClearBufferuiv can only be used with GL_COLOR buffer, got %s",
|
MGLOG_E("ClearBufferuiv can only be used with GL_COLOR buffer, got %s",
|
||||||
MG_Util::ConvertGLEnumToString(buffer).c_str());
|
MG_Util::ConvertGLEnumToString(buffer).c_str());
|
||||||
|
|||||||
@@ -850,24 +850,47 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget);
|
GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget);
|
||||||
Bind(asTarget);
|
Bind(asTarget);
|
||||||
|
|
||||||
// connect attachments (set buffers)
|
// -------------------- Connect attachments (set buffers) -----------------------
|
||||||
// TODO: remapping
|
// 1. Remap draw buffers
|
||||||
auto& stateDrawBuffers = stateFBOObject->GetDrawBuffers();
|
auto& stateDrawBuffers = stateFBOObject->GetDrawBuffers();
|
||||||
Bool drawBufferDirty = false;
|
Bool drawBufferClean = false;
|
||||||
for (GLint i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; ++i) {
|
if (memcmp(m_frontendDrawBuffers, stateDrawBuffers.data(),
|
||||||
auto currentBuf = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(stateDrawBuffers[i]);
|
FramebufferObject::MAX_DRAW_BUFFERS * sizeof(FramebufferAttachmentType)) == 0) {
|
||||||
if (m_backendDrawBuffers[i] != currentBuf)
|
drawBufferClean = true;
|
||||||
drawBufferDirty = true;
|
|
||||||
m_backendDrawBuffers[i] = currentBuf;
|
|
||||||
}
|
}
|
||||||
if (drawBufferDirty)
|
|
||||||
MG_External::GLES::glDrawBuffers(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS, m_backendDrawBuffers);
|
|
||||||
|
|
||||||
auto currentReadBuf = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(stateFBOObject->GetReadBuffer());
|
if (!drawBufferClean) {
|
||||||
if (m_backendReadBuffer != currentReadBuf)
|
memcpy(m_frontendDrawBuffers, stateDrawBuffers.data(),
|
||||||
MG_External::GLES::glReadBuffer(m_backendReadBuffer);
|
FramebufferObject::MAX_DRAW_BUFFERS * sizeof(FramebufferAttachmentType));
|
||||||
|
std::fill(m_backendDrawBuffers, m_backendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, GL_NONE);
|
||||||
|
int nEffectiveBuffers = 0;
|
||||||
|
for (GLint i = 0; i < FramebufferObject::MAX_DRAW_BUFFERS; ++i) {
|
||||||
|
if (stateDrawBuffers[i] == FramebufferAttachmentType::None) {
|
||||||
|
m_backendDrawBuffers[i] = GL_NONE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// attach texture to fbo
|
// Create compacted mapping
|
||||||
|
m_backendDrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
|
||||||
|
nEffectiveBuffers = i + 1;
|
||||||
|
}
|
||||||
|
MG_External::GLES::glDrawBuffers(nEffectiveBuffers, m_backendDrawBuffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Remap read buffer
|
||||||
|
auto frontendReadBuf = stateFBOObject->GetReadBuffer();
|
||||||
|
if (frontendReadBuf != m_frontendReadBuffer) {
|
||||||
|
m_frontendReadBuffer = frontendReadBuf;
|
||||||
|
|
||||||
|
GLenum glBackendReadBuffer = GetBackendAttachmentType(frontendReadBuf);
|
||||||
|
|
||||||
|
if (m_backendReadBuffer != glBackendReadBuffer) {
|
||||||
|
m_backendReadBuffer = glBackendReadBuffer;
|
||||||
|
MG_External::GLES::glReadBuffer(glBackendReadBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------- Attach texture to backend FBO -----------------------
|
||||||
// TODO: attach according to remapped
|
// TODO: attach according to remapped
|
||||||
const auto& attachments = stateFBOObject->GetAllAttachmentObjects();
|
const auto& attachments = stateFBOObject->GetAllAttachmentObjects();
|
||||||
const auto& attachmentVersions = stateFBOObject->GetAllFramebufferAttachmentVersions();
|
const auto& attachmentVersions = stateFBOObject->GetAllFramebufferAttachmentVersions();
|
||||||
@@ -885,8 +908,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferAttachmentType BackendFramebufferObject::GetCompactedAttachmentTypeAtDrawBufferIndex(Int index) {
|
GLenum BackendFramebufferObject::GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const {
|
||||||
return m_compactedFrontendDrawBuffers[index];
|
GLenum glBackendReadBuffer = GL_NONE;
|
||||||
|
auto it = std::find(m_frontendDrawBuffers,
|
||||||
|
m_frontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, frontendAtt);
|
||||||
|
Bool notFound = (it == m_frontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS);
|
||||||
|
if (notFound) {
|
||||||
|
MGLOG_D("%s: frontendAtt not found in draw buffer (probably not remapped), just use the same as frontend", __func__);
|
||||||
|
glBackendReadBuffer = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(frontendAtt);
|
||||||
|
} else {
|
||||||
|
MGLOG_D("%s: frontendAtt found in draw buffer, keep it consistent as in read buffers", __func__);
|
||||||
|
auto index = std::distance(m_frontendDrawBuffers, it);
|
||||||
|
glBackendReadBuffer = m_backendDrawBuffers[index];
|
||||||
|
}
|
||||||
|
return glBackendReadBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
|
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
bool SyncAttachmentObject(GLenum glFBOTarget,
|
bool SyncAttachmentObject(GLenum glFBOTarget,
|
||||||
const MG_State::GLState::FramebufferAttachmentObject& attachmentObject,
|
const MG_State::GLState::FramebufferAttachmentObject& attachmentObject,
|
||||||
GLenum glBackendAttachment);
|
GLenum glBackendAttachment);
|
||||||
FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
|
// FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
|
||||||
|
GLenum GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const;
|
||||||
private:
|
private:
|
||||||
Uint m_backendFBOId = 0;
|
Uint m_backendFBOId = 0;
|
||||||
|
|
||||||
@@ -146,17 +146,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
*/
|
*/
|
||||||
FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
|
FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
|
||||||
FramebufferAttachmentType::None};
|
FramebufferAttachmentType::None};
|
||||||
/* this will save buffers in its compacted GL form,
|
|
||||||
not consecutive is not allowed
|
|
||||||
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT5, COLOR_ATTACHMENT4]
|
|
||||||
(no GL_NONE among those)
|
|
||||||
*/
|
|
||||||
FramebufferAttachmentType
|
|
||||||
m_compactedFrontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {
|
|
||||||
FramebufferAttachmentType::None};
|
|
||||||
/* this will save buffers in stricter ES rules
|
/* this will save buffers in stricter ES rules
|
||||||
reversion, absence or not consecutive are not allowed, according to ES spec
|
reversion, absence or not consecutive are not allowed, according to ES spec
|
||||||
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, NONE, ...]
|
i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, COLOR_ATTACHMENT3, ...]
|
||||||
this array could be provided as data directly to ES `glDrawBuffers` function
|
this array could be provided as data directly to ES `glDrawBuffers` function
|
||||||
*/
|
*/
|
||||||
GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE};
|
GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE};
|
||||||
|
|||||||
Reference in New Issue
Block a user