mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (MG_Impl, MG_State): implement the DSA vertex array queries
glGetVertexArrayiv, glGetVertexArrayIndexediv and glGetVertexArrayIndexed64iv were stubs, so nothing could read a vertex array's state without binding it first -- the exact thing direct state access exists to avoid. They read the state the vertex array already holds. Two accessors were needed for that: the relative offset and the binding points, which are the binding-point view the flat per-attribute state was resolved from and cannot be reconstructed from the resolved form. Note the index means different things by entry point: for the 32-bit indexed query it is an attribute, but GL_VERTEX_BINDING_OFFSET names a vertex buffer binding point directly (GL 4.6 core 10.3.1). GL_VERTEX_ATTRIB_ARRAY_LONG is answered GL_FALSE throughout, which is honest while 64-bit vertex attributes are unsupported. Takes direct_state_access.vertex_arrays_* from 8 to 12 of 19 on Espryt. GL_VERTEX_BINDING_OFFSET still reads back 0: the query is right but the offset is not reaching the binding point, which is a separate defect further up.
This commit is contained in:
@@ -1092,9 +1092,9 @@ DECLARE_GL_FUNCTION_HEAD(void, VertexArrayAttribFormat, GLuint vaobj, GLuint att
|
||||
DECLARE_GL_FUNCTION_HEAD(void, VertexArrayAttribIFormat, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexArrayAttribIFormat, vaobj, attribindex, size, type, relativeoffset)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexArrayAttribLFormat, GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexArrayAttribLFormat, vaobj, attribindex, size, type, relativeoffset)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, VertexArrayBindingDivisor, GLuint vaobj, GLuint bindingindex, GLuint divisor) DECLARE_GL_FUNCTION_END_NO_RETURN(void, VertexArrayBindingDivisor, vaobj, bindingindex, divisor)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayiv, GLuint vaobj, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayiv, vaobj, pname, param)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayIndexediv, GLuint vaobj, GLuint index, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayIndexediv, vaobj, index, pname, param)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetVertexArrayIndexed64iv, GLuint vaobj, GLuint index, GLenum pname, GLint64* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetVertexArrayIndexed64iv, vaobj, index, pname, param)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayiv, GLuint vaobj, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexArrayiv, vaobj, pname, param)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayIndexediv, GLuint vaobj, GLuint index, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexArrayIndexediv, vaobj, index, pname, param)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetVertexArrayIndexed64iv, GLuint vaobj, GLuint index, GLenum pname, GLint64* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetVertexArrayIndexed64iv, vaobj, index, pname, param)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, CreateSamplers, GLsizei n, GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateSamplers, n, samplers)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CreateProgramPipelines, GLsizei n, GLuint* pipelines) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CreateProgramPipelines, n, pipelines)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, CreateQueries, GLenum target, GLsizei n, GLuint* ids) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateQueries, target, n, ids)
|
||||
|
||||
@@ -1044,6 +1044,83 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
VertexArrayVertexBuffer_State(vaobj, bindingindex, buffer, offset, stride);
|
||||
}
|
||||
|
||||
// glGetVertexArrayiv reports exactly one thing (GL 4.6 core table 23.4): which buffer the
|
||||
// named vertex array takes its indices from. Everything else about a vertex array is
|
||||
// per-attribute and belongs to the indexed queries below.
|
||||
void GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint* param) {
|
||||
auto vao = GetNamedVertexArrayObject_State(vaobj, __func__);
|
||||
if (!vao || !param) return;
|
||||
if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"pname must be GL_ELEMENT_ARRAY_BUFFER_BINDING."));
|
||||
return;
|
||||
}
|
||||
const auto& indexBuffer = vao->GetIndexBufferBindingSlot().GetBoundObject();
|
||||
*param = indexBuffer ? static_cast<GLint>(indexBuffer->GetExternalIndex()) : 0;
|
||||
}
|
||||
|
||||
void GetVertexArrayIndexediv(GLuint vaobj, GLuint index, GLenum pname, GLint* param) {
|
||||
auto vao = GetNamedVertexArrayObject_State(vaobj, __func__);
|
||||
if (!vao || !param) return;
|
||||
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
|
||||
const auto& attr = vao->GetAttribute(index);
|
||||
switch (pname) {
|
||||
case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
|
||||
*param = attr.Enabled ? GL_TRUE : GL_FALSE;
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_SIZE:
|
||||
*param = static_cast<GLint>(attr.Size);
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
|
||||
*param = static_cast<GLint>(attr.Stride);
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_TYPE:
|
||||
*param = static_cast<GLint>(MG_Util::ConvertDataTypeToGLEnum(attr.Type));
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
|
||||
*param = attr.Normalized ? GL_TRUE : GL_FALSE;
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
|
||||
*param = attr.IsInteger ? GL_TRUE : GL_FALSE;
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_LONG:
|
||||
// 64-bit attributes are not supported, so no attribute is ever a long one.
|
||||
*param = GL_FALSE;
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
|
||||
*param = static_cast<GLint>(attr.Divisor);
|
||||
return;
|
||||
case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
|
||||
*param = static_cast<GLint>(vao->GetAttributeRelativeOffset(index));
|
||||
return;
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"pname is not an accepted indexed vertex array query."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Only GL_VERTEX_BINDING_OFFSET needs 64 bits. Its `index` names a vertex buffer binding
|
||||
// point directly (GL 4.6 core 10.3.1), not an attribute - unlike every pname the 32-bit
|
||||
// indexed query above accepts, which is why this one does not go through an attribute's
|
||||
// binding index.
|
||||
void GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, GLenum pname, GLint64* param) {
|
||||
auto vao = GetNamedVertexArrayObject_State(vaobj, __func__);
|
||||
if (!vao || !param) return;
|
||||
if (!VertexArrayImpl::ValidateVertexAttributeIndex(index)) return;
|
||||
if (pname != GL_VERTEX_BINDING_OFFSET) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "pname must be GL_VERTEX_BINDING_OFFSET."));
|
||||
return;
|
||||
}
|
||||
*param = static_cast<GLint64>(vao->GetBindingPoint(index).Offset);
|
||||
}
|
||||
|
||||
void VertexArrayAttribFormat(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized,
|
||||
GLuint relativeoffset) {
|
||||
VertexArrayAttribFormat_State(vaobj, attribindex, size, type, normalized, relativeoffset);
|
||||
|
||||
@@ -92,6 +92,9 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void EnableVertexArrayAttrib(GLuint vaobj, GLuint index);
|
||||
void VertexArrayElementBuffer(GLuint vaobj, GLuint buffer);
|
||||
void VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
|
||||
void GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint* param);
|
||||
void GetVertexArrayIndexediv(GLuint vaobj, GLuint index, GLenum pname, GLint* param);
|
||||
void GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index, GLenum pname, GLint64* param);
|
||||
void VertexArrayAttribFormat(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized,
|
||||
GLuint relativeoffset);
|
||||
void VertexArrayAttribIFormat(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
|
||||
|
||||
@@ -84,6 +84,21 @@ namespace MobileGL {
|
||||
void SetAttributeFormatSeparate(Uint attribIndex, int size, DataType type, Bool normalized,
|
||||
Bool isInteger, Uint relativeOffset);
|
||||
|
||||
// The binding-point view the attributes were resolved from. Kept queryable
|
||||
// because glGetVertexArrayIndexed[64]iv reports it verbatim, and the resolved
|
||||
// flat attribute cannot always be inverted back into it.
|
||||
Uint GetAttributeRelativeOffset(Uint attribIndex) const {
|
||||
return attribIndex < m_attributeRelativeOffset.size() ? m_attributeRelativeOffset[attribIndex] : 0;
|
||||
}
|
||||
Uint GetAttributeBindingIndex(Uint attribIndex) const {
|
||||
return attribIndex < m_attributeBindingIndex.size() ? m_attributeBindingIndex[attribIndex]
|
||||
: attribIndex;
|
||||
}
|
||||
const VertexBufferBindingPoint& GetBindingPoint(Uint bindingIndex) const {
|
||||
static const VertexBufferBindingPoint kEmpty{};
|
||||
return bindingIndex < m_bindingPoints.size() ? m_bindingPoints[bindingIndex] : kEmpty;
|
||||
}
|
||||
|
||||
const VertexAttributeVersion& GetAttributeVersion(Uint index) const;
|
||||
const Array<VertexAttributeVersion, MAX_VERTEX_ATTRIBS>& GetAllAttributeVersions() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user