From 238d0ffade9e1589ceb8f720dc10ad84b3aa76f3 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 14 Aug 2025 13:50:34 +0800 Subject: [PATCH] [Feat] (MG_State/Program): GetActiveUniform --- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 32 ++++++++++++++++--- .../GLState/ProgramState/ProgramObject.cpp | 24 +++++++++++--- .../GLState/ProgramState/ProgramObject.h | 17 ++++++++++ MobileGL/MG_Test/Buffer/CMakeLists.txt | 1 + MobileGL/MG_Test/Program/CMakeLists.txt | 1 + MobileGL/MG_Test/VertexArray/CMakeLists.txt | 1 + 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index 980cfe94..d131d6cf 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -1,6 +1,7 @@ #include "GL_Program.h" #include "MG_State/GLState/Core.h" +#include "MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.h" namespace MobileGL { namespace MG_Impl::GLImpl { @@ -60,6 +61,9 @@ namespace MobileGL { auto sz = std::min(bufSize - 1, srcLength); if (length) *length = sz; + + if (bufSize == 0) return; + memcpy(dst, src, sz); dst[sz] = '\0'; } @@ -144,7 +148,30 @@ namespace MobileGL { void GetActiveUniform_State(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) { - THROW_UNIMPL_EXCEPTION; + if (bufSize < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", __func__, + "`bufSize` is less than 0.")); + return; + } + auto programObject = TryToGetProgramObject(program); + if (!programObject) + return; + auto uniformCount = programObject->GetUniformCount(); + if (index >= uniformCount) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", __func__, + "`index` is greater than or equal to the number of active uniform variables in `program`.")); + return; + } + + if (type != nullptr) + *type = programObject->GetUniformType(index); + if (bufSize == 0) return; + auto& uniformName = programObject->GetUniformName(index); + CopyStr(bufSize, length, name, uniformName.c_str(), uniformName.length()); } void GetAttachedShaders_State(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) { @@ -213,8 +240,6 @@ namespace MobileGL { CopyStr(bufSize, length, source, src.c_str(), src.length()); } - - GLint GetUniformLocation_State(GLuint program, const GLchar* name) { auto programObject = TryToGetProgramObject(program); if (!programObject) @@ -283,7 +308,6 @@ namespace MobileGL { if (!programObject) return; MG_State::pGLContext->UseProgram(program); - } void Uniform1f_State(GLint location, GLfloat v0) { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index 78f4117d..31be0325 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -1,6 +1,8 @@ #include "ProgramObject.h" #include +#include "MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.h" + namespace MobileGL { namespace MG_State { namespace GLState { @@ -75,7 +77,9 @@ namespace MobileGL { for (const auto& shader : m_shaders) { for (const auto& [name, loc] : shader->GetUniformLocations()) { // collect all the names to map - m_uniforms[name] = loc; + if (loc != 4095 || m_uniforms.find(name) == m_uniforms.end()) { + m_uniforms[name] = loc; + } // set a flag for those who have an explicit location if (loc != 4095) { @@ -121,6 +125,12 @@ namespace MobileGL { } } } + + m_uniformNames.resize(m_uniformOffsets.size()); + for (auto& [name, loc] : m_uniforms) { + m_uniformNames[loc] = name; + m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)name.length()); + } } void ProgramObject::PostLink() { @@ -135,14 +145,20 @@ namespace MobileGL { assert(false); return; } - auto& metadata = session.GetMetadata(); - auto& uniformOffsets = metadata.plainUniformOffsetsInUBO; + m_metadata = session.GetMetadata(); + auto& uniformOffsets = m_metadata.plainUniformOffsetsInUBO; for (const auto& [name, offset] : uniformOffsets) { assert(m_uniforms.find(name) != m_uniforms.end()); assert(m_uniforms[name] < m_uniformOffsets.size()); m_uniformOffsets[m_uniforms[name]] = offset; } - m_uboScratch.resize(metadata.uboSize); + + m_uniformTypes.resize(uniformOffsets.size()); + for (const auto& [name, type] : m_metadata.plainUniformMemberTypes) { + m_uniformTypes[m_uniforms[name]] = MG_Util::ConvertSpvcTypeToGLEnum(type); + } + + m_uboScratch.resize(m_metadata.uboSize, 0); } } // namespace GLState } // namespace MG_State diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index 9955ed96..6309da71 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -1,6 +1,7 @@ #pragma once #include #include "ShaderObject.h" +#include "MG_Util/ShaderTranspiler/SpvcSession.h" namespace MobileGL { namespace MG_State { @@ -15,10 +16,19 @@ namespace MobileGL { void MarkAsDeleted(); Vector>& GetAttachedShaders(); const String& GetInfoLog() const { return m_infoLog; } + Int GetUniformMaxLength() const { return m_uniformNameMaxLength; } + Uint GetUniformCount() { return m_uniformOffsets.size(); } Int GetUniformLocation(const String& name) { const auto it = m_uniforms.find(name); return (it == m_uniforms.end()) ? -1 : it->second; } + GLenum GetUniformType(Uint index) const { + return m_uniformTypes[index]; + } + + const String& GetUniformName(Uint index) const { + return m_uniformNames[index]; + } private: void PreLink(); void PostLink(); @@ -29,12 +39,19 @@ namespace MobileGL { Vector> m_programBinary; // Uniforms + MG_Util::ShaderTranspiler::SpvcMetadata m_metadata; + UnorderedMap m_uniforms; // 0 or 1 for if the location is explicitly specified at PreLink stage, // offsets into global ubo for PostLink Vector m_uniformOffsets; + Vector m_uniformNames; + Vector m_uniformTypes; + Vector m_uboScratch; + Int m_uniformNameMaxLength = 0; + String m_infoLog; Bool m_deleteStatus = false; Bool m_linkStatus = true; diff --git a/MobileGL/MG_Test/Buffer/CMakeLists.txt b/MobileGL/MG_Test/Buffer/CMakeLists.txt index 2aa17712..9cf1dfda 100644 --- a/MobileGL/MG_Test/Buffer/CMakeLists.txt +++ b/MobileGL/MG_Test/Buffer/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable( ${MGL_ROOT}/MobileGL/MG_Backend/Init.cpp ${MGL_ROOT}/MobileGL/MG_Util/Debug/Log.cpp ${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp + ${MGL_ROOT}/MobileGL/MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.cpp ) target_include_directories(BufferTest PRIVATE diff --git a/MobileGL/MG_Test/Program/CMakeLists.txt b/MobileGL/MG_Test/Program/CMakeLists.txt index 38b3d47c..3d828123 100644 --- a/MobileGL/MG_Test/Program/CMakeLists.txt +++ b/MobileGL/MG_Test/Program/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable( ${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp ${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp + ${MGL_ROOT}/MobileGL/MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.cpp ${MGL_ROOT}/MobileGL/MG_State/GLState/Core.cpp ${MGL_ROOT}/MobileGL/MG_State/GLState/BufferState/BufferState.cpp diff --git a/MobileGL/MG_Test/VertexArray/CMakeLists.txt b/MobileGL/MG_Test/VertexArray/CMakeLists.txt index 638c45fd..2dcac661 100644 --- a/MobileGL/MG_Test/VertexArray/CMakeLists.txt +++ b/MobileGL/MG_Test/VertexArray/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable( ${MGL_ROOT}/MobileGL/MG_Backend/Init.cpp ${MGL_ROOT}/MobileGL/MG_Util/Debug/Log.cpp ${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp + ${MGL_ROOT}/MobileGL/MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.cpp ) target_include_directories(VertexArrayTest PRIVATE