mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 05:38:31 +09:00
[Feat] (MG_Impl/GLImpl, MG_State): implement glGetActiveUniformsiv (UBO reflection query)
Completes the uniform-block reflection chain: glGetUniformIndices, glGetActiveUniformName and glGetActiveUniformBlockiv were already implemented; glGetActiveUniformsiv was the last stub. Supports all 8 GL 3.3 Core pnames: * GL_UNIFORM_TYPE / SIZE / NAME_LENGTH / BLOCK_INDEX / OFFSET / ARRAY_STRIDE come straight from glslang's TObjectReflection (the same reflection the existing uniform queries use). * GL_UNIFORM_IS_ROW_MAJOR from the member's TType layout qualifier, guarded by isMatrix() so a scalar in a layout(row_major) block does not wrongly report 1. * GL_UNIFORM_MATRIX_STRIDE is derived: glslang exposes no matrix stride, so it is computed from the std140 rule (each column/row vector rounded up to a vec4), which matches the std140 layout MobileGL's SPIR-V path emits. Evaluates to 16 for every GL 3.3 float matrix. The -1-vs-0 distinction is handled explicitly: OFFSET / ARRAY_STRIDE / MATRIX_STRIDE / BLOCK_INDEX return -1 for a default-block uniform (glslang gives arrayStride 0 there, so it is gated on block membership), while ARRAY_STRIDE / MATRIX_STRIDE return 0 for a non-array / non-matrix member that IS in a block. Errors: GL_INVALID_VALUE for uniformCount<0, any index >= active uniform count, or a never-generated program name; GL_INVALID_OPERATION for a live shader name; GL_INVALID_ENUM for an unaccepted pname (e.g. the GL 4.2 GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX). All validation runs before any write, so params is untouched on error. There is no "not linked" error -- an unlinked program has zero active uniforms, so any index raises GL_INVALID_VALUE. Also fix GetActiveUniformArraySize, which returned glslang's TObjectReflection.size verbatim: that field only carries the element count for a non-block array and reports 1 for a block array member, so GL_UNIFORM_SIZE (and glGetActiveUniform's size out-param, and glGetProgramResourceiv's GL_ARRAY_SIZE) wrongly reported 1 for an array inside a UBO. Take the count from the TType instead, which is authoritative for both cases. Covered by 3 ProgramTest cases (std140 block with scalar/array/mat4 + a default-block sampler, a row_major variant, and the six error cases) that link real shaders and assert every pname value.
This commit is contained in:
@@ -265,7 +265,7 @@ DECLARE_GL_FUNCTION_HEAD(void, ClearBufferfv, GLenum buffer, GLint drawbuffer, c
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ClearBufferfi, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearBufferfi, buffer, drawbuffer, depth, stencil)
|
||||
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_HEAD(void, GetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) DECLARE_GL_FUNCTION_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_HEAD(void, GetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetActiveUniformsiv, program, uniformCount, uniformIndices, pname, params)
|
||||
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)
|
||||
|
||||
@@ -424,6 +424,101 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
}
|
||||
|
||||
void GetActiveUniformsiv_State(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname,
|
||||
GLint* params) {
|
||||
if (uniformCount < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"uniformCount " + std::to_string(uniformCount) + " is less than 0."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Program-name resolution with the correct two-error split: a live shader name is
|
||||
// GL_INVALID_OPERATION, a never-generated name is GL_INVALID_VALUE. glGetActiveUniformsiv has
|
||||
// no "not linked" error, so unlike TryToGetLinkedProgramForInterfaceQuery there is no
|
||||
// link-status check here; an unlinked program simply has zero active uniforms (handled below).
|
||||
if (!MG_State::pGLContext->ValidateProgramName(program)) {
|
||||
const ErrorCode error = MG_State::pGLContext->ValidateShaderName(program) ? ErrorCode::InvalidOperation
|
||||
: ErrorCode::InvalidValue;
|
||||
MG_State::pGLContext->RecordError(
|
||||
error, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
std::to_string(program) + " is not a program object."));
|
||||
return;
|
||||
}
|
||||
auto& programObject = MG_State::pGLContext->GetProgramObject(program);
|
||||
if (!programObject) return;
|
||||
|
||||
switch (pname) {
|
||||
case GL_UNIFORM_TYPE:
|
||||
case GL_UNIFORM_SIZE:
|
||||
case GL_UNIFORM_NAME_LENGTH:
|
||||
case GL_UNIFORM_BLOCK_INDEX:
|
||||
case GL_UNIFORM_OFFSET:
|
||||
case GL_UNIFORM_ARRAY_STRIDE:
|
||||
case GL_UNIFORM_MATRIX_STRIDE:
|
||||
case GL_UNIFORM_IS_ROW_MAJOR:
|
||||
break;
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"pname " + std::to_string(pname) + " is not an accepted value."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (uniformCount == 0) return;
|
||||
if (uniformIndices == nullptr || params == nullptr) return;
|
||||
|
||||
// Every index must be < the number of active uniforms, checked before any write so params is
|
||||
// left untouched on error. GetUniformCount() is 0 for an unlinked program, which is also the
|
||||
// spec-mandated GL_INVALID_VALUE path for querying an unlinked program (no separate error).
|
||||
const Uint activeUniforms = programObject->GetUniformCount();
|
||||
for (GLsizei i = 0; i < uniformCount; ++i) {
|
||||
if (uniformIndices[i] >= activeUniforms) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"uniformIndices[" + std::to_string(i) +
|
||||
"] = " + std::to_string(uniformIndices[i]) +
|
||||
" is greater than or equal to the number of active uniforms."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (GLsizei i = 0; i < uniformCount; ++i) {
|
||||
const Uint idx = uniformIndices[i];
|
||||
switch (pname) {
|
||||
case GL_UNIFORM_TYPE:
|
||||
params[i] = static_cast<GLint>(programObject->GetActiveUniformType(idx));
|
||||
break;
|
||||
case GL_UNIFORM_SIZE:
|
||||
params[i] = programObject->GetActiveUniformArraySize(idx);
|
||||
break;
|
||||
case GL_UNIFORM_NAME_LENGTH:
|
||||
params[i] = static_cast<GLint>(programObject->GetActiveUniformName(idx).length() + 1);
|
||||
break;
|
||||
case GL_UNIFORM_BLOCK_INDEX:
|
||||
params[i] = programObject->GetActiveUniformBlockIndex(idx);
|
||||
break;
|
||||
case GL_UNIFORM_OFFSET:
|
||||
params[i] = programObject->GetActiveUniformOffset(idx);
|
||||
break;
|
||||
case GL_UNIFORM_ARRAY_STRIDE:
|
||||
params[i] = programObject->GetActiveUniformArrayStride(idx);
|
||||
break;
|
||||
case GL_UNIFORM_MATRIX_STRIDE:
|
||||
params[i] = programObject->GetActiveUniformMatrixStride(idx);
|
||||
break;
|
||||
case GL_UNIFORM_IS_ROW_MAJOR:
|
||||
params[i] = programObject->GetActiveUniformIsRowMajor(idx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetAttachedShaders_State(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
|
||||
if (maxCount < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
@@ -1503,6 +1598,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
GetUniformIndices_State(program, uniformCount, uniformNames, uniformIndices);
|
||||
}
|
||||
|
||||
void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname,
|
||||
GLint* params) {
|
||||
GetActiveUniformsiv_State(program, uniformCount, uniformIndices, pname, params);
|
||||
}
|
||||
|
||||
void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
|
||||
GetAttachedShaders_State(program, maxCount, count, shaders);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
GLchar* uniformName);
|
||||
void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames,
|
||||
GLuint* uniformIndices);
|
||||
void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname,
|
||||
GLint* params);
|
||||
void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders);
|
||||
GLint GetAttribLocation(GLuint program, const GLchar* name);
|
||||
void GetProgramiv(GLuint program, GLenum pname, GLint* params);
|
||||
|
||||
Reference in New Issue
Block a user