From e85b067314b9276e2e93700f1f518ed8ab1a2832 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sat, 15 Nov 2025 21:37:08 +0800 Subject: [PATCH] [Fix] (MG_Backend/DirectGLES|MG_Impl/Program): Correct UBO binding. --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 58 ++-- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 7 +- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 261 ++++++++++-------- 3 files changed, 191 insertions(+), 135 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index d0fc2dd6..52e3c4f1 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -14,7 +14,7 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace BufferImpl { void SyncNeccessaryBuffers() { // All buffers we need are: - // 1.VBOs 2.IBO 3.UBOs (TODO) 4.SSBOs (TODO) + // 1.VBO 2.IBO 3.UBO 4.PBO 5.SSBO (TODO) Vector> buffersToSync; const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); @@ -43,11 +43,9 @@ namespace MobileGL::MG_Backend::DirectGLES { 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); + if (obj) buffersToSync.push_back(obj); } - // PBO const auto& pbo = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); if (pbo) { @@ -141,22 +139,20 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr; - for (auto target: fboTargets) { - auto currentFBO = - MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject(); + for (auto target : fboTargets) { + auto currentFBO = MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject(); if (!currentFBO) { MGLOG_E("No FBO is currently bound, cannot sync current FBO."); continue; } - if (currentFBO == - MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { + if (currentFBO == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { // Default FBO, nothing to sync continue; } - const auto &backendFBOIt = g_backendFramebufferObjects.find(currentFBO); + const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO); SharedPtr backendFBOObject; if (backendFBOIt == g_backendFramebufferObjects.end()) { backendFBOObject = MakeShared(); @@ -266,12 +262,14 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO); if (backendFBOIt != FramebufferImpl::g_backendFramebufferObjects.end()) { backendFBOIt->second->Bind(target); + } else { + MGLOG_E("No backend FBO found (maybe not synced) for current %s FBO, cannot bind FBO.", + (target == FramebufferTarget::Read ? "READ" : "DRAW")); } } else { - if (target == FramebufferTarget::Read) - MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - else - MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + MGLOG_D("Binding default framebuffer as %s FBO", (target == FramebufferTarget::Read ? "READ" : "DRAW")); + MG_External::GLES::glBindFramebuffer( + target == FramebufferTarget::Draw ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER, 0); } } @@ -336,7 +334,8 @@ namespace MobileGL::MG_Backend::DirectGLES { auto backendProgramId = backendProgramIt->second->GetBackendProgramId(); // Global UBO if (currentProgram->GetUBOSize() > 0) { - MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, backendProgramIt->second->GetBackendGlobalUBOId()); + 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); @@ -351,24 +350,38 @@ namespace MobileGL::MG_Backend::DirectGLES { } // Normal UBO auto uboCount = currentProgram->GetActiveUniformBlocksCount(); + Uint lastUBOBinding = 0; // to prevent overlapping bindings between global UBO and normal UBOs for (Int i = 0; i < uboCount; ++i) { - // state binding point == backend binding point + ++lastUBOBinding; + // program state binding index == backend binding index // 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); + MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding); // 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); + + if (bufferObj) { + const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObj); + if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) { + const auto& backendBufferObject = backendBufferIt->second; + backendBufferObject->Bind(GL_UNIFORM_BUFFER); + if (range.end == 0) { + MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding, + backendBufferObject->GetBackendBufferId()); + } else { + MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding, + backendBufferObject->GetBackendBufferId(), + range.start, range.end - range.start); + } + } else { + MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO."); + } } } @@ -384,6 +397,7 @@ namespace MobileGL::MG_Backend::DirectGLES { } } else { MG_External::GLES::glUseProgram(0); + MGLOG_E("No backend program found (maybe not synced) for current program, cannot use program."); } } } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 99137eea..15e042f8 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -530,12 +530,13 @@ namespace MobileGL::MG_Backend::DirectGLES { } if (!stateProgramObject->GetLinkStatus()) { - MGLOG_E("Program object is not linked, skipping backend sync. Program: %p", stateProgramObject.get()); + MGLOG_E("Program object is not linked, skipping backend sync. State program ID: %u", + stateProgramObject->GetExternalIndex()); return; } - MGLOG_D("Syncing program to backend. State program: %p, Backend ID: %p", stateProgramObject.get(), - m_backendProgramId); + MGLOG_D("Syncing program to backend. State program ID: %u, Backend ID: %u", + stateProgramObject->GetExternalIndex(), m_backendProgramId); // Detach all existing shaders GLint attachedCount = 0; diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index a6446168..0871a691 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -12,7 +12,7 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", __func__, - "`shader` is not a value generated by OpenGL.")); + std::to_string(shader) + " is not a valid name.")); return false; } return true; @@ -25,7 +25,8 @@ namespace MobileGL { if (!shaderObject) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`shader` is not a shader object.")); + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(shader) + " is not a shader object.")); return nullptr; } return shaderObject; @@ -36,7 +37,7 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", __func__, - "`program` is not a value generated by OpenGL")); + std::to_string(program) + " is not a valid name.")); return false; } return true; @@ -49,7 +50,8 @@ namespace MobileGL { if (!programObject) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not a program object.")); + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(program) + " is not a program object.")); return nullptr; } return programObject; @@ -71,10 +73,11 @@ namespace MobileGL { auto shaderObject = TryToGetShaderObject(shader); if (!shaderObject) return; if (!programObject->AttachShader(shaderObject)) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, - "`shader` is already attached to `program`.")); + MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(shader) + + " is already attached to " + + std::to_string(program) + ".")); return; } } @@ -84,7 +87,8 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", __func__, - "`index` is greater than or equal to `GL_MAX_VERTEX_ATTRIBS`.")); + "index " + std::to_string(index) + + " is greater than or equal to `GL_MAX_VERTEX_ATTRIBS`.")); return; } @@ -92,7 +96,8 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`name` starts with the reserved prefix `gl_`.")); + "name " + std::string(name) + + " starts with the reserved prefix `gl_`.")); return; } @@ -154,7 +159,8 @@ namespace MobileGL { if (bufSize < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`bufSize` is less than 0.")); + MakeShared("MG_Impl/GLImpl", __func__, + "bufSize " + std::to_string(bufSize) + " is less than 0.")); return; } auto programObject = TryToGetProgramObject(program); @@ -165,7 +171,9 @@ namespace MobileGL { ErrorCode::InvalidValue, MakeShared( "MG_Impl/GLImpl", __func__, - "`index` is greater than or equal to the number of active attribute variables in `program`.")); + "index " + std::to_string(index) + + " is greater than or equal to the number of active attribute variables in " + + std::to_string(program) + ".")); return; } if (type != nullptr) *type = programObject->GetAttribType(index); @@ -179,7 +187,8 @@ namespace MobileGL { if (bufSize < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`bufSize` is less than 0.")); + MakeShared("MG_Impl/GLImpl", __func__, + "bufSize " + std::to_string(bufSize) + " is less than 0.")); return; } auto programObject = TryToGetProgramObject(program); @@ -190,7 +199,9 @@ namespace MobileGL { ErrorCode::InvalidValue, MakeShared( "MG_Impl/GLImpl", __func__, - "`index` is greater than or equal to the number of active uniform variables in `program`.")); + "index " + std::to_string(index) + + " is greater than or equal to the number of active uniform variables in " + + std::to_string(program) + ".")); return; } @@ -204,7 +215,8 @@ namespace MobileGL { if (maxCount < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`maxCount` is less than 0.")); + MakeShared("MG_Impl/GLImpl", __func__, + "maxCount " + std::to_string(maxCount) + " is less than 0.")); return; } auto programObject = TryToGetProgramObject(program); @@ -296,7 +308,8 @@ namespace MobileGL { 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.")); + MakeShared("MG_Impl/GLImpl", __func__, + "pname " + std::to_string(pname) + " is not an accepted value.")); return; } } @@ -332,7 +345,8 @@ namespace MobileGL { default: MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum, - MakeShared("MG_Impl/GLImpl", __func__, "`pname` is not an accepted value.")); + MakeShared("MG_Impl/GLImpl", __func__, + "pname " + std::to_string(pname) + " is not an accepted value.")); return; } } @@ -349,7 +363,8 @@ namespace MobileGL { if (bufSize < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`bufSize` is less than 0.")); + MakeShared("MG_Impl/GLImpl", __func__, + "bufSize " + std::to_string(bufSize) + " is less than 0.")); } auto shaderObject = TryToGetShaderObject(shader); @@ -375,7 +390,7 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`program` has not been successfully linked.")); + std::to_string(program) + " has not been successfully linked.")); return; } @@ -384,8 +399,9 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`location` does not correspond to a valid uniform variable location " - "for the specified program object.")); + "location " + std::to_string(location) + + " does not correspond to a valid uniform variable location " + "for the specified program object.")); return; } @@ -395,8 +411,9 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`location` does not correspond to a valid uniform variable location " - "for the specified program object.")); + "location " + std::to_string(location) + + " does not correspond to a valid uniform variable location " + "for the specified program object.")); return; } @@ -446,7 +463,8 @@ namespace MobileGL { if (count < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`count` is less than 0.")); + MakeShared("MG_Impl/GLImpl", __func__, + "count " + std::to_string(count) + " is less than 0.")); return; } @@ -504,8 +522,10 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`location` is an invalid uniform location for the current program " - "object and `location` is not equal to -1.")); + "location " + std::to_string(location) + + " is an invalid uniform location for the current program " + "object and location " + + std::to_string(location) + " is not equal to -1.")); return; } @@ -631,8 +651,10 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`location` is an invalid uniform location for the current program " - "object and `location` is not equal to -1.")); + "location " + std::to_string(location) + + " is an invalid uniform location for the current program " + "object and location " + + std::to_string(location) + " is not equal to -1.")); return; } @@ -667,8 +689,10 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`location` is an invalid uniform location for the current program " - "object and `location` is not equal to -1.")); + "location " + std::to_string(location) + + " is an invalid uniform location for the current program " + "object and location " + + std::to_string(location) + " is not equal to -1.")); return; } @@ -703,8 +727,10 @@ namespace MobileGL { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, - "`location` is an invalid uniform location for the current program " - "object and `location` is not equal to -1.")); + "location " + std::to_string(location) + + " is an invalid uniform location for the current program " + "object and location " + + std::to_string(location) + " is not equal to -1.")); return; } @@ -723,133 +749,147 @@ namespace MobileGL { } GLuint GetUniformBlockIndex_State(GLuint program, const GLchar* uniformBlockName) { - auto programObject = TryToGetProgramObject(program); + const auto& programObject = TryToGetProgramObject(program); if (!programObject) return GL_INVALID_INDEX; if (!programObject->GetLinkStatus()) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(program) + + " is not a program object that has been linked.")); return GL_INVALID_INDEX; } - - auto index = programObject->GetUniformBlockIndex(uniformBlockName); + const auto& index = programObject->GetUniformBlockIndex(uniformBlockName); return index; } void UniformBlockBinding_State(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { - auto programObject = MG_State::pGLContext->GetCurrentProgram(); - if (programObject == nullptr) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "There is no current program object.")); - return; - } + const auto& programObject = TryToGetProgramObject(program); if (!programObject->GetLinkStatus()) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); + MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "Program object" + + std::to_string(program) + + " that has been linked.")); return; } if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`uniformBlockIndex` is greater than or equal to the value of `GL_ACTIVE_UNIFORM_BLOCKS` or is not the index of an active uniform block in program.")); + ErrorCode::InvalidValue, + MakeShared( + "MG_Impl/GLImpl", __func__, + "uniformBlockIndex " + std::to_string(uniformBlockIndex) + + " is greater than or equal to the value of `GL_ACTIVE_UNIFORM_BLOCKS` or is " + "not the index of an active uniform block in program" + + std::to_string(program) + ".")); return; } programObject->SetUniformBlockBinding(uniformBlockIndex, uniformBlockBinding); } void GetActiveUniformBlockiv_State(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { - auto programObject = MG_State::pGLContext->GetCurrentProgram(); - if (programObject == nullptr) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "There is no current program object.")); - return; - } + const auto& programObject = TryToGetProgramObject(program); if (!programObject->GetLinkStatus()) { - MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); + MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "Program object" + + std::to_string(program) + + " that has been linked.")); return; } if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`uniformBlockIndex` is greater than or equal to the value of `GL_ACTIVE_UNIFORM_BLOCKS` or is not the index of an active uniform block in program.")); + ErrorCode::InvalidValue, + MakeShared( + "MG_Impl/GLImpl", __func__, + "uniformBlockIndex " + std::to_string(uniformBlockIndex) + + " is greater than or equal to the value of `GL_ACTIVE_UNIFORM_BLOCKS` or is " + "not the index of an active uniform block in program" + + std::to_string(program) + ".")); return; } switch (pname) { - case GL_UNIFORM_BLOCK_DATA_SIZE: { - *params = programObject->GetUBOSizeAt(uniformBlockIndex); - MGLOG_D("%s: GL_UNIFORM_BLOCK_DATA_SIZE = %d", __func__, *params); - break; - } - case GL_UNIFORM_BLOCK_NAME_LENGTH: { - *params = programObject->GetUniformBlockName(uniformBlockIndex).length() + 1; - MGLOG_D("%s: GL_UNIFORM_BLOCK_NAME_LENGTH = %d", __func__, *params); - break; - } - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { - // TODO: deduct global ubo? - *params = programObject->GetActiveUniformBlocksCount(); - MGLOG_D("%s: GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = %d", __func__, *params); - break; - } - case GL_UNIFORM_BLOCK_BINDING: { - // TODO - MGLOG_D("%s: GL_UNIFORM_BLOCK_BINDING = ", __func__, *params); - } - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER: - default: - MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str()); - MG_State::pGLContext->RecordError( - ErrorCode::InvalidEnum, - MakeShared("MG_Impl/GLImpl", __func__, "`pname` is not one of the accepted tokens.")); - break; + case GL_UNIFORM_BLOCK_DATA_SIZE: { + *params = programObject->GetUBOSizeAt(uniformBlockIndex); + MGLOG_D("%s: GL_UNIFORM_BLOCK_DATA_SIZE = %d", __func__, *params); + break; + } + case GL_UNIFORM_BLOCK_NAME_LENGTH: { + *params = programObject->GetUniformBlockName(uniformBlockIndex).length() + 1; + MGLOG_D("%s: GL_UNIFORM_BLOCK_NAME_LENGTH = %d", __func__, *params); + break; + } + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { + // TODO: deduct global ubo? + *params = programObject->GetActiveUniformBlocksCount(); + MGLOG_D("%s: GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = %d", __func__, *params); + break; + } + case GL_UNIFORM_BLOCK_BINDING: { + // TODO + MGLOG_D("%s: GL_UNIFORM_BLOCK_BINDING = ", __func__, *params); + } + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER: + default: + MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str()); + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + "pname " + std::to_string(pname) + + " is not one of the accepted tokens.")); + break; } } - void GetActiveUniformBlockName_State(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) { + void GetActiveUniformBlockName_State(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName) { auto programObject = TryToGetProgramObject(program); if (!programObject) return; if (!programObject->GetLinkStatus()) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(program) + + " is not a program object that has been linked.")); return; } if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidValue, - MakeShared("MG_Impl/GLImpl", __func__, "`uniformBlockIndex` is greater than or equal to the value of `GL_ACTIVE_UNIFORM_BLOCKS` or is not the index of an active uniform block in program.")); + ErrorCode::InvalidValue, + MakeShared( + "MG_Impl/GLImpl", __func__, + "uniformBlockIndex " + std::to_string(uniformBlockIndex) + + " is greater than or equal to the value of `GL_ACTIVE_UNIFORM_BLOCKS` or is " + "not the index of an active uniform block in program.")); return; } const auto& name = programObject->GetUniformBlockName(uniformBlockIndex); CopyStr(bufSize, length, uniformBlockName, name.c_str(), name.length()); - MGLOG_D("%s: \"%s\" at uniformBlockIndex %02d, length = %d", __func__, uniformBlockName, uniformBlockIndex, *length); + MGLOG_D("%s: \"%s\" at uniformBlockIndex %02d, length = %d", __func__, uniformBlockName, uniformBlockIndex, + *length); } void BindFragDataLocation_State(GLuint program, GLuint colorNumber, const char* name) { auto programObject = TryToGetProgramObject(program); if (programObject == nullptr) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not the name of a program object.")); + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(program) + " is not the name of a program object.")); return; } if (strncmp(name, "gl_", 3) == 0) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, - "`name` starts with the reserved prefix `gl_`.")); + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "name " + std::string(name) + + " starts with the reserved prefix `gl_`.")); return; } // TODO: Emit error "if `colorNumber` is greater than or equal to `GL_MAX_DRAW_BUFFERS`" @@ -862,16 +902,16 @@ namespace MobileGL { auto programObject = TryToGetProgramObject(program); if (programObject == nullptr) { MG_State::pGLContext->RecordError( - ErrorCode::InvalidOperation, - MakeShared("MG_Impl/GLImpl", __func__, "`program` is not the name of a program object.")); + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + std::to_string(program) + " is not the name of a program object.")); return -1; } return programObject->GetFragmentDataLocation(name); } - void ValidateProgram_State(GLuint program) { -// THROW_UNIMPL_EXCEPTION; + // THROW_UNIMPL_EXCEPTION; } void AttachShader(GLuint program, GLuint shader) { @@ -1068,7 +1108,8 @@ namespace MobileGL { GetActiveUniformBlockiv_State(program, uniformBlockIndex, pname, params); } - void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) { + void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, + GLchar* uniformBlockName) { GetActiveUniformBlockName_State(program, uniformBlockIndex, bufSize, length, uniformBlockName); }