From bc46cb9c5f92d6dd3c28ac407a9f75acca4d17a4 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 22 Aug 2025 14:58:24 +0800 Subject: [PATCH] [Feat] (MG_State/Program): glUniform*v --- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 55 +++++++++++++++---- .../GLState/ProgramState/ProgramObject.cpp | 10 ++-- MobileGL/MG_Test/Program/ProgramTest.cpp | 50 +++++++++++++---- 3 files changed, 91 insertions(+), 24 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index b33c49eb..9708004f 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -451,6 +451,7 @@ namespace MobileGL { ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", __func__, "`count` is less than 0.")); + return; } auto shaderObject = TryToGetShaderObject(shader); @@ -465,7 +466,7 @@ namespace MobileGL { shaderObject->SetShaderSource(Move(src)); } - void UseProgram_State(GLuint program) { + void UseProgram_State(GLint program) { if (program == 0) { MG_State::pGLContext->UseProgram(0); return; @@ -477,37 +478,71 @@ namespace MobileGL { MG_State::pGLContext->UseProgram(program); } - void Uniform1fv_State(GLint location, GLsizei count, const GLfloat* value) { + template + void Uniform_State(MG_State::GLState::ProgramObject& programObject, GLuint location, T* value) { + auto size = programObject.GetUniformSizesInBytes(location); + auto offset = programObject.GetUniformOffset(location); + assert(size >= VecCount * sizeof(T)); + memcpy((char*)programObject.MapUBO() + offset, value, VecCount * sizeof(T)); + } - THROW_UNIMPL_EXCEPTION; + template + void Uniformv_State(GLint location, GLsizei count, T* value) { + if (location == -1) + return; + + 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; + } + + if (location >= programObject->GetUniformCount() || location < -1) { + 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.")); + return; + } + + for (GLint offset = 0; offset < count; offset++) { + Uniform_State(*programObject, location + offset, value + offset * VecCount); + } + } + + void Uniform1fv_State(GLint location, GLsizei count, const GLfloat* value) { + Uniformv_State<1>(location, count, value); } void Uniform2fv_State(GLint location, GLsizei count, const GLfloat* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<2>(location, count, value); } void Uniform3fv_State(GLint location, GLsizei count, const GLfloat* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<3>(location, count, value); } void Uniform4fv_State(GLint location, GLsizei count, const GLfloat* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<4>(location, count, value); } void Uniform1iv_State(GLint location, GLsizei count, const GLint* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<1>(location, count, value); } void Uniform2iv_State(GLint location, GLsizei count, const GLint* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<2>(location, count, value); } void Uniform3iv_State(GLint location, GLsizei count, const GLint* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<3>(location, count, value); } void Uniform4iv_State(GLint location, GLsizei count, const GLint* value) { - THROW_UNIMPL_EXCEPTION; + Uniformv_State<4>(location, count, value); } void UniformMatrix2fv_State(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index d1da8fef..9278ba28 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -174,14 +174,16 @@ namespace MobileGL { m_uboScratch.resize(size); m_uniformOffsets.resize(meta.plainUniformOffsetsInUBO.size()); for (const auto& [name, offset] : meta.plainUniformOffsetsInUBO) { - m_uniformOffsets[m_uniformLocations[name]] = offset; + if (m_uniformLocations.find(name) != m_uniformLocations.end()) + m_uniformOffsets[m_uniformLocations[name]] = offset; } m_uniformSizesInBytes.resize(meta.plainUniformMemberSizesInBytes.size()); for (const auto& [name, size] : meta.plainUniformMemberSizesInBytes) { - m_uniformSizesInBytes[m_uniformLocations[name]] = size; + if (m_uniformLocations.find(name) != m_uniformLocations.end()) + m_uniformSizesInBytes[m_uniformLocations[name]] = size; } - assert(m_uniformOffsets.size() == GetUniformCount()); - assert(m_uniformSizesInBytes.size() == GetUniformCount()); + // assert(m_uniformOffsets.size() == GetUniformCount()); + // assert(m_uniformSizesInBytes.size() == GetUniformCount()); } void ProgramObject::WaitUntilGenerationCompleted() { diff --git a/MobileGL/MG_Test/Program/ProgramTest.cpp b/MobileGL/MG_Test/Program/ProgramTest.cpp index 0449d560..52120260 100644 --- a/MobileGL/MG_Test/Program/ProgramTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramTest.cpp @@ -64,6 +64,7 @@ uniform vec3 Offset; uniform vec3 ColorScale; layout(location = 6) uniform float Saturation; uniform int AQuickFoxJumpsOverALazyDog; +uniform int intVal; out vec4 fragColor; @@ -84,7 +85,7 @@ void main() { vec3 Chroma = OutColor - Luma; OutColor = (Chroma * Saturation) + Luma; - fragColor = vec4(OutColor, 1.0); + fragColor = vec4(OutColor, float(intVal)); })"; @@ -101,16 +102,26 @@ TEST_F(ProgramTest, CompileFragment) { } TEST_F(ProgramTest, CompileAndLink) { + char infoLog[1024] = ""; + GLuint vs = CreateShader(GL_VERTEX_SHADER); ShaderSource(vs, 1, &vsSrc, NULL); printf("Compiling vertex shader: %s\n", vsSrc); CompileShader(vs); + GLint vsStatus = GL_FALSE; + GetShaderiv(vs, GL_COMPILE_STATUS, &vsStatus); + GetShaderInfoLog(vs, 1024, nullptr, infoLog); + ASSERT_EQ(vsStatus, GL_TRUE) << infoLog; printf("Compiled vertex shader.\n"); GLuint fs = CreateShader(GL_FRAGMENT_SHADER); ShaderSource(fs, 1, &fsSrc, NULL); printf("Compiling fragment shader: %s\n", fsSrc); CompileShader(fs); + GLint fsStatus = GL_FALSE; + GetShaderiv(fs, GL_COMPILE_STATUS, &fsStatus); + GetShaderInfoLog(fs, 1024, nullptr, infoLog); + ASSERT_EQ(fsStatus, GL_TRUE) << infoLog; printf("Compiled fragment shader.\n"); GLuint program = CreateProgram(); @@ -124,18 +135,37 @@ TEST_F(ProgramTest, CompileAndLink) { LinkProgram(program); printf("Program linked.\n"); - EXPECT_EQ(GetUniformLocation(program, "ProjMat"), 0); - EXPECT_EQ(GetUniformLocation(program, "Gray"), 1); - EXPECT_EQ(GetUniformLocation(program, "Saturation"), 6); + ASSERT_EQ(GetUniformLocation(program, "ProjMat"), 0); + ASSERT_EQ(GetUniformLocation(program, "Gray"), 1); + ASSERT_EQ(GetUniformLocation(program, "Saturation"), 6); GLint uniformCount = 0; GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformCount); - EXPECT_EQ(uniformCount, 11); + ASSERT_EQ(uniformCount, 12); GLint uniformNameMaxLength = 0; GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformNameMaxLength); - EXPECT_EQ(uniformNameMaxLength, 12); + ASSERT_EQ(uniformNameMaxLength, 12); - EXPECT_EQ(GetAttribLocation(program, "Position"), 0); - EXPECT_EQ(GetAttribLocation(program, "fIn1"), 1); - EXPECT_EQ(GetAttribLocation(program, "fIn3"), 3); - EXPECT_EQ(GetAttribLocation(program, "fIn5"), 5); + ASSERT_EQ(GetAttribLocation(program, "Position"), 0); + ASSERT_EQ(GetAttribLocation(program, "fIn1"), 1); + ASSERT_EQ(GetAttribLocation(program, "fIn3"), 3); + ASSERT_EQ(GetAttribLocation(program, "fIn5"), 5); + + UseProgram(program); + + auto locRed = GetUniformLocation(program, "RedMatrix"); + Uniform3f(locRed, 1.0, 3.0, 5.0); + float redVal[3]; + GetUniformfv(program, locRed, redVal); + ASSERT_EQ(redVal[0], 1.0); + ASSERT_EQ(redVal[1], 3.0); + ASSERT_EQ(redVal[2], 5.0); + + auto locAbc = GetUniformLocation(program, "AQuickFoxJumpsOverALazyDog"); + ASSERT_EQ(locAbc, -1); + + auto locInt = GetUniformLocation(program, "intVal"); + Uniform1i(locInt, 114514); + int intVal; + GetUniformiv(program, locInt, &intVal); + EXPECT_EQ(intVal, 114514); }