[Fix] (MG_Impl/GLImpl): unblock the non-texture sections of GL CTS per-case state reset - clamp advertised GL_MAX_UNIFORM_BUFFER_BINDINGS to the state layer indexed-binding capacity (glBindBufferBase rejected indices past it), let glBindRenderbuffer(0) unbind without recording INVALID_OPERATION (name 0 must never reach the name-table lookup), and allow writes to generic vertex attribute 0 current value (core GL has no attribute-0 restriction; gluStateReset writes vertexAttrib4f(0,...) after every case) - with these plus the default-texture work, multi-case glcts batches complete in one process instead of aborting after the first case

This commit is contained in:
2026-07-16 23:36:58 -04:00
parent 076cd0d19d
commit 981f10e4da
4 changed files with 32 additions and 13 deletions
@@ -76,7 +76,13 @@ namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl {
}
Bool ValidateRenderbufferName(Uint index, Bool allowZero) {
if (index == 0 && !allowZero) {
if (index == 0) {
// Zero is never a GenRenderbuffers name, so it must not reach the name-table lookup
// below: where it is allowed (glBindRenderbuffer / FramebufferRenderbuffer detach) it
// means "unbind", and looking it up would record a bogus INVALID_OPERATION - GL CTS's
// per-case state reset calls glBindRenderbuffer(GL_RENDERBUFFER, 0) after every case.
if (allowZero) return true;
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName",
+9 -1
View File
@@ -1894,7 +1894,15 @@ namespace MobileGL::MG_Impl::GLImpl {
*params = dynamicParameters.MaxTextureSize;
break;
case GL_MAX_UNIFORM_BUFFER_BINDINGS:
*params = std::max(dynamicParameters.MaxUniformBufferBindings, kFrontendMinUniformBufferBindings);
// Never advertise more indexed binding points than the state layer's fixed per-target
// array can store (BufferBindingPointCount): glBindBufferBase rejects indices past
// that capacity, and GL CTS's per-case state reset walks every advertised binding
// (gluStateReset), so an over-advertised value aborts whole test batches. The floor
// equals the GL 3.3 core minimum (36), so the clamp never under-advertises.
*params = static_cast<GLint>(std::min<SizeT>(
static_cast<SizeT>(std::max(dynamicParameters.MaxUniformBufferBindings,
kFrontendMinUniformBufferBindings)),
MG_State::GLState::BufferBindingPointCount));
break;
case GL_MAX_UNIFORM_BLOCK_SIZE:
*params = dynamicParameters.MaxUniformBlockSize;
@@ -78,15 +78,12 @@ namespace MobileGL::MG_Impl::GLImpl {
}
static bool ValidateCurrentVertexAttribIndex(GLuint index, const char* funcName) {
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return false;
if (index == 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", funcName,
"Generic vertex attribute 0 current value cannot be modified."));
return false;
}
return true;
// GL 3.3 core 2.7: VertexAttrib* sets the current value of ANY generic attribute,
// including index 0 - only an out-of-range index is an error (INVALID_VALUE).
// "Attribute 0 is immutable" was legacy immediate-mode lore; rejecting it broke GL
// CTS's per-case state reset, which writes vertexAttrib4f(0, 0,0,0,1) after every case.
(void)funcName;
return VertexArrayImpl::ValidateVertexAttributeIndex(index);
}
static bool TryGetVertexAttribute(GLuint index, const MG_State::GLState::VertexAttribute** outAttr) {
@@ -1173,9 +1173,17 @@ TEST_F(GeneralVertexArrayTest, CurrentAttrib_PackedValidation) {
GetVertexAttribfv(1, GL_CURRENT_VERTEX_ATTRIB, out);
EXPECT_FLOAT_EQ(out[0], 42.0f); // unchanged by the failed call
// Attribute 0 is rejected by MobileGL policy (GL_INVALID_OPERATION).
// GL 3.3 core 2.7: attribute 0's current value is writable like any other generic
// attribute - no error. (An earlier MobileGL policy rejected index 0 with
// GL_INVALID_OPERATION, which broke GL CTS's per-case state reset: gluStateReset writes
// vertexAttrib4f(0, 0,0,0,1) for every attribute after every case.)
VertexAttribP4ui(0, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 1u);
EXPECT_EQ(GetError(), GL_INVALID_OPERATION);
EXPECT_EQ(GetError(), GL_NO_ERROR);
GetVertexAttribfv(0, GL_CURRENT_VERTEX_ATTRIB, out);
EXPECT_EQ(GetError(), GL_NO_ERROR);
EXPECT_FLOAT_EQ(out[0], 1.0f); // x field of the packed word
VertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f); // restore the initial current value
EXPECT_EQ(GetError(), GL_NO_ERROR);
// Out-of-range index -> GL_INVALID_VALUE.
VertexAttribP4ui(VertexArrayImpl::GetMaxVertexAttribs(), GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 1u);