[Fix] (MG_Backend/DirectGLES|MG_Impl/Program): Correct UBO binding.

This commit is contained in:
BZLZHH
2025-11-15 21:37:08 +08:00
parent 4cb82e2e50
commit e85b067314
3 changed files with 191 additions and 135 deletions
+34 -20
View File
@@ -14,7 +14,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace BufferImpl { namespace BufferImpl {
void SyncNeccessaryBuffers() { void SyncNeccessaryBuffers() {
// All buffers we need are: // 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<SharedPtr<MG_State::GLState::BufferObject>> buffersToSync; Vector<SharedPtr<MG_State::GLState::BufferObject>> buffersToSync;
const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray();
@@ -43,11 +43,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (SizeT i = 0; i < uboBindingPointCnt; ++i) { for (SizeT i = 0; i < uboBindingPointCnt; ++i) {
auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i); auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, i);
auto obj = point.GetBoundObject(); auto obj = point.GetBoundObject();
if (obj) if (obj) buffersToSync.push_back(obj);
buffersToSync.push_back(obj);
} }
// PBO // PBO
const auto& pbo = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject(); const auto& pbo = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::PixelUnpack).GetBoundObject();
if (pbo) { if (pbo) {
@@ -141,22 +139,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr; MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr;
for (auto target: fboTargets) { for (auto target : fboTargets) {
auto currentFBO = auto currentFBO = MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject();
MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject();
if (!currentFBO) { if (!currentFBO) {
MGLOG_E("No FBO is currently bound, cannot sync current FBO."); MGLOG_E("No FBO is currently bound, cannot sync current FBO.");
continue; continue;
} }
if (currentFBO == if (currentFBO == MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) {
MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) {
// Default FBO, nothing to sync // Default FBO, nothing to sync
continue; continue;
} }
const auto &backendFBOIt = g_backendFramebufferObjects.find(currentFBO); const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO);
SharedPtr<BackendFramebufferObject> backendFBOObject; SharedPtr<BackendFramebufferObject> backendFBOObject;
if (backendFBOIt == g_backendFramebufferObjects.end()) { if (backendFBOIt == g_backendFramebufferObjects.end()) {
backendFBOObject = MakeShared<BackendFramebufferObject>(); backendFBOObject = MakeShared<BackendFramebufferObject>();
@@ -266,12 +262,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO); const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO);
if (backendFBOIt != FramebufferImpl::g_backendFramebufferObjects.end()) { if (backendFBOIt != FramebufferImpl::g_backendFramebufferObjects.end()) {
backendFBOIt->second->Bind(target); 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 { } else {
if (target == FramebufferTarget::Read) MGLOG_D("Binding default framebuffer as %s FBO", (target == FramebufferTarget::Read ? "READ" : "DRAW"));
MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); MG_External::GLES::glBindFramebuffer(
else target == FramebufferTarget::Draw ? GL_DRAW_FRAMEBUFFER : GL_READ_FRAMEBUFFER, 0);
MG_External::GLES::glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
} }
} }
@@ -336,7 +334,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto backendProgramId = backendProgramIt->second->GetBackendProgramId(); auto backendProgramId = backendProgramIt->second->GetBackendProgramId();
// Global UBO // Global UBO
if (currentProgram->GetUBOSize() > 0) { 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(), MG_External::GLES::glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(),
currentProgram->MapUBO()); currentProgram->MapUBO());
MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0); MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, 0);
@@ -351,25 +350,39 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
// Normal UBO // Normal UBO
auto uboCount = currentProgram->GetActiveUniformBlocksCount(); auto uboCount = currentProgram->GetActiveUniformBlocksCount();
Uint lastUBOBinding = 0; // to prevent overlapping bindings between global UBO and normal UBOs
for (Int i = 0; i < uboCount; ++i) { 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 // 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, binding); MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding);
// Connect buffer to backend binding point // Connect buffer to backend binding point
auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding); auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding);
auto bufferObj = point.GetBoundObject(); auto bufferObj = point.GetBoundObject();
auto range = point.GetRange(); auto range = point.GetRange();
if (range.end > bufferObj->GetSize()) {
MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, binding, BufferImpl::g_backendBufferObjects[bufferObj]->GetBackendBufferId()); 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 { } else {
MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, binding, BufferImpl::g_backendBufferObjects[bufferObj]->GetBackendBufferId(), MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding,
backendBufferObject->GetBackendBufferId(),
range.start, range.end - range.start); range.start, range.end - range.start);
} }
} else {
MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO.");
}
}
} }
// Sampler unit binding // Sampler unit binding
@@ -384,6 +397,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} else { } else {
MG_External::GLES::glUseProgram(0); MG_External::GLES::glUseProgram(0);
MGLOG_E("No backend program found (maybe not synced) for current program, cannot use program.");
} }
} }
} }
+4 -3
View File
@@ -530,12 +530,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
if (!stateProgramObject->GetLinkStatus()) { 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; return;
} }
MGLOG_D("Syncing program to backend. State program: %p, Backend ID: %p", stateProgramObject.get(), MGLOG_D("Syncing program to backend. State program ID: %u, Backend ID: %u",
m_backendProgramId); stateProgramObject->GetExternalIndex(), m_backendProgramId);
// Detach all existing shaders // Detach all existing shaders
GLint attachedCount = 0; GLint attachedCount = 0;
+108 -67
View File
@@ -12,7 +12,7 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`shader` is not a value generated by OpenGL.")); std::to_string(shader) + " is not a valid name."));
return false; return false;
} }
return true; return true;
@@ -25,7 +25,8 @@ namespace MobileGL {
if (!shaderObject) { if (!shaderObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`shader` is not a shader object.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(shader) + " is not a shader object."));
return nullptr; return nullptr;
} }
return shaderObject; return shaderObject;
@@ -36,7 +37,7 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`program` is not a value generated by OpenGL")); std::to_string(program) + " is not a valid name."));
return false; return false;
} }
return true; return true;
@@ -49,7 +50,8 @@ namespace MobileGL {
if (!programObject) { if (!programObject) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not a program object.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) + " is not a program object."));
return nullptr; return nullptr;
} }
return programObject; return programObject;
@@ -71,10 +73,11 @@ namespace MobileGL {
auto shaderObject = TryToGetShaderObject(shader); auto shaderObject = TryToGetShaderObject(shader);
if (!shaderObject) return; if (!shaderObject) return;
if (!programObject->AttachShader(shaderObject)) { if (!programObject->AttachShader(shaderObject)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`shader` is already attached to `program`.")); std::to_string(shader) +
" is already attached to " +
std::to_string(program) + "."));
return; return;
} }
} }
@@ -84,7 +87,8 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("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; return;
} }
@@ -92,7 +96,8 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`name` starts with the reserved prefix `gl_`.")); "name " + std::string(name) +
" starts with the reserved prefix `gl_`."));
return; return;
} }
@@ -154,7 +159,8 @@ namespace MobileGL {
if (bufSize < 0) { if (bufSize < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`bufSize` is less than 0.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"bufSize " + std::to_string(bufSize) + " is less than 0."));
return; return;
} }
auto programObject = TryToGetProgramObject(program); auto programObject = TryToGetProgramObject(program);
@@ -165,7 +171,9 @@ namespace MobileGL {
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>( MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__, "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; return;
} }
if (type != nullptr) *type = programObject->GetAttribType(index); if (type != nullptr) *type = programObject->GetAttribType(index);
@@ -179,7 +187,8 @@ namespace MobileGL {
if (bufSize < 0) { if (bufSize < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`bufSize` is less than 0.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"bufSize " + std::to_string(bufSize) + " is less than 0."));
return; return;
} }
auto programObject = TryToGetProgramObject(program); auto programObject = TryToGetProgramObject(program);
@@ -190,7 +199,9 @@ namespace MobileGL {
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>( MakeShared<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__, "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; return;
} }
@@ -204,7 +215,8 @@ namespace MobileGL {
if (maxCount < 0) { if (maxCount < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`maxCount` is less than 0.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"maxCount " + std::to_string(maxCount) + " is less than 0."));
return; return;
} }
auto programObject = TryToGetProgramObject(program); auto programObject = TryToGetProgramObject(program);
@@ -296,7 +308,8 @@ namespace MobileGL {
MGLOG_D("%s: %s", __func__, MG_Util::ConvertGLEnumToString(pname).c_str()); MGLOG_D("%s: %s", __func__, MG_Util::ConvertGLEnumToString(pname).c_str());
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`pname` is not an accepted value.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"pname " + std::to_string(pname) + " is not an accepted value."));
return; return;
} }
} }
@@ -332,7 +345,8 @@ namespace MobileGL {
default: default:
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`pname` is not an accepted value.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"pname " + std::to_string(pname) + " is not an accepted value."));
return; return;
} }
} }
@@ -349,7 +363,8 @@ namespace MobileGL {
if (bufSize < 0) { if (bufSize < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`bufSize` is less than 0.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"bufSize " + std::to_string(bufSize) + " is less than 0."));
} }
auto shaderObject = TryToGetShaderObject(shader); auto shaderObject = TryToGetShaderObject(shader);
@@ -375,7 +390,7 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`program` has not been successfully linked.")); std::to_string(program) + " has not been successfully linked."));
return; return;
} }
@@ -384,7 +399,8 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`location` does not correspond to a valid uniform variable location " "location " + std::to_string(location) +
" does not correspond to a valid uniform variable location "
"for the specified program object.")); "for the specified program object."));
return; return;
} }
@@ -395,7 +411,8 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`location` does not correspond to a valid uniform variable location " "location " + std::to_string(location) +
" does not correspond to a valid uniform variable location "
"for the specified program object.")); "for the specified program object."));
return; return;
} }
@@ -446,7 +463,8 @@ namespace MobileGL {
if (count < 0) { if (count < 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`count` is less than 0.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"count " + std::to_string(count) + " is less than 0."));
return; return;
} }
@@ -504,8 +522,10 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`location` is an invalid uniform location for the current program " "location " + std::to_string(location) +
"object and `location` is not equal to -1.")); " is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return; return;
} }
@@ -631,8 +651,10 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`location` is an invalid uniform location for the current program " "location " + std::to_string(location) +
"object and `location` is not equal to -1.")); " is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return; return;
} }
@@ -667,8 +689,10 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`location` is an invalid uniform location for the current program " "location " + std::to_string(location) +
"object and `location` is not equal to -1.")); " is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return; return;
} }
@@ -703,8 +727,10 @@ namespace MobileGL {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`location` is an invalid uniform location for the current program " "location " + std::to_string(location) +
"object and `location` is not equal to -1.")); " is an invalid uniform location for the current program "
"object and location " +
std::to_string(location) + " is not equal to -1."));
return; return;
} }
@@ -723,61 +749,64 @@ namespace MobileGL {
} }
GLuint GetUniformBlockIndex_State(GLuint program, const GLchar* uniformBlockName) { 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) return GL_INVALID_INDEX;
if (!programObject->GetLinkStatus()) { if (!programObject->GetLinkStatus()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) +
" is not a program object that has been linked."));
return GL_INVALID_INDEX; return GL_INVALID_INDEX;
} }
const auto& index = programObject->GetUniformBlockIndex(uniformBlockName);
auto index = programObject->GetUniformBlockIndex(uniformBlockName);
return index; return index;
} }
void UniformBlockBinding_State(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { void UniformBlockBinding_State(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) {
auto programObject = MG_State::pGLContext->GetCurrentProgram(); const auto& programObject = TryToGetProgramObject(program);
if (programObject == nullptr) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "There is no current program object."));
return;
}
if (!programObject->GetLinkStatus()) { if (!programObject->GetLinkStatus()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
ErrorCode::InvalidOperation, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); "Program object" +
std::to_string(program) +
" that has been linked."));
return; return;
} }
if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) { if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("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.")); MakeShared<GenericErrorInfo>(
"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; return;
} }
programObject->SetUniformBlockBinding(uniformBlockIndex, uniformBlockBinding); programObject->SetUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
} }
void GetActiveUniformBlockiv_State(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { void GetActiveUniformBlockiv_State(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) {
auto programObject = MG_State::pGLContext->GetCurrentProgram(); const auto& programObject = TryToGetProgramObject(program);
if (programObject == nullptr) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "There is no current program object."));
return;
}
if (!programObject->GetLinkStatus()) { if (!programObject->GetLinkStatus()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
ErrorCode::InvalidOperation, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); "Program object" +
std::to_string(program) +
" that has been linked."));
return; return;
} }
if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) { if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("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.")); MakeShared<GenericErrorInfo>(
"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; return;
} }
switch (pname) { switch (pname) {
@@ -811,30 +840,39 @@ namespace MobileGL {
default: default:
MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str()); MGLOG_E("%s: unknown pname = %p %s", __func__, pname, MG_Util::ConvertGLEnumToString(pname).c_str());
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, ErrorCode::InvalidEnum, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`pname` is not one of the accepted tokens.")); "pname " + std::to_string(pname) +
" is not one of the accepted tokens."));
break; 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); auto programObject = TryToGetProgramObject(program);
if (!programObject) return; if (!programObject) return;
if (!programObject->GetLinkStatus()) { if (!programObject->GetLinkStatus()) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not a program object that has been linked.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) +
" is not a program object that has been linked."));
return; return;
} }
if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) { if (!programObject->IsActiveUniformBlock(uniformBlockIndex)) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue, ErrorCode::InvalidValue,
MakeShared<GenericErrorInfo>("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.")); MakeShared<GenericErrorInfo>(
"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; return;
} }
const auto& name = programObject->GetUniformBlockName(uniformBlockIndex); const auto& name = programObject->GetUniformBlockName(uniformBlockIndex);
CopyStr(bufSize, length, uniformBlockName, name.c_str(), name.length()); 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) { void BindFragDataLocation_State(GLuint program, GLuint colorNumber, const char* name) {
@@ -842,14 +880,16 @@ namespace MobileGL {
if (programObject == nullptr) { if (programObject == nullptr) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not the name of a program object.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) + " is not the name of a program object."));
return; return;
} }
if (strncmp(name, "gl_", 3) == 0) { if (strncmp(name, "gl_", 3) == 0) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`name` starts with the reserved prefix `gl_`.")); "name " + std::string(name) +
" starts with the reserved prefix `gl_`."));
return; return;
} }
// TODO: Emit error "if `colorNumber` is greater than or equal to `GL_MAX_DRAW_BUFFERS`" // TODO: Emit error "if `colorNumber` is greater than or equal to `GL_MAX_DRAW_BUFFERS`"
@@ -863,15 +903,15 @@ namespace MobileGL {
if (programObject == nullptr) { if (programObject == nullptr) {
MG_State::pGLContext->RecordError( MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, ErrorCode::InvalidOperation,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "`program` is not the name of a program object.")); MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::to_string(program) + " is not the name of a program object."));
return -1; return -1;
} }
return programObject->GetFragmentDataLocation(name); return programObject->GetFragmentDataLocation(name);
} }
void ValidateProgram_State(GLuint program) { void ValidateProgram_State(GLuint program) {
// THROW_UNIMPL_EXCEPTION; // THROW_UNIMPL_EXCEPTION;
} }
void AttachShader(GLuint program, GLuint shader) { void AttachShader(GLuint program, GLuint shader) {
@@ -1068,7 +1108,8 @@ namespace MobileGL {
GetActiveUniformBlockiv_State(program, uniformBlockIndex, pname, params); 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); GetActiveUniformBlockName_State(program, uniformBlockIndex, bufSize, length, uniformBlockName);
} }