[Feat] (MG_Backend/DirectGLES): Implement ClearBuffer* in backend.

This commit is contained in:
BZLZHH
2025-12-14 12:06:48 +08:00
parent 5071a98e00
commit de028204a2
4 changed files with 319 additions and 131 deletions
+177 -5
View File
@@ -440,10 +440,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Bind texture object // Bind texture object
auto target = textureObject->GetTarget(); auto target = textureObject->GetTarget();
if (target == TextureTarget::Texture1D || if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle ||
target == TextureTarget::TextureRectangle || target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray ||
target == TextureTarget::Texture1DArray || target == TextureTarget::Texture3D || target == TextureTarget::Texture3D || target == TextureTarget::Texture2DMultisample ||
target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray) { target == TextureTarget::Texture2DArray) {
MGLOG_D(" Texture target %s is not supported, skipping.", MGLOG_D(" Texture target %s is not supported, skipping.",
MG_Util::ConvertTextureTargetToString(target).c_str()); MG_Util::ConvertTextureTargetToString(target).c_str());
continue; continue;
@@ -511,7 +511,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Connect program ubo index to backend binding point // Connect program ubo index to backend binding point
auto binding = currentProgram->GetUniformBlockBinding(i); auto binding = currentProgram->GetUniformBlockBinding(i);
auto& name = currentProgram->GetUniformBlockName(i); auto& name = currentProgram->GetUniformBlockName(i);
GLuint backendBlkIdx = MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str()); GLuint backendBlkIdx =
MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str());
MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding); MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding);
// Connect buffer to backend binding point // Connect buffer to backend binding point
@@ -932,4 +933,175 @@ namespace MobileGL::MG_Backend::DirectGLES {
const GLubyte* GetString(GLenum name) { const GLubyte* GetString(GLenum name) {
return MG_External::GLES::glGetString(name); return MG_External::GLES::glGetString(name);
} }
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
MG_External::GLES::glClearBufferfi(buffer, drawbuffer, depth, stencil);
}
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
return;
}
auto backendFBO = backendFBOIt->second;
GLint realDrawbuffer = drawbuffer;
if (buffer == GL_COLOR) {
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
return;
}
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
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) {
if (drawbuffer != 0) {
MGLOG_W("Depth/stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
}
realDrawbuffer = 0;
}
MG_External::GLES::glClearBufferfv(buffer, realDrawbuffer, value);
}
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
return;
}
auto backendFBO = backendFBOIt->second;
GLint realDrawbuffer = drawbuffer;
if (buffer == GL_COLOR) {
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
return;
}
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
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_STENCIL) {
if (drawbuffer != 0) {
MGLOG_W("Stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer);
}
realDrawbuffer = 0;
}
MG_External::GLES::glClearBufferiv(buffer, realDrawbuffer, value);
}
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
TextureImpl::SyncNeccessaryTextures();
FramebufferImpl::SyncCurrentFBO();
RenderStateImpl::SyncRenderState();
BindCurrentFBO(FramebufferTarget::Draw);
auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject());
if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) {
MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer.");
return;
}
auto backendFBO = backendFBOIt->second;
GLint realDrawbuffer = drawbuffer;
if (buffer == GL_COLOR) {
auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers();
if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MGLOG_E("Invalid drawbuffer index: %d", drawbuffer);
return;
}
FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer];
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 {
MGLOG_E("ClearBufferuiv can only be used with GL_COLOR buffer, got %s",
MG_Util::ConvertGLEnumToString(buffer).c_str());
return;
}
MG_External::GLES::glClearBufferuiv(buffer, realDrawbuffer, value);
}
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
@@ -6,6 +6,10 @@
operation Utils::CheckGLESError(); operation Utils::CheckGLESError();
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value);
void Clear(GLbitfield mask); void Clear(GLbitfield mask);
void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices); void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
void DrawArrays(GLenum mode, GLint first, GLsizei count); void DrawArrays(GLenum mode, GLint first, GLsizei count);
+21 -11
View File
@@ -306,8 +306,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto targetInternal = stateTextureObject->GetTarget(); auto targetInternal = stateTextureObject->GetTarget();
MGLOG_D(" Texture target for syncing is %s", MGLOG_D(" Texture target for syncing is %s",
MG_Util::ConvertTextureTargetToString(targetInternal).c_str()); MG_Util::ConvertTextureTargetToString(targetInternal).c_str());
if (targetInternal == TextureTarget::Texture1D || if (targetInternal == TextureTarget::Texture1D || targetInternal == TextureTarget::TextureRectangle ||
targetInternal == TextureTarget::TextureRectangle ||
targetInternal == TextureTarget::Texture2DMultisampleArray || targetInternal == TextureTarget::Texture2DMultisampleArray ||
targetInternal == TextureTarget::Texture1DArray || targetInternal == TextureTarget::Texture3D || targetInternal == TextureTarget::Texture1DArray || targetInternal == TextureTarget::Texture3D ||
targetInternal == TextureTarget::Texture2DMultisample || targetInternal == TextureTarget::Texture2DMultisample ||
@@ -334,12 +333,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str());
}); });
const auto baseSize = stateTextureObject->GetBaseSize(); const auto baseSize = stateTextureObject->GetBaseSize();
StateTextureBasicInfo currentTextureInfo = { StateTextureBasicInfo currentTextureInfo = {stateTextureObject->GetFormat(),
stateTextureObject->GetFormat(), static_cast<SizeT>(baseSize.x()), static_cast<SizeT>(baseSize.y()), static_cast<SizeT>(baseSize.x()),
static_cast<SizeT>(baseSize.z()), 0, 0}; static_cast<SizeT>(baseSize.y()),
static_cast<SizeT>(baseSize.z()),
0,
0};
switch (stateTextureObject->GetStorageType()) { switch (stateTextureObject->GetStorageType()) {
case TextureStorageType::Mipmap: { case TextureStorageType::Mipmap: {
auto* textureMipmapObject = static_cast<MG_State::GLState::TextureObjectMipmap*>(stateTextureObject.get()); auto* textureMipmapObject =
static_cast<MG_State::GLState::TextureObjectMipmap*>(stateTextureObject.get());
const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount(); const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount();
currentTextureInfo.mipmapLevels = mipmapCount; currentTextureInfo.mipmapLevels = mipmapCount;
@@ -376,8 +379,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat, MG_External::GLES::glTexImage2D(glUploadTarget, static_cast<GLint>(level), glInternalFormat,
static_cast<GLsizei>(levelTexelSize.x()), static_cast<GLsizei>(levelTexelSize.x()),
static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat, glType, static_cast<GLsizei>(levelTexelSize.y()), 0, glFormat,
pData); glType, pData);
// TODO: handle more texture types // TODO: handle more texture types
@@ -426,14 +429,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
break; break;
} }
case TextureStorageType::Buffer: { case TextureStorageType::Buffer: {
auto* textureBufferObject = static_cast<MG_State::GLState::TextureObjectBuffer*>(stateTextureObject.get()); auto* textureBufferObject =
static_cast<MG_State::GLState::TextureObjectBuffer*>(stateTextureObject.get());
auto& slot = textureBufferObject->GetBufferBindingSlot(); auto& slot = textureBufferObject->GetBufferBindingSlot();
auto buffer = slot.GetBoundObject(); auto buffer = slot.GetBoundObject();
auto bufferIndex = buffer->GetExternalIndex(); auto bufferIndex = buffer->GetExternalIndex();
currentTextureInfo.bufferExternalIndex = bufferIndex; currentTextureInfo.bufferExternalIndex = bufferIndex;
Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo); Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo);
MGLOG_D("Texture state changed significantly or not initialized, regenerating texture (tex buffer) with ID: %u", MGLOG_D("Texture state changed significantly or not initialized, regenerating texture (tex buffer) "
"with ID: %u",
m_backendTextureId); m_backendTextureId);
// Need to sync texture buffer if not synced yet // Need to sync texture buffer if not synced yet
@@ -458,7 +463,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId); MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId);
break; break;
} }
default: THROW_UNIMPL_EXCEPTION; default:
THROW_UNIMPL_EXCEPTION;
} }
{ // Update built-in sampler parameters { // Update built-in sampler parameters
@@ -702,6 +708,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
FramebufferAttachmentType BackendFramebufferObject::GetCompactedAttachmentTypeAtDrawBufferIndex(Int index) {
return m_compactedFrontendDrawBuffers[index];
}
UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>> UnorderedMap<SharedPtr<MG_State::GLState::FramebufferObject>, SharedPtr<BackendFramebufferObject>>
g_backendFramebufferObjects; g_backendFramebufferObjects;
} // namespace FramebufferImpl } // namespace FramebufferImpl
+3 -1
View File
@@ -58,7 +58,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
bool operator==(const StateTextureBasicInfo& other) const { bool operator==(const StateTextureBasicInfo& other) const {
return internalFormat == other.internalFormat && width == other.width && height == other.height && return internalFormat == other.internalFormat && width == other.width && height == other.height &&
depth == other.depth && mipmapLevels == other.mipmapLevels && bufferExternalIndex == other.bufferExternalIndex; depth == other.depth && mipmapLevels == other.mipmapLevels &&
bufferExternalIndex == other.bufferExternalIndex;
} }
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); } bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
@@ -94,6 +95,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferTarget asTarget); FramebufferTarget asTarget);
Uint GetBackendFramebufferId() { return m_backendFBOId; } Uint GetBackendFramebufferId() { return m_backendFBOId; }
void Bind(FramebufferTarget target); void Bind(FramebufferTarget target);
FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index);
private: private:
Uint m_backendFBOId = 0; Uint m_backendFBOId = 0;