From 278656ac5a9057a9a34e141abfe8ee5784c9c7d0 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 1 Nov 2025 23:06:25 +0800 Subject: [PATCH] [Feat]: (MG_Impl/Program, MG_State/Program): implement UBO --- .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 8 +- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 117 ++++++++++++++++++ MobileGL/MG_Impl/GLImpl/Program/GL_Program.h | 4 + .../GLState/ProgramState/ProgramObject.cpp | 5 + .../GLState/ProgramState/ProgramObject.h | 34 +++++ 5 files changed, 164 insertions(+), 4 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 11385eba..c63dc83a 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -241,10 +241,10 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferfi, GLenum buffer, GLint drawbuff DECLARE_GL_FUNCTION_HEAD(void, CopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CopyBufferSubData, readTarget, writeTarget, readOffset, writeOffset, size) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformIndices, program, uniformCount, uniformNames, uniformIndices) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformsiv, program, uniformCount, uniformIndices, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(GLuint, GetUniformBlockIndex, GLuint program, const GLchar* uniformBlockName) DECLARE_GL_FUNCTION_STUB_END(GLuint, GetUniformBlockIndex, program, uniformBlockName) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformBlockiv, program, uniformBlockIndex, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetActiveUniformBlockName, GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetActiveUniformBlockName, program, uniformBlockIndex, bufSize, length, uniformBlockName) -DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformBlockBinding, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformBlockBinding, program, uniformBlockIndex, uniformBlockBinding) +DECLARE_GL_FUNCTION_HEAD(GLuint, GetUniformBlockIndex, GLuint program, const GLchar* uniformBlockName) DECLARE_GL_FUNCTION_END(GLuint, GetUniformBlockIndex, program, uniformBlockName) +DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformBlockiv, program, uniformBlockIndex, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetActiveUniformBlockName, GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformBlockName, program, uniformBlockIndex, bufSize, length, uniformBlockName) +DECLARE_GL_FUNCTION_HEAD(void, UniformBlockBinding, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformBlockBinding, program, uniformBlockIndex, uniformBlockBinding) DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawArraysInstanced, GLenum mode, GLint first, GLsizei count, GLsizei instancecount) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawArraysInstanced, mode, first, count, instancecount) DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawElementsInstanced, GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawElementsInstanced, mode, count, type, indices, instancecount) DECLARE_GL_FUNCTION_STUB_HEAD(GLsync, FenceSync, GLenum condition, GLbitfield flags) DECLARE_GL_FUNCTION_STUB_END(GLsync, FenceSync, condition, flags) diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 51d34e21..11fdfeec 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -1,4 +1,5 @@ #include "GL_Program.h" +#include "MG_Util/Converters/GLToStr/GLEnumConverter.h" #include #include #include @@ -704,6 +705,106 @@ namespace MobileGL { } } + GLuint GetUniformBlockIndex_State(GLuint program, const GLchar* uniformBlockName) { + 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.")); + return GL_INVALID_INDEX; + } + + + auto index = programObject->GetUniformBlockIndex(uniformBlockName); + return index; + } + + void UniformBlockBinding_State(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { + 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.")); + 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.")); + return; + } + programObject->SetUniformBlockBinding(uniformBlockIndex, uniformBlockBinding); + } + + void GetActiveUniformBlockiv_State(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { + 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.")); + 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.")); + return; + } + switch (pname) { + case GL_UNIFORM_BLOCK_DATA_SIZE: { + *params = programObject->GetUBOSizeAt(uniformBlockIndex); + break; + } + case GL_UNIFORM_BLOCK_NAME_LENGTH: { + *params = programObject->GetUniformBlockName(uniformBlockIndex).length() + 1; + break; + } + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: { + // TODO: deduct global ubo? + *params = programObject->GetActiveUniformBlocksCount(); + break; + } + case GL_UNIFORM_BLOCK_BINDING: { + // TODO + } + 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_D("%s: pname = %s", __func__, 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.")); + return; + } + } + + 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.")); + 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.")); + return; + } + const auto& name = programObject->GetUniformBlockName(uniformBlockIndex); + CopyStr(bufSize, length, uniformBlockName, name.c_str(), name.length()); + } + void ValidateProgram_State(GLuint program) { THROW_UNIMPL_EXCEPTION; } @@ -890,6 +991,22 @@ namespace MobileGL { UniformMatrix4fv_State(location, count, transpose, value); } + GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { + return GetUniformBlockIndex_State(program, uniformBlockName); + } + + void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { + UniformBlockBinding_State(program, uniformBlockIndex, uniformBlockBinding); + } + + void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { + GetActiveUniformBlockiv_State(program, uniformBlockIndex, pname, params); + } + + void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) { + GetActiveUniformBlockName_State(program, uniformBlockIndex, bufSize, length, uniformBlockName); + } + void ValidateProgram(GLuint program) { ValidateProgram_State(program); } diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h index 55cb8beb..afbf524e 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h @@ -49,6 +49,10 @@ namespace MobileGL { void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName); + void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); + void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); void ValidateProgram(GLuint program); } // namespace MG_Impl::GLImpl } // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 5a94ced7..f8e96ae3 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -199,10 +199,15 @@ namespace MobileGL { // ---------- UBO ---------- int uboCount = m_program->getNumUniformBlocks(); + m_uniformBlockIndexInTProgram.resize(uboCount, -1); + m_uniformBlockBinding.resize(uboCount, 0); for (int i = 0; i < uboCount; i++) { auto& ubo = m_program->getUniformBlock(i); m_uniformBlockNameMaxLength = std::max(m_uniformBlockNameMaxLength, (Int)ubo.name.length()); + m_uniformBlockIndex[ubo.name] = ubo.getBinding(); + m_uniformBlockIndexInTProgram[ubo.getBinding()] = i; } + } void ProgramObject::GenerateBinary() { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index a7336ee5..a525c043 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -75,6 +75,34 @@ namespace MobileGL { Int GetActiveUniformBlocksCount() const { return m_program->getNumUniformBlocks(); } Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; } Int GetActiveUniformBlocksMaxNameLength() const { return m_uniformBlockNameMaxLength; } + Uint GetUniformBlockIndex(const char* name) const { + auto it = m_uniformBlockIndex.find(name); + if (it != m_uniformBlockIndex.end()) + return it->second; + return 0xFFFFFFFFu; // GL_INVALID_INDEX + } + Bool IsActiveUniformBlock(Uint index) const { + if (index >= GetActiveUniformBlocksCount()) + return false; + if (m_uniformBlockIndexInTProgram[index] == -1) + return false; + return true; + } + Uint GetUBOSizeAt(Uint index) const { + if (!IsActiveUniformBlock(index)) + return 0; + return m_program->getUniformBlock(m_uniformBlockIndexInTProgram[index]).size; + } + + + const String& GetUniformBlockName(Uint index) const { + auto& ubo = m_program->getUniform(m_uniformBlockIndexInTProgram[index]); + return ubo.name; + } + + void SetUniformBlockBinding(Uint index, Uint binding) { + m_uniformBlockBinding[index] = binding; + } Vector>& GetGeneratedSpirv() { return m_generatedSpirv; } @@ -105,6 +133,12 @@ namespace MobileGL { // ditto. Will be set at glUniform1i Vector m_uniformSamplerOrImageUnitIndex; + UnorderedMap m_uniformBlockIndex; + + // Ordered by block index + Vector m_uniformBlockIndexInTProgram; + Vector m_uniformBlockBinding; + // Need to be reflected after linking of SPIR-V binary Vector m_uniformOffsets; Vector m_uniformSizesInBytes;