From b3824c871c5a686eb307e81ae9970cb5ccd869f0 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sun, 7 Dec 2025 10:50:13 +0800 Subject: [PATCH] [Feat] (MG_Backend/DirectGLES): Implement more draw funcs. Add DrawSyncBit. --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 182 +++++++++++++++--- MobileGL/MG_Backend/DirectGLES/DirectGLES.h | 17 ++ 2 files changed, 169 insertions(+), 30 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 5b51df3f..2834ed52 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -13,6 +13,22 @@ #include namespace MobileGL::MG_Backend::DirectGLES { + enum class DrawSyncBit : Uint32 { + None = 0, + IndexBuffer = 1 << 0, + IndirectBuffer = 1 << 1, + Instancing = 1 << 2 + }; + + inline DrawSyncBit operator|(DrawSyncBit a, DrawSyncBit b) { + return static_cast(static_cast(a) | static_cast(b)); + } + + inline DrawSyncBit& operator|=(DrawSyncBit& a, DrawSyncBit b) { + a = a | b; + return a; + } + namespace DebugImpl { void ErrorLopper::Loop(std::function func) { #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG @@ -45,9 +61,10 @@ namespace MobileGL::MG_Backend::DirectGLES { // TODO: deletion for deleted objects namespace BufferImpl { - void SyncNeccessaryBuffers() { + void SyncNeccessaryBuffers(Bool includeIBO = false, Bool includeIndirectBuffer = false) { // All buffers we need are: - // 1.VBO 2.IBO 3.UBO 4.PBO 5.SSBO (TODO) + // 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO) + // PBO is not needed since it should be handled in frontend Vector> buffersToSync; const auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); @@ -69,11 +86,25 @@ namespace MobileGL::MG_Backend::DirectGLES { } // IBO - const auto& possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject(); - if (possibleIBO) { - const auto& end = buffersToSync.end(); - if (std::find(buffersToSync.begin(), end, possibleIBO) == end) { - buffersToSync.push_back(possibleIBO); + if (includeIBO) { + const auto& possibleIBO = currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject(); + if (possibleIBO) { + const auto& end = buffersToSync.end(); + if (std::find(buffersToSync.begin(), end, possibleIBO) == end) { + buffersToSync.push_back(possibleIBO); + } + } + } + + // Indirect Buffer Object + if (includeIndirectBuffer) { + const auto& possibleIndirectBuffer = + MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject(); + if (possibleIndirectBuffer) { + const auto& end = buffersToSync.end(); + if (std::find(buffersToSync.begin(), end, possibleIndirectBuffer) == end) { + buffersToSync.push_back(possibleIndirectBuffer); + } } } @@ -323,9 +354,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } } - void PrepareForDraw() { - BufferImpl::SyncNeccessaryBuffers(); - VertexArrayImpl::SyncCurrentVAO(); + void PrepareForDraw(DrawSyncBit syncBit) { + BufferImpl::SyncNeccessaryBuffers(syncBit & DrawSyncBit::IndexBuffer, syncBit & DrawSyncBit::IndirectBuffer); + VertexArrayImpl::SyncCurrentVAO(); // TODO: instancing TextureImpl::SyncNeccessaryTextures(); FramebufferImpl::SyncCurrentFBO(); PrgramImpl::SyncCurrentProgram(); @@ -474,16 +505,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } - void DrawArrays(GLenum mode, GLint first, GLsizei count) { - PrepareForDraw(); - MG_External::GLES::glDrawArrays(mode, first, count); - } - - void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { - PrepareForDraw(); - MG_External::GLES::glDrawElements(mode, count, type, indices); - } - void Clear(GLbitfield mask) { TextureImpl::SyncNeccessaryTextures(); FramebufferImpl::SyncCurrentFBO(); @@ -494,27 +515,128 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glClear(mask); } - void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint baseVertex) { - PrepareForDraw(); - MG_External::GLES::glDrawElementsBaseVertex(mode, count, type, indices, baseVertex); + void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawElements(mode, count, type, indices); } - void MultiDrawElements(GLenum mode, const GLsizei* counts, GLenum type, const void* const* indices, + void DrawArrays(GLenum mode, GLint first, GLsizei count) { + DrawSyncBit syncBit = DrawSyncBit::None; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawArrays(mode, first, count); + } + + void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLint basevertex) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawElementsBaseVertex(mode, count, type, indices, basevertex); + } + + void MultiDrawElements(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices, GLsizei drawcount) { - PrepareForDraw(); + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer; + PrepareForDraw(syncBit); + for (GLsizei i = 0; i < drawcount; ++i) { - MG_External::GLES::glDrawElements(mode, counts[i], type, indices[i]); + MG_External::GLES::glDrawElements(mode, count[i], type, indices[i]); } } - void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* counts, GLenum type, const void* const* indices, - GLsizei drawcount, const GLint* baseVertices) { - PrepareForDraw(); + void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices, + GLsizei drawcount, const GLint* basevertex) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer; + PrepareForDraw(syncBit); + for (GLsizei i = 0; i < drawcount; ++i) { - MG_External::GLES::glDrawElementsBaseVertex(mode, counts[i], type, indices[i], baseVertices[i]); + MG_External::GLES::glDrawElementsBaseVertex(mode, count[i], type, indices[i], basevertex[i]); } } + void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::IndirectBuffer; + PrepareForDraw(syncBit); + + for (GLsizei i = 0; i < drawcount; ++i) { + const GLvoid* cmd = reinterpret_cast(reinterpret_cast(indirect) + + i * (stride ? stride : sizeof(GLsizei) * 4)); + MG_External::GLES::glDrawElementsIndirect(mode, type, cmd); + } + } + + void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) { + DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer; + PrepareForDraw(syncBit); + + for (GLsizei i = 0; i < drawcount; ++i) { + const GLvoid* cmd = reinterpret_cast(reinterpret_cast(indirect) + + i * (stride ? stride : sizeof(GLsizei) * 4)); + MG_External::GLES::glDrawArraysIndirect(mode, cmd); + } + } + + void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const void* indices, GLint basevertex) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex); + } + + void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawRangeElements(mode, start, end, count, type, indices); + } + + void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLint basevertex, GLuint baseinstance) { + // Not supported in OpenGL ES + MGLOG_W("DrawElementsInstancedBaseVertexBaseInstance is not supported in OpenGL ES."); + } + + void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLint basevertex) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::Instancing; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex); + } + + void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLuint baseinstance) { + // Not supported in OpenGL ES + MGLOG_W("DrawElementsInstancedBaseInstance is not supported in OpenGL ES."); + } + + void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::Instancing; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawElementsInstanced(mode, count, type, indices, instancecount); + } + + void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect) { + DrawSyncBit syncBit = DrawSyncBit::IndexBuffer | DrawSyncBit::IndirectBuffer; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawElementsIndirect(mode, type, indirect); + } + + void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, + GLuint baseinstance) { + // Not supported in OpenGL ES + MGLOG_W("DrawArraysInstancedBaseInstance is not supported in OpenGL ES."); + } + + void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) { + DrawSyncBit syncBit = DrawSyncBit::Instancing; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawArraysInstanced(mode, first, count, instancecount); + } + + void DrawArraysIndirect(GLenum mode, const void* indirect) { + DrawSyncBit syncBit = DrawSyncBit::IndirectBuffer; + PrepareForDraw(syncBit); + MG_External::GLES::glDrawArraysIndirect(mode, indirect); + } + void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { DebugImpl::ErrorLopper errorLopper; diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h index 7816d849..06caf70f 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h @@ -14,6 +14,23 @@ namespace MobileGL::MG_Backend::DirectGLES { GLsizei drawcount); void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei* count, GLenum type, const GLvoid* const* indices, GLsizei drawcount, const GLint* basevertex); + void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride); + void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride); + void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, + const void* indices, GLint basevertex); + void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices); + void DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLint basevertex, GLuint baseinstance); + void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLint basevertex); + void DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type, const void* indices, + GLsizei instancecount, GLuint baseinstance); + void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount); + void DrawElementsIndirect(GLenum mode, GLenum type, const void* indirect); + void DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, + GLuint baseinstance); + void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); + void DrawArraysIndirect(GLenum mode, const void* indirect); void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width,