mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 12:18:30 +09:00
[Feat] (MG_Impl, MG_State, MG_Backend, MG_Util): packed 2_10_10_10 and GL_BGRA vertex array formats
glVertexAttribPointer now accepts the GL 3.3 Core packed types GL_INT_/GL_UNSIGNED_INT_2_10_10_10_REV and the GL_BGRA size, clearing the two long-standing "// TODO: implement GL_BGRA support" markers. Adds the format end to end across the frontend, VAO state, and both backends. - DataType: add Int2101010Rev / Uint2101010Rev with GLToMG / MGToGL / MGToStr converter cases. - Validation (ValidateVertexAttribFormat): the full glVertexAttribPointer / glVertexAttribIPointer error table -- size is 1..4 or GL_BGRA (else INVALID_VALUE, which takes precedence); a packed type requires size 4 or GL_BGRA (else INVALID_OPERATION); GL_BGRA requires GL_UNSIGNED_BYTE or a packed type AND normalized == GL_TRUE (else INVALID_OPERATION); the integer path rejects packed types (INVALID_ENUM) and GL_BGRA size (INVALID_VALUE). - VAO: store GL_BGRA as size 4 plus a new IsBgra flag (reset on the binding-format path). - DirectVulkan: map the packed/BGRA formats to VK_FORMAT_A2B10G10R10_* (normal) and VK_FORMAT_A2R10G10B10_* / VK_FORMAT_B8G8R8A8_UNORM (BGRA reversed), fold IsBgra into the pipeline hash, and size packed/BGRA elements as one 4-byte word via GetAttributeByteSize. (Vulkan *_SNORM decodes with the GL 4.2 symmetric rule, a documented deviation from the 3.3 signed formula.) - DirectGLES: round-trip the packed enum through the loader, pass GL_BGRA as the driver size argument, and size client uploads with the packed 4-byte word. Tests: 4 VertexArrayTest cases covering packed/BGRA storage and the full float/integer error table; the packed-size hard-fail is mutation-verified. VertexArrayTest 42/42, SanityTest 30/30, library builds clean.
This commit is contained in:
@@ -89,4 +89,85 @@ namespace MobileGL::MG_Impl::GLImpl::VertexArrayImpl {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Bool ValidateVertexAttribFormat(Uint index, GLint sizeRaw, DataType type, Bool normalized, Int stride,
|
||||
Bool integerPath) {
|
||||
constexpr const char* fn = "ValidateVertexAttribFormat";
|
||||
if (type == DataType::Unknown) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", fn,
|
||||
std::format("Invalid type for attribute {}.", index)));
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool isPacked = (type == DataType::Int2101010Rev || type == DataType::Uint2101010Rev);
|
||||
// The packed 2_10_10_10 types are float-normalizing only; glVertexAttribIPointer never accepts them.
|
||||
if (integerPath && isPacked) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", fn,
|
||||
std::format("glVertexAttribIPointer does not accept packed 2_10_10_10 types (attribute {}).",
|
||||
index)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sizeRaw == static_cast<GLint>(GL_BGRA)) {
|
||||
// GL_BGRA is a float-path-only size: it needs GL_UNSIGNED_BYTE or a 2_10_10_10 type and
|
||||
// normalized == GL_TRUE. On the integer path it is simply an out-of-range size.
|
||||
if (integerPath) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", fn,
|
||||
std::format("GL_BGRA size is not valid for glVertexAttribIPointer (attribute {}).", index)));
|
||||
return false;
|
||||
}
|
||||
if (!(type == DataType::Uint8 || isPacked)) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", fn,
|
||||
std::format("GL_BGRA size requires GL_UNSIGNED_BYTE or a 2_10_10_10 type (attribute {}).",
|
||||
index)));
|
||||
return false;
|
||||
}
|
||||
if (!normalized) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", fn,
|
||||
std::format("GL_BGRA size requires normalized == GL_TRUE (attribute {}).", index)));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Size-range (INVALID_VALUE) takes precedence over the packed-size-must-be-4 rule.
|
||||
if (sizeRaw < 1 || sizeRaw > 4) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", fn,
|
||||
std::format("Invalid size {} for attribute {}. Must be 1-4 or GL_BGRA.", sizeRaw, index)));
|
||||
return false;
|
||||
}
|
||||
if (isPacked && sizeRaw != 4) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", fn,
|
||||
std::format("A 2_10_10_10 type requires size 4 or GL_BGRA (attribute {}).", index)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (stride < 0) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", fn,
|
||||
std::format("Negative stride {} for attribute {}.", stride, index)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace MobileGL::MG_Impl::GLImpl::VertexArrayImpl
|
||||
|
||||
Reference in New Issue
Block a user