[Fix, Test] (MG_Util, MG_State, MG_Backend): the GL 4.3 vertex binding model - array vertex inputs, zero binding strides, instance divisors, and formats ES refuses

This commit is contained in:
2026-08-12 05:36:00 -04:00
parent 21b5fc2d92
commit 2fced2241b
13 changed files with 1129 additions and 29 deletions
@@ -61,12 +61,16 @@ namespace MobileGL::MG_State::GLState {
}
void VertexArrayObject::SetAttributeFormat(Uint index, int size, DataType type, Bool normalized, int stride,
SizeT offset, Bool isInteger, Bool isBgra) {
SizeT offset, Bool isInteger, Bool isBgra, int effectiveStride) {
if (index >= MAX_VERTEX_ATTRIBS) return;
if (size < 1 || size > 4) {
return;
}
// See VertexAttribute::Stride: the resolved field carries the effective stride so that
// a zero in it can only ever mean the binding model's "do not advance".
const int resolvedStride = effectiveStride >= 0 ? effectiveStride : stride;
// The classic pointer-style API takes back full ownership of the resolved fields.
m_attributeUsesBindingModel[index] = false;
@@ -77,7 +81,7 @@ namespace MobileGL::MG_State::GLState {
m_attributes[index].LegacyPointer = offset;
if (m_attributes[index].Size == size && m_attributes[index].Type == type &&
m_attributes[index].Normalized == normalized && m_attributes[index].Stride == stride &&
m_attributes[index].Normalized == normalized && m_attributes[index].Stride == resolvedStride &&
m_attributes[index].Offset == offset && m_attributes[index].IsInteger == isInteger &&
m_attributes[index].IsBgra == isBgra && !m_attributes[index].IsLong) {
return;
@@ -87,7 +91,7 @@ namespace MobileGL::MG_State::GLState {
attr.Size = size;
attr.Type = type;
attr.Normalized = normalized;
attr.Stride = stride;
attr.Stride = resolvedStride;
attr.Offset = offset;
attr.IsInteger = isInteger;
attr.IsBgra = isBgra;
@@ -19,6 +19,14 @@ namespace MobileGL {
int Size = 4;
DataType Type = DataType::Float32;
Bool Normalized = false;
// The RESOLVED byte distance between consecutive elements, never the raw
// glVertexAttrib*Pointer argument: a pointer call's stride 0 means "tightly
// packed" and is resolved to the element size here, so a zero that survives
// into this field can only have come from the binding model, where a zero
// VERTEX_BINDING_STRIDE means the opposite - every vertex reads the SAME
// element and the fetch address never advances (GL 4.6 core 10.3.1). Backends
// consume this verbatim; collapsing 0 back into the element size is what made
// KHR-GL43.vertex_attrib_binding.basic-input-case7/8 read past the buffer.
int Stride = 0;
SizeT Offset = 0;
Bool IsInteger = false;
@@ -76,8 +84,12 @@ namespace MobileGL {
void DisableAttribute(Uint index);
Bool IsAttributeEnabled(Uint index) const;
// `stride` is the raw glVertexAttrib*Pointer argument, reported verbatim by
// GL_VERTEX_ATTRIB_ARRAY_STRIDE. `effectiveStride` is what the fetch actually
// advances by - the same value when the argument is non-zero, the tightly
// packed element size when it is zero. Pass -1 to say the two are the same.
void SetAttributeFormat(Uint index, int size, DataType type, Bool normalized, int stride, SizeT offset,
Bool isInteger, Bool isBgra = false);
Bool isInteger, Bool isBgra = false, int effectiveStride = -1);
void BindAttributeBuffer(Uint index, const SharedPtr<BufferObject>& buffer);