mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (MG_Impl/VertexArray): implement client-side buffer
This commit is contained in:
@@ -863,6 +863,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
#endif
|
#endif
|
||||||
DrawSyncBit syncBit = DrawSyncBit::None;
|
DrawSyncBit syncBit = DrawSyncBit::None;
|
||||||
PrepareForDraw(syncBit);
|
PrepareForDraw(syncBit);
|
||||||
|
const auto& currentVAO = MG_State::pGLContext->GetBoundVertexArray();
|
||||||
|
if (currentVAO) {
|
||||||
|
const auto& backendVAOIt = VertexArrayImpl::g_backendVertexArrayObjects.find(currentVAO.get());
|
||||||
|
if (backendVAOIt != VertexArrayImpl::g_backendVertexArrayObjects.end()) {
|
||||||
|
backendVAOIt->second->SyncClientSideAttributesForDrawArrays(currentVAO, first, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
g_GLESFuncs.glDrawArrays(mode, first, count);
|
g_GLESFuncs.glDrawArrays(mode, first, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,10 +194,34 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
} // namespace BufferImpl
|
} // namespace BufferImpl
|
||||||
|
|
||||||
namespace VertexArrayImpl {
|
namespace VertexArrayImpl {
|
||||||
|
namespace {
|
||||||
|
SizeT GetDataTypeSize(DataType type) {
|
||||||
|
switch (type) {
|
||||||
|
case DataType::Int8:
|
||||||
|
case DataType::Uint8:
|
||||||
|
return 1;
|
||||||
|
case DataType::Int16:
|
||||||
|
case DataType::Uint16:
|
||||||
|
case DataType::Float16:
|
||||||
|
return 2;
|
||||||
|
case DataType::Int32:
|
||||||
|
case DataType::Uint32:
|
||||||
|
case DataType::Float32:
|
||||||
|
case DataType::Fixed32:
|
||||||
|
return 4;
|
||||||
|
case DataType::Float64:
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
BackendVertexArrayObject::BackendVertexArrayObject() {
|
BackendVertexArrayObject::BackendVertexArrayObject() {
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||||
#endif
|
#endif
|
||||||
|
m_clientAttributeBufferIds.fill(0);
|
||||||
g_GLESFuncs.glGenVertexArrays(1, &m_backendVAOId);
|
g_GLESFuncs.glGenVertexArrays(1, &m_backendVAOId);
|
||||||
if (m_backendVAOId == 0) {
|
if (m_backendVAOId == 0) {
|
||||||
MGLOG_E("Failed to generate vertex array object.");
|
MGLOG_E("Failed to generate vertex array object.");
|
||||||
@@ -207,6 +231,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackendVertexArrayObject::~BackendVertexArrayObject() {
|
||||||
|
if (m_backendVAOId != 0) {
|
||||||
|
g_GLESFuncs.glDeleteVertexArrays(1, &m_backendVAOId);
|
||||||
|
m_backendVAOId = 0;
|
||||||
|
}
|
||||||
|
for (auto& bufferId : m_clientAttributeBufferIds) {
|
||||||
|
if (bufferId != 0) {
|
||||||
|
g_GLESFuncs.glDeleteBuffers(1, &bufferId);
|
||||||
|
bufferId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BackendVertexArrayObject::Bind() const {
|
void BackendVertexArrayObject::Bind() const {
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
|
||||||
@@ -312,6 +349,58 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
m_syncedAttributeVersions = allAttributeVersions;
|
m_syncedAttributeVersions = allAttributeVersions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BackendVertexArrayObject::SyncClientSideAttributesForDrawArrays(
|
||||||
|
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count) {
|
||||||
|
if (!stateVAOObject || count <= 0 || first < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
|
||||||
|
const auto& allAttributes = stateVAOObject->GetAllAttributes();
|
||||||
|
for (Uint attribIndex = 0; attribIndex < allAttributes.size(); ++attribIndex) {
|
||||||
|
const auto& attrib = allAttributes[attribIndex];
|
||||||
|
if (!attrib.Enabled || attrib.Buffer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* clientData = reinterpret_cast<const Uint8*>(attrib.Offset);
|
||||||
|
const SizeT componentSize = GetDataTypeSize(attrib.Type);
|
||||||
|
if (!clientData || componentSize == 0 || attrib.Size <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SizeT elementSize = componentSize * static_cast<SizeT>(attrib.Size);
|
||||||
|
const SizeT stride = attrib.Stride > 0 ? static_cast<SizeT>(attrib.Stride) : elementSize;
|
||||||
|
const SizeT uploadSize = static_cast<SizeT>(first + count - 1) * stride + elementSize;
|
||||||
|
|
||||||
|
auto& bufferId = m_clientAttributeBufferIds[attribIndex];
|
||||||
|
if (bufferId == 0) {
|
||||||
|
g_GLESFuncs.glGenBuffers(1, &bufferId);
|
||||||
|
if (bufferId == 0) {
|
||||||
|
MGLOG_E("Failed to create client-side vertex attribute upload buffer.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_GLESFuncs.glBindBuffer(GL_ARRAY_BUFFER, bufferId);
|
||||||
|
g_GLESFuncs.glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(uploadSize), clientData,
|
||||||
|
GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
if (!attrib.IsInteger) {
|
||||||
|
g_GLESFuncs.glVertexAttribPointer(
|
||||||
|
attribIndex, attrib.Size, MG_Util::ConvertDataTypeToGLEnum(attrib.Type),
|
||||||
|
attrib.Normalized ? GL_TRUE : GL_FALSE, static_cast<GLsizei>(stride), nullptr);
|
||||||
|
} else {
|
||||||
|
g_GLESFuncs.glVertexAttribIPointer(attribIndex, attrib.Size,
|
||||||
|
MG_Util::ConvertDataTypeToGLEnum(attrib.Type),
|
||||||
|
static_cast<GLsizei>(stride), nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferImpl::g_boundVertexBufferObject = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
|
StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
|
||||||
g_backendVertexArrayObjects;
|
g_backendVertexArrayObjects;
|
||||||
} // namespace VertexArrayImpl
|
} // namespace VertexArrayImpl
|
||||||
|
|||||||
@@ -137,12 +137,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
class BackendVertexArrayObject {
|
class BackendVertexArrayObject {
|
||||||
public:
|
public:
|
||||||
BackendVertexArrayObject();
|
BackendVertexArrayObject();
|
||||||
|
~BackendVertexArrayObject();
|
||||||
void SyncToBackend(const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject);
|
void SyncToBackend(const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject);
|
||||||
|
void SyncClientSideAttributesForDrawArrays(
|
||||||
|
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count);
|
||||||
Uint GetBackendVertexArrayId() const { return m_backendVAOId; }
|
Uint GetBackendVertexArrayId() const { return m_backendVAOId; }
|
||||||
void Bind() const;
|
void Bind() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Uint m_backendVAOId = 0;
|
Uint m_backendVAOId = 0;
|
||||||
|
Array<Uint, MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS> m_clientAttributeBufferIds;
|
||||||
Bool m_isInitialized = false;
|
Bool m_isInitialized = false;
|
||||||
Uint16 m_syncedIndexBufferVersion = 0;
|
Uint16 m_syncedIndexBufferVersion = 0;
|
||||||
Array<MG_State::GLState::VertexAttributeVersion, MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS>
|
Array<MG_State::GLState::VertexAttributeVersion, MG_State::GLState::VertexArrayObject::MAX_VERTEX_ATTRIBS>
|
||||||
|
|||||||
@@ -60,12 +60,6 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
|
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
|
||||||
auto& vbo = vboSlot.GetBoundObject();
|
auto& vbo = vboSlot.GetBoundObject();
|
||||||
if (!vbo) {
|
|
||||||
MG_State::pGLContext->RecordError(
|
|
||||||
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
|
|
||||||
"No buffer is bound to GL_ARRAY_BUFFER."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto offset = reinterpret_cast<SizeT>(pointer);
|
auto offset = reinterpret_cast<SizeT>(pointer);
|
||||||
|
|
||||||
@@ -91,12 +85,6 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
|
|
||||||
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
|
auto& vboSlot = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::Vertex);
|
||||||
auto& vbo = vboSlot.GetBoundObject();
|
auto& vbo = vboSlot.GetBoundObject();
|
||||||
if (!vbo) {
|
|
||||||
MG_State::pGLContext->RecordError(
|
|
||||||
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "VertexAttribPointer_State",
|
|
||||||
"No buffer is bound to GL_ARRAY_BUFFER."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeT offset = reinterpret_cast<SizeT>(pointer);
|
SizeT offset = reinterpret_cast<SizeT>(pointer);
|
||||||
|
|
||||||
|
|||||||
@@ -363,6 +363,24 @@ TEST_F(GeneralVertexArrayTest, General_ElementArrayBufferBindingIsVaoLocalAndZer
|
|||||||
EXPECT_EQ(GetError(), GL_NO_ERROR);
|
EXPECT_EQ(GetError(), GL_NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(GeneralVertexArrayTest, General_ClientSideVertexAttribPointerIsAccepted) {
|
||||||
|
GLuint vao = CreateVAO();
|
||||||
|
BindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
float vertices[] = {0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
|
||||||
|
EnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
auto vaoObj = MG_State::pGLContext->GetVertexArrayObject(vao);
|
||||||
|
ASSERT_NE(vaoObj, nullptr);
|
||||||
|
|
||||||
|
const auto& attr = vaoObj->GetAttribute(0);
|
||||||
|
EXPECT_TRUE(attr.Enabled);
|
||||||
|
EXPECT_EQ(attr.Buffer, nullptr);
|
||||||
|
EXPECT_EQ(attr.Offset, reinterpret_cast<SizeT>(vertices));
|
||||||
|
EXPECT_EQ(GetError(), GL_NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(GeneralVertexArrayTest, General_IntegerAttributes) {
|
TEST_F(GeneralVertexArrayTest, General_IntegerAttributes) {
|
||||||
GLuint vao = CreateVAO();
|
GLuint vao = CreateVAO();
|
||||||
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 128);
|
GLuint vbo = CreateVBO(GL_ARRAY_BUFFER, 128);
|
||||||
|
|||||||
Reference in New Issue
Block a user