From ef1924d7f960573205b2a5b59558e7e426fddebc Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 5 Nov 2025 15:37:10 +0800 Subject: [PATCH] [Feat] (MG_State/Program, DirectGLES): plumb ubo to backend --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 61 +++++++++++++++---- MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp | 4 +- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 14 +++++ .../GLState/BufferState/BufferState.h | 7 ++- MobileGL/MG_State/GLState/Core.h | 3 + .../GLState/ProgramState/ProgramObject.cpp | 3 + .../GLState/ProgramState/ProgramObject.h | 4 ++ 7 files changed, 82 insertions(+), 14 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 04957685..d3af7173 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -15,6 +15,7 @@ namespace MobileGL::MG_Backend::DirectGLES { void SyncNeccessaryBuffers() { // All buffers we need are: // 1.VBOs 2.IBO 3.UBOs (TODO) 4.SSBOs (TODO) + Vector> buffersToSync; const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); if (!currentVAOObject) { @@ -22,6 +23,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } + // VBO for (const auto& attrib : currentVAOObject->GetAllAttributes()) { if (!attrib.Enabled) continue; const auto& bufferObject = attrib.Buffer; @@ -29,11 +31,24 @@ namespace MobileGL::MG_Backend::DirectGLES { buffersToSync.push_back(bufferObject); } } + + // IBO const auto& possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject(); if (possibleIBO) { buffersToSync.push_back(possibleIBO); } + // UBO + auto uboBindingPointCnt = MG_State::pGLContext->GetBufferBindingPointCount(BufferTarget::Uniform); + for (SizeT i = 0; i < uboBindingPointCnt; ++i) { + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i); + auto obj = point.GetBoundObject(); + if (obj) + buffersToSync.push_back(obj); + } + + + // PBO const auto& pbo = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); if (pbo) { buffersToSync.push_back(pbo); @@ -300,20 +315,44 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(currentProgram); if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) { backendProgramIt->second->Use(); - // UBO - MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, backendProgramIt->second->GetBackendGlobalUBOId()); - MG_External::GLES::glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(), - currentProgram->MapUBO()); - MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0); + auto backendProgramId = backendProgramIt->second->GetBackendProgramId(); + // Global UBO + if (currentProgram->GetUBOSize() > 0) { + MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, backendProgramIt->second->GetBackendGlobalUBOId()); + MG_External::GLES::glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(), + currentProgram->MapUBO()); + MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0); - Uint blockIndex = MG_External::GLES::glGetUniformBlockIndex( - backendProgramIt->second->GetBackendProgramId(), MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME); + Uint blockIndex = MG_External::GLES::glGetUniformBlockIndex( + backendProgramId, MG_Util::ShaderTranspiler::GLOBAL_UBO_NAME); - MG_External::GLES::glUniformBlockBinding(backendProgramIt->second->GetBackendProgramId(), blockIndex, - 0); + MG_External::GLES::glUniformBlockBinding(backendProgramId, blockIndex, 0); - MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, 0, - backendProgramIt->second->GetBackendGlobalUBOId()); + MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, 0, + backendProgramIt->second->GetBackendGlobalUBOId()); + } + // Normal UBO + auto uboCount = currentProgram->GetActiveUniformBlocksCount(); + for (Int i = 0; i < uboCount; ++i) { + // state binding point == backend binding point + + // Connect program ubo index to backend binding point + auto binding = currentProgram->GetUniformBlockBinding(i); + auto& name = currentProgram->GetUniformBlockName(i); + GLuint backendBlkIdx = MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str()); + MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, binding); + + // Connect buffer to backend binding point + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding); + auto bufferObj = point.GetBoundObject(); + auto range = point.GetRange(); + if (range.end > bufferObj->GetSize()) { + MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, binding, BufferImpl::g_backendBufferObjects[bufferObj]->GetBackendBufferId()); + } else { + MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, binding, BufferImpl::g_backendBufferObjects[bufferObj]->GetBackendBufferId(), + range.start, range.end - range.start); + } + } // Sampler unit binding auto maxUniformLoc = currentProgram->GetMaxUniformLocation(); diff --git a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp index 7841d573..5c357b85 100644 --- a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp @@ -494,7 +494,7 @@ namespace MobileGL { return MG_State::pGLContext->ValidateBufferObject(buffer) ? GL_TRUE : GL_FALSE; } - void BindBufferBase_State(GLenum target, GLuint index, GLuint buffer) { + void BindBufferBase_State(GLenum target, GLuint pointIndex, GLuint buffer) { BufferTarget bufferTarget = MG_Util::ConvertGLEnumToBufferTarget(target); if (!BufferImpl::ValidateBufferBindingPointTarget(bufferTarget)) return; @@ -504,7 +504,7 @@ namespace MobileGL { bufferObject = MG_State::pGLContext->GetBufferObject(buffer); } - auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, index); + auto& point = MG_State::pGLContext->GetBufferBindingPoint(bufferTarget, pointIndex); point.Bind(bufferObject); point.ClearRange(); } diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 6c2ba384..3d07d90b 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -99,6 +99,7 @@ namespace MobileGL { auto programObject = TryToGetProgramObject(program); if (!programObject) return; + MGLOG_D("%s: loc %02d = \"%s\"", __func__, index, name); programObject->SetExplicitAttribLocation(index, name); } @@ -231,43 +232,55 @@ namespace MobileGL { switch (pname) { case GL_DELETE_STATUS: *params = programObject->GetDeleteStatus(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_LINK_STATUS: *params = programObject->GetLinkStatus(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_VALIDATE_STATUS: *params = programObject->GetValidateStatus(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_INFO_LOG_LENGTH: { const auto& log = programObject->GetInfoLog(); *params = log.length(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; } case GL_ATTACHED_SHADERS: { const auto& attachedShaders = programObject->GetAttachedShaders(); *params = attachedShaders.size(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; } case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS: *params = programObject->GetActiveAtomicCounterCount(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_ACTIVE_ATTRIBUTES: *params = programObject->GetActiveAttributesCount(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: *params = programObject->GetActiveAttributesMaxLength(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_ACTIVE_UNIFORMS: *params = programObject->GetUniformCount(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_ACTIVE_UNIFORM_MAX_LENGTH: *params = programObject->GetUniformMaxLength(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_ACTIVE_UNIFORM_BLOCKS: // GL >= 3.1 *params = programObject->GetActiveUniformBlocksCount(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: // ditto. *params = programObject->GetActiveUniformBlocksMaxNameLength(); + MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params); break; case GL_COMPUTE_WORK_GROUP_SIZE: // GL >= 4.3 @@ -280,6 +293,7 @@ namespace MobileGL { case GL_GEOMETRY_INPUT_TYPE: case GL_GEOMETRY_OUTPUT_TYPE: default: + MGLOG_D("%s: %s", __func__, MG_Util::ConvertGLEnumToString(pname).c_str()); MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, "`pname` is not an accepted value.")); diff --git a/MobileGL/MG_State/GLState/BufferState/BufferState.h b/MobileGL/MG_State/GLState/BufferState/BufferState.h index e774b50d..8f26434a 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferState.h +++ b/MobileGL/MG_State/GLState/BufferState/BufferState.h @@ -25,6 +25,11 @@ namespace MobileGL { BindingSlot& GetBindingSlot(BufferTarget target); // For glBindBufferBase / glBindBufferRange BindingSlotRange1D& GetBindingPoint(BufferTarget target, Uint index); + constexpr SizeT GetBindingPointCount(const BufferTarget target) const { + auto it = std::find(BufferBindPointTargets.begin(), BufferBindPointTargets.end(), target); + auto index = std::distance(BufferBindPointTargets.begin(), it); + return m_bufferBindPointTargets[index].size(); + } void MarkBufferObjectForDeletion(Uint index); Bool ValidateName(Uint index) const; Bool ValidateBufferObject(Uint index) const; @@ -35,7 +40,7 @@ namespace MobileGL { Array, GlobalBufferTargets.size()> m_bindingSlots; // TODO: query the count somewhere globally? // For glBindBufferBase / glBindBufferRange - Array, 14>, BufferBindPointTargets.size()> m_bufferBindPointTargets; + Array, 16>, BufferBindPointTargets.size()> m_bufferBindPointTargets; }; } // namespace GLState } // namespace MG_State diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index ffa66572..edbc9c41 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -33,6 +33,9 @@ namespace MobileGL { SharedPtr GetBufferObject(Uint index); BindingSlot& GetBufferBindingSlot(BufferTarget target); BindingSlotRange1D& GetBufferBindingPoint(BufferTarget target, Uint index); + constexpr SizeT GetBufferBindingPointCount(BufferTarget target) const { + return m_bufferState.GetBindingPointCount(target); + } SharedPtr CreateBufferObject(Uint index); void MarkBufferObjectForDeletion(Uint index); Bool ValidateBufferName(Uint index) const; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 0d5737dc..6dc76e51 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -208,6 +208,9 @@ namespace MobileGL { auto& ubo = m_program->getUniformBlock(i); m_uniformBlockNameMaxLength = std::max(m_uniformBlockNameMaxLength, (Int)ubo.name.length()); m_uniformBlockIndexByName[ubo.name] = i; + // if there's binding defined in shader as layout(binding = ...), + // retrieve it here + m_uniformBlockBinding[i] = ubo.getBinding(); } } diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index f609eadb..53ee722e 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -103,6 +103,10 @@ namespace MobileGL { m_uniformBlockBinding[index] = binding; } + Uint GetUniformBlockBinding(Uint index) const { + return m_uniformBlockBinding[index]; + } + Vector>& GetGeneratedSpirv() { return m_generatedSpirv; } Uint GetExternalIndex() const { return m_externalIndex; }