From 6c1d1e0e7a86e56a030d3f6ab290c40935e724b6 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 7 May 2025 15:38:30 +0800 Subject: [PATCH] [Feat] implement renaming for buffer --- .../Implementations/GL/Buffer/GL_Buffer.cpp | 15 +- .../Implementations/GL/Drawing/GL_Drawing.cpp | 588 +++++++++--------- MG/MG_GL/State/Buffer/BufferState.cpp | 124 ++-- MG/MG_GL/State/Buffer/BufferState.h | 14 +- MG/MG_GL/State/Core/GLState.cpp | 18 +- MG/MG_GL/State/Core/GLState.h | 8 +- 6 files changed, 412 insertions(+), 355 deletions(-) diff --git a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp index f6d567d9..70c43f1b 100644 --- a/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp +++ b/MG/MG_GL/Implementations/GL/Buffer/GL_Buffer.cpp @@ -39,7 +39,14 @@ namespace MG_GL::GL { void BindBuffer(GLenum target, GLuint buffer) { MG_Util::Debug::LogD("glBindBuffer, target: %d, buffer: %d", target, buffer); - if (buffer != 0 && !MG_State::ValidateBufferHandle(buffer)) { + if (buffer != 0 && + MG_State::ValidateGeneratedName(buffer) && + !MG_State::ValidateAllocatedBufferHandle(buffer)) { + MG_Util::Debug::LogE("Actually creating buffer: %u", buffer); + GLenum result = MG_State::CreateBuffer(buffer); + } + + if (buffer != 0 && !MG_State::ValidateAllocatedBufferHandle(buffer)) { MG_State::SetError(GL_INVALID_VALUE); MG_Util::Debug::LogE("Invalid buffer handle: %u", buffer); return; @@ -80,9 +87,9 @@ namespace MG_GL::GL { return; } - GLenum result = MG_State::CreateBuffers(n, buffers); + GLenum result = MG_State::GenBufferNames(n, buffers); if (result == GL_NO_ERROR) { - MG_Util::Debug::LogD("Generated buffers:"); + MG_Util::Debug::LogD("Generated buffer names:"); for (GLsizei i = 0; i < n; ++i) { MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]); } @@ -100,7 +107,7 @@ namespace MG_GL::GL { return GL_FALSE; } - bool isValid = MG_State::ValidateBufferHandle(buffer); + bool isValid = MG_State::ValidateAllocatedBufferHandle(buffer); // Should we report gl error here or in MG_State? MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid"); return isValid ? GL_TRUE : GL_FALSE; diff --git a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp index f4152177..240a2630 100644 --- a/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp +++ b/MG/MG_GL/Implementations/GL/Drawing/GL_Drawing.cpp @@ -180,43 +180,138 @@ namespace MG_GL::GL { } - static std::unordered_map s_bufferDirtyFlags_bufferObj; +// static std::unordered_map s_bufferDirtyFlags_bufferObj; void SyncAllBuffersToGLES(BufferState* bufferState) { - GLint currentVBO = 0, currentEBO = 0; - CallAndCheck(::GLES::glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤tVBO);) - CallAndCheck(::GLES::glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤tEBO);) - for (auto& [mgBufferId, bufferObj] : bufferState->buffers_) { - if (!bufferObj.generated) continue; - - // TODO: Check if the buffer changes rather than always update it. - if (s_bufferMap.find(mgBufferId) == s_bufferMap.end() || true) { - if (s_bufferMap.find(mgBufferId) == s_bufferMap.end()) { - GLuint glBuffer; - CallAndCheck(::GLES::glGenBuffers(1, &glBuffer);) - s_bufferMap[mgBufferId] = glBuffer; - } - CallAndCheck(::GLES::glBindBuffer(bufferObj.target, s_bufferMap[mgBufferId]);) - CallAndCheck(::GLES::glBufferData( - bufferObj.target, - bufferObj.data.size(), - bufferObj.data.data(), - bufferObj.usage - );) - s_bufferDirtyFlags_bufferObj[mgBufferId] = bufferObj.data.data(); + GLint prev_vbo = 0; + CallAndCheck(::GLES::glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev_vbo);) + + for (auto& [mgname, obj] : bufferState->buffers_) { + if (!obj.generated) + continue; + + // Gen real buffers at ES + if (s_bufferMap.find(mgname) == s_bufferMap.end()) { + GLuint glname; + CallAndCheck(::GLES::glGenBuffers(1, &glname);) + s_bufferMap[mgname] = glname; } + + GLuint glname = s_bufferMap[mgname]; + + // Populate data to ES + CallAndCheck(::GLES::glBindBuffer(GL_ARRAY_BUFFER, glname);) + CallAndCheck(::GLES::glBufferData( + GL_ARRAY_BUFFER, + obj.data.size(), + obj.data.data(), + obj.usage);) + +// s_bufferDirtyFlags_bufferObj[mgname] = obj.data.data(); } - CallAndCheck(::GLES::glBindBuffer(GL_ARRAY_BUFFER, currentVBO);) - CallAndCheck(::GLES::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, currentEBO);) + CallAndCheck(::GLES::glBindBuffer(GL_ARRAY_BUFFER, prev_vbo);) } - void DrawArraysSHITTILY(GLenum mode, GLint first, GLsizei count) { - - } static GLuint lastBoundVAO = 0; static GLuint lastBoundProgram = 0; static GLuint lastBoundFBO[2] = {0}; static std::array lastBoundTextures; + + void RealizeFBOState(GLenum fbtype) { + FramebufferState* fbState = MG_State_T::framebufferState; + + GLuint fb = fbState->currentBindings_[fbtype]; + if (fb != lastBoundFBO[(fbtype == GL_DRAW_FRAMEBUFFER) ? 0 : 1]) { + GLuint glFBO = 0; + + if (fb == 0) { + CallAndCheck(::GLES::glBindFramebuffer(fbtype, 0);) + glFBO = 0; + } else { + bool isNewGlesFBO = false; + + if (s_framebufferMap.find(fb) == s_framebufferMap.end()) { + CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) + s_framebufferMap[fb] = glFBO; + CallAndCheck(::GLES::glBindFramebuffer(fbtype, glFBO);) + MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, fb); + isNewGlesFBO = true; + } else { + glFBO = s_framebufferMap[fb]; + CallAndCheck(::GLES::glBindFramebuffer(fbtype, glFBO);) + MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, fb); + } + + if (glFBO != 0) { + FramebufferObject* mgFBO = fbState->GetCurrentFBO(fbtype); + if (mgFBO) { + MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, fb); + + for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { + + if (mgAtt.type != GL_TEXTURE_2D) { + MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, fb); + continue; + } + + GLuint expectedGLTexId = 0; + if (mgAtt.handle != 0) { + if (s_textureMap.count(mgAtt.handle)) { + expectedGLTexId = s_textureMap[mgAtt.handle]; + } else { + MG_Util::Debug::LogE("MobileGL Texture %u for FBO %u attachment 0x%X not found in s_textureMap during FBO sync!", mgAtt.handle, fb, mgAttachmentPoint); + for (auto const& [key, val] : s_textureMap) + MG_Util::Debug::LogW(" key: %d, val: %d", key, val); + continue; + } + } + + GLint glesAttachedType = 0; + GLint glesAttachedName = 0; + + CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(fbtype, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) + + if (glesAttachedType == GL_TEXTURE) { + CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(fbtype, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) + } else if (glesAttachedType != GL_NONE) { + MG_Util::Debug::LogW("GLES FBO %u attachment 0x%X has non-texture type 0x%X (expected GL_TEXTURE or GL_NONE)", glFBO, mgAttachmentPoint, glesAttachedType); + } + + if ((GLuint)glesAttachedName != expectedGLTexId) { + MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", + fb, mgAttachmentPoint, expectedGLTexId, glesAttachedName); + + CallAndCheck(::GLES::glFramebufferTexture2D( + fbtype, + mgAttachmentPoint, + GL_TEXTURE_2D, + expectedGLTexId, + mgAtt.mipLevel + );) + } + } + + GLenum status = ::GLES::glCheckFramebufferStatus(fbtype); + if (status != GL_FRAMEBUFFER_COMPLETE) { + MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", + fb, glFBO, status, MG_Util::Debug::GLEnumToString(status)); + } + + } else { + MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", fb); + } + } + } + + lastBoundFBO[(fbtype == GL_DRAW_FRAMEBUFFER) ? 0 : 1] = fb; + } + } + + + void DrawArraysSHITTILY(GLenum mode, GLint first, GLsizei count) { + + } + void DrawElementsSHITTILY(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { CommonState* commonState = MG_State_T::commonState; TextureState* textureState = MG_State_T::textureState; @@ -578,95 +673,97 @@ namespace MG_GL::GL { } // Framebuffer - GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER]; - if (currentFBO != lastBoundFBO[0]) { - GLuint glFBO = 0; + RealizeFBOState(GL_DRAW_FRAMEBUFFER); +// GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER]; +// if (currentFBO != lastBoundFBO[0]) { +// GLuint glFBO = 0; +// +// if (currentFBO == 0) { +// CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, 0);) +// glFBO = 0; +// } else { +// bool isNewGlesFBO = false; +// +// if (s_framebufferMap.find(currentFBO) == s_framebufferMap.end()) { +// CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) +// s_framebufferMap[currentFBO] = glFBO; +// CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) +// MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); +// GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); +// if (status != GL_FRAMEBUFFER_COMPLETE) { +// MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after creation! Status: 0x%X (%s)", +// currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status)); +// } +// isNewGlesFBO = true; +// } else { +// glFBO = s_framebufferMap[currentFBO]; +// CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) +// MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); +// } +// +// if (glFBO != 0) { +// FramebufferObject* mgFBO = fbState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER); +// if (mgFBO) { +// MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, currentFBO); +// +// for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { +// +// if (mgAtt.type != GL_TEXTURE_2D) { +// MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, currentFBO); +// continue; +// } +// +// GLuint expectedGLTexId = 0; +// if (mgAtt.handle != 0) { +// if (s_textureMap.count(mgAtt.handle)) { +// expectedGLTexId = s_textureMap[mgAtt.handle]; +// } else { +// MG_Util::Debug::LogE("MobileGL Texture %u for FBO %u attachment 0x%X not found in s_textureMap during FBO sync!", mgAtt.handle, currentFBO, mgAttachmentPoint); +// for (auto const& [key, val] : s_textureMap) +// MG_Util::Debug::LogW(" key: %d, val: %d", key, val); +// continue; +// } +// } +// +// GLint glesAttachedType = 0; +// GLint glesAttachedName = 0; +// +// CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) +// +// if (glesAttachedType == GL_TEXTURE) { +// CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) +// } else if (glesAttachedType != GL_NONE) { +// MG_Util::Debug::LogW("GLES FBO %u attachment 0x%X has non-texture type 0x%X (expected GL_TEXTURE or GL_NONE)", glFBO, mgAttachmentPoint, glesAttachedType); +// } +// +// if ((GLuint)glesAttachedName != expectedGLTexId) { +// MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", +// currentFBO, mgAttachmentPoint, expectedGLTexId, glesAttachedName); +// +// CallAndCheck(::GLES::glFramebufferTexture2D( +// GL_FRAMEBUFFER, +// mgAttachmentPoint, +// GL_TEXTURE_2D, +// expectedGLTexId, +// mgAtt.mipLevel +// );) +// } +// } +// GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); +// if (status != GL_FRAMEBUFFER_COMPLETE) { +// MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", +// currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status)); +// } +// +// } else { +// MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", currentFBO); +// } +// } +// } +// +// lastBoundFBO[0] = currentFBO; +// } - if (currentFBO == 0) { - CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, 0);) - glFBO = 0; - } else { - bool isNewGlesFBO = false; - - if (s_framebufferMap.find(currentFBO) == s_framebufferMap.end()) { - CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) - s_framebufferMap[currentFBO] = glFBO; - CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) - MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); - GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after creation! Status: 0x%X (%s)", - currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status)); - } - isNewGlesFBO = true; - } else { - glFBO = s_framebufferMap[currentFBO]; - CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) - MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); - } - - if (glFBO != 0) { - FramebufferObject* mgFBO = fbState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER); - if (mgFBO) { - MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, currentFBO); - - for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { - - if (mgAtt.type != GL_TEXTURE_2D) { - MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, currentFBO); - continue; - } - - GLuint expectedGLTexId = 0; - if (mgAtt.handle != 0) { - if (s_textureMap.count(mgAtt.handle)) { - expectedGLTexId = s_textureMap[mgAtt.handle]; - } else { - MG_Util::Debug::LogE("MobileGL Texture %u for FBO %u attachment 0x%X not found in s_textureMap during FBO sync!", mgAtt.handle, currentFBO, mgAttachmentPoint); - for (auto const& [key, val] : s_textureMap) - MG_Util::Debug::LogW(" key: %d, val: %d", key, val); - continue; - } - } - - GLint glesAttachedType = 0; - GLint glesAttachedName = 0; - - CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) - - if (glesAttachedType == GL_TEXTURE) { - CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) - } else if (glesAttachedType != GL_NONE) { - MG_Util::Debug::LogW("GLES FBO %u attachment 0x%X has non-texture type 0x%X (expected GL_TEXTURE or GL_NONE)", glFBO, mgAttachmentPoint, glesAttachedType); - } - - if ((GLuint)glesAttachedName != expectedGLTexId) { - MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", - currentFBO, mgAttachmentPoint, expectedGLTexId, glesAttachedName); - - CallAndCheck(::GLES::glFramebufferTexture2D( - GL_FRAMEBUFFER, - mgAttachmentPoint, - GL_TEXTURE_2D, - expectedGLTexId, - mgAtt.mipLevel - );) - } - } - GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", - currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status)); - } - - } else { - MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", currentFBO); - } - } - } - - lastBoundFBO[0] = currentFBO; - } if (vao->elementBuffer != 0 || indices != nullptr) { @@ -679,96 +776,6 @@ namespace MG_GL::GL { } } - void RealizeFBOState(GLenum fbtype) { - FramebufferState* fbState = MG_State_T::framebufferState; - - GLuint fb = fbState->currentBindings_[fbtype]; - if (fb != lastBoundFBO[(fbtype == GL_DRAW_FRAMEBUFFER) ? 0 : 1]) { - GLuint glFBO = 0; - - if (fb == 0) { - CallAndCheck(::GLES::glBindFramebuffer(fbtype, 0);) - glFBO = 0; - } else { - bool isNewGlesFBO = false; - - if (s_framebufferMap.find(fb) == s_framebufferMap.end()) { - CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) - s_framebufferMap[fb] = glFBO; - CallAndCheck(::GLES::glBindFramebuffer(fbtype, glFBO);) - MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, fb); - isNewGlesFBO = true; - } else { - glFBO = s_framebufferMap[fb]; - CallAndCheck(::GLES::glBindFramebuffer(fbtype, glFBO);) - MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, fb); - } - - if (glFBO != 0) { - FramebufferObject* mgFBO = fbState->GetCurrentFBO(fbtype); - if (mgFBO) { - MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, fb); - - for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { - - if (mgAtt.type != GL_TEXTURE_2D) { - MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, fb); - continue; - } - - GLuint expectedGLTexId = 0; - if (mgAtt.handle != 0) { - if (s_textureMap.count(mgAtt.handle)) { - expectedGLTexId = s_textureMap[mgAtt.handle]; - } else { - MG_Util::Debug::LogE("MobileGL Texture %u for FBO %u attachment 0x%X not found in s_textureMap during FBO sync!", mgAtt.handle, fb, mgAttachmentPoint); - for (auto const& [key, val] : s_textureMap) - MG_Util::Debug::LogW(" key: %d, val: %d", key, val); - continue; - } - } - - GLint glesAttachedType = 0; - GLint glesAttachedName = 0; - - CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(fbtype, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) - - if (glesAttachedType == GL_TEXTURE) { - CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(fbtype, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) - } else if (glesAttachedType != GL_NONE) { - MG_Util::Debug::LogW("GLES FBO %u attachment 0x%X has non-texture type 0x%X (expected GL_TEXTURE or GL_NONE)", glFBO, mgAttachmentPoint, glesAttachedType); - } - - if ((GLuint)glesAttachedName != expectedGLTexId) { - MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", - fb, mgAttachmentPoint, expectedGLTexId, glesAttachedName); - - CallAndCheck(::GLES::glFramebufferTexture2D( - fbtype, - mgAttachmentPoint, - GL_TEXTURE_2D, - expectedGLTexId, - mgAtt.mipLevel - );) - } - } - - GLenum status = ::GLES::glCheckFramebufferStatus(fbtype); - if (status != GL_FRAMEBUFFER_COMPLETE) { - MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", - fb, glFBO, status, MG_Util::Debug::GLEnumToString(status)); - } - - } else { - MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", fb); - } - } - } - - lastBoundFBO[(fbtype == GL_DRAW_FRAMEBUFFER) ? 0 : 1] = fb; - } - } - void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, @@ -801,92 +808,93 @@ namespace MG_GL::GL { CommonState* commonState = MG_State_T::commonState; FramebufferState* fbState = MG_State_T::framebufferState; - GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER]; - if (currentFBO != lastBoundFBO[0]) { - GLuint glFBO = 0; - - if (currentFBO == 0) { - CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, 0);) - glFBO = 0; - } else { - bool isNewGlesFBO = false; - - if (s_framebufferMap.find(currentFBO) == s_framebufferMap.end()) { - CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) - s_framebufferMap[currentFBO] = glFBO; - CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) - MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); - isNewGlesFBO = true; - } else { - glFBO = s_framebufferMap[currentFBO]; - CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) - MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); - } - - if (glFBO != 0) { - FramebufferObject* mgFBO = fbState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER); - if (mgFBO) { - MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, currentFBO); - - for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { - - if (mgAtt.type != GL_TEXTURE_2D) { - MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, currentFBO); - continue; - } - - GLuint expectedGLTexId = 0; - if (mgAtt.handle != 0) { - if (s_textureMap.count(mgAtt.handle)) { - expectedGLTexId = s_textureMap[mgAtt.handle]; - } else { - MG_Util::Debug::LogE("MobileGL Texture %u for FBO %u attachment 0x%X not found in s_textureMap during FBO sync!", mgAtt.handle, currentFBO, mgAttachmentPoint); - for (auto const& [key, val] : s_textureMap) - MG_Util::Debug::LogW(" key: %d, val: %d", key, val); - continue; - } - } - - GLint glesAttachedType = 0; - GLint glesAttachedName = 0; - - CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) - - if (glesAttachedType == GL_TEXTURE) { - CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) - } else if (glesAttachedType != GL_NONE) { - MG_Util::Debug::LogW("GLES FBO %u attachment 0x%X has non-texture type 0x%X (expected GL_TEXTURE or GL_NONE)", glFBO, mgAttachmentPoint, glesAttachedType); - } - - if ((GLuint)glesAttachedName != expectedGLTexId) { - MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", - currentFBO, mgAttachmentPoint, expectedGLTexId, glesAttachedName); - - CallAndCheck(::GLES::glFramebufferTexture2D( - GL_FRAMEBUFFER, - mgAttachmentPoint, - GL_TEXTURE_2D, - expectedGLTexId, - mgAtt.mipLevel - );) - } - } - - GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", - currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status)); - } - - } else { - MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", currentFBO); - } - } - } - - lastBoundFBO[0] = currentFBO; - } +// GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER]; +// if (currentFBO != lastBoundFBO[0]) { +// GLuint glFBO = 0; +// +// if (currentFBO == 0) { +// CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, 0);) +// glFBO = 0; +// } else { +// bool isNewGlesFBO = false; +// +// if (s_framebufferMap.find(currentFBO) == s_framebufferMap.end()) { +// CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) +// s_framebufferMap[currentFBO] = glFBO; +// CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) +// MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); +// isNewGlesFBO = true; +// } else { +// glFBO = s_framebufferMap[currentFBO]; +// CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) +// MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); +// } +// +// if (glFBO != 0) { +// FramebufferObject* mgFBO = fbState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER); +// if (mgFBO) { +// MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, currentFBO); +// +// for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { +// +// if (mgAtt.type != GL_TEXTURE_2D) { +// MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, currentFBO); +// continue; +// } +// +// GLuint expectedGLTexId = 0; +// if (mgAtt.handle != 0) { +// if (s_textureMap.count(mgAtt.handle)) { +// expectedGLTexId = s_textureMap[mgAtt.handle]; +// } else { +// MG_Util::Debug::LogE("MobileGL Texture %u for FBO %u attachment 0x%X not found in s_textureMap during FBO sync!", mgAtt.handle, currentFBO, mgAttachmentPoint); +// for (auto const& [key, val] : s_textureMap) +// MG_Util::Debug::LogW(" key: %d, val: %d", key, val); +// continue; +// } +// } +// +// GLint glesAttachedType = 0; +// GLint glesAttachedName = 0; +// +// CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) +// +// if (glesAttachedType == GL_TEXTURE) { +// CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) +// } else if (glesAttachedType != GL_NONE) { +// MG_Util::Debug::LogW("GLES FBO %u attachment 0x%X has non-texture type 0x%X (expected GL_TEXTURE or GL_NONE)", glFBO, mgAttachmentPoint, glesAttachedType); +// } +// +// if ((GLuint)glesAttachedName != expectedGLTexId) { +// MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", +// currentFBO, mgAttachmentPoint, expectedGLTexId, glesAttachedName); +// +// CallAndCheck(::GLES::glFramebufferTexture2D( +// GL_FRAMEBUFFER, +// mgAttachmentPoint, +// GL_TEXTURE_2D, +// expectedGLTexId, +// mgAtt.mipLevel +// );) +// } +// } +// +// GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); +// if (status != GL_FRAMEBUFFER_COMPLETE) { +// MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", +// currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status)); +// } +// +// } else { +// MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", currentFBO); +// } +// } +// } +// +// lastBoundFBO[0] = currentFBO; +// } + RealizeFBOState(GL_DRAW_FRAMEBUFFER); static GLfloat lastClearColor[4] = {-1.0f, -1.0f, -1.0f, -1.0f}; if (memcmp(lastClearColor, commonState->clearColor, sizeof(lastClearColor)) != 0) { diff --git a/MG/MG_GL/State/Buffer/BufferState.cpp b/MG/MG_GL/State/Buffer/BufferState.cpp index 4dde0d53..6b3a997b 100644 --- a/MG/MG_GL/State/Buffer/BufferState.cpp +++ b/MG/MG_GL/State/Buffer/BufferState.cpp @@ -6,56 +6,79 @@ #include "BufferState.h" -GLenum BufferState::Create(GLuint* buffer) { - MG_Util::Debug::LogD("MG_State: Buffer: Create called"); - if (!buffer) return GL_INVALID_VALUE; +GLenum BufferState::GenName(GLuint *buffer) { + MG_Util::Debug::LogD("MG_State: Buffer: GenName"); + if (!buffer) + return GL_INVALID_VALUE; GLuint id = 0; - if (!freeIds_.empty()) { - id = *freeIds_.begin(); - freeIds_.erase(freeIds_.begin()); + if (freeId_.empty()) { + id = lastId_++; } else { - id = ++lastId_; + id = freeId_.back(); + freeId_.pop_back(); } + *buffer = id; - BufferObject& obj = buffers_[id]; - MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", id); + MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id); + + return GL_NO_ERROR; +} + +GLenum BufferState::GenNameN(GLsizei n, GLuint* buffers) { + MG_Util::Debug::LogD("MG_State: Buffer: GenNameN called with n=%d", n); + if (n < 0) return GL_INVALID_VALUE; + + for (GLsizei i = 0; i < n; ++i) { + GLenum result = GenName(&buffers[i]); + if (result != GL_NO_ERROR) { + MG_Util::Debug::LogE("MG_State: Buffer: GenNameN failed with error 0x%x", result); + return result; + } + } + MG_Util::Debug::LogD("MG_State: Buffer: GenNameN created buffers successfully"); + return GL_NO_ERROR; +} + +GLenum BufferState::Create(GLuint buffer) { + MG_Util::Debug::LogD("MG_State: Buffer: Create called"); + if (!buffer) + return GL_INVALID_VALUE; + + if (ValidateAllocatedHandle(buffer)) + return GL_INVALID_VALUE; + + BufferObject& obj = buffers_[buffer]; + MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %d", buffer); obj.generated = true; return GL_NO_ERROR; } -GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) { - MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n); - if (n < 0) return GL_INVALID_VALUE; - - for (GLsizei i = 0; i < n; ++i) { - GLenum result = Create(&buffers[i]); - if (result != GL_NO_ERROR) { - MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result); - return result; - } - } - MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully"); - return GL_NO_ERROR; -} +//GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) { +// MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n); +// if (n < 0) return GL_INVALID_VALUE; +// +// for (GLsizei i = 0; i < n; ++i) { +// GLenum result = Create(&buffers[i]); +// if (result != GL_NO_ERROR) { +// MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result); +// return result; +// } +// } +// MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully"); +// return GL_NO_ERROR; +//} GLenum BufferState::Bind(GLenum target, GLuint buffer) { - if (!IsValidTarget_(target)) return GL_INVALID_ENUM; - MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=0x%x, buffer=%u", target, buffer); + // We don't handle unallocated buffer names here, just plain bind - if (buffer != 0) { - auto it = buffers_.find(buffer); - if (it == buffers_.end()) { - buffers_[buffer]; - } else { - BufferObject& obj = it->second; - if (obj.target != 0 && obj.target != target) { - MG_Util::Debug::LogE("MG_State: Buffer: Bind can not bind a buffer to different target 0x%x, current bind target is 0x%x", target, obj.target); - return GL_INVALID_OPERATION; - } - } - buffers_[buffer].target = target; + if (!IsValidTarget_(target)) return GL_INVALID_ENUM; + MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=%s, buffer=%u", MG_Util::Debug::GLEnumToString(target), buffer); + + if (buffer != 0 && !ValidateAllocatedHandle(buffer)) { + MG_Util::Debug::LogE("MG_State: Buffer: Binding invalid buffer %d to %s", buffer, MG_Util::Debug::GLEnumToString(target)); + return GL_INVALID_OPERATION; } currentBindings_[target] = buffer; @@ -119,18 +142,25 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) { return GL_NO_ERROR; } -bool BufferState::ValidateHandle(GLuint buffer) { - bool isvalid = buffers_.count(buffer) > 0; - MG_Util::Debug::LogD("MG_State: Buffer: ValidateHandle called on buffer %u returns %d", buffer, isvalid); - return isvalid; +bool BufferState::ValidateAllocatedHandle(GLuint buffer) { + bool isValid = buffers_.find(buffer) != buffers_.end(); + MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid); + return isValid; +} + +bool BufferState::ValidateGeneratedName(GLuint buffer) { + bool inFreeList = std::find(freeId_.begin(), freeId_.end(), buffer) != freeId_.end(); + bool lessThanLast = buffer < lastId_; // lastId_ is not generated yet + MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, lessThanLast && !inFreeList); + return lessThanLast && !inFreeList; } void BufferState::Delete(GLuint buffer) { - if (buffers_.erase(buffer)) { - freeIds_.insert(buffer); - for (auto& [target, id] : currentBindings_) { - if (id == buffer) id = 0; - } + buffers_.erase(buffer); + if (ValidateGeneratedName(buffer)) + freeId_.emplace_back(buffer); + for (auto& [target, id] : currentBindings_) { + if (id == buffer) id = 0; } MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer); } @@ -179,7 +209,7 @@ GLenum BufferState::QueryPropertyIntVector(GLenum target, GLenum pname, GLint* p case GL_BUFFER_USAGE: *params = static_cast(buffer.usage); break; - MG_Util::Debug::LogD("MG_State: Buffer: QueryPropertyIntVector Query info about buffer %u succeed",buffer.target); + MG_Util::Debug::LogD("MG_State: Buffer: QueryPropertyIntVector Query info about buffer %u succeed", target); default: return GL_INVALID_ENUM; } diff --git a/MG/MG_GL/State/Buffer/BufferState.h b/MG/MG_GL/State/Buffer/BufferState.h index 948953f3..4e8c54ac 100644 --- a/MG/MG_GL/State/Buffer/BufferState.h +++ b/MG/MG_GL/State/Buffer/BufferState.h @@ -11,7 +11,6 @@ class BufferState { public: struct BufferObject { - GLenum target = 0; GLenum usage = GL_STATIC_DRAW; std::vector data; bool isMapped = false; @@ -20,23 +19,26 @@ public: }; // Return: the validity of the operation, according to OpenGL 3 standard - GLenum Create(GLuint* buffer); - GLenum CreateN(GLsizei n, GLuint* buffers); + GLenum GenName(GLuint* buffer); + GLenum GenNameN(GLsizei n, GLuint* buffers); + GLenum Create(GLuint buffer); +// GLenum CreateN(GLsizei n, GLuint* buffers); GLenum Bind(GLenum target, GLuint buffer); GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage); GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer); GLenum ReleaseBufferMemory(GLenum target); GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const; - bool ValidateHandle(GLuint buffer); + bool ValidateAllocatedHandle(GLuint buffer); + bool ValidateGeneratedName(GLuint buffer); void Delete(GLuint buffer); GLuint GetCurrentBinding(GLenum target) const; std::unordered_map currentBindings_; std::unordered_map buffers_; private: - std::set freeIds_; - GLuint lastId_ = 0; + std::vector freeId_; + GLuint lastId_ = 1; static bool IsValidTarget_(GLenum target); }; diff --git a/MG/MG_GL/State/Core/GLState.cpp b/MG/MG_GL/State/Core/GLState.cpp index f7f5f290..8638d52b 100644 --- a/MG/MG_GL/State/Core/GLState.cpp +++ b/MG/MG_GL/State/Core/GLState.cpp @@ -160,12 +160,16 @@ namespace MG_State { return MG_State_T::bufferState->ReleaseBufferMemory(target); } - GLenum CreateBuffer(GLuint* buffer) { + GLenum CreateBuffer(GLuint buffer) { return MG_State_T::bufferState->Create(buffer); } - GLenum CreateBuffers(GLsizei n, GLuint* buffers) { - return MG_State_T::bufferState->CreateN(n, buffers); +// GLenum CreateBuffers(GLsizei n, GLuint* buffers) { +// return MG_State_T::bufferState->CreateN(n, buffers); +// } + + GLenum GenBufferNames(GLsizei n, GLuint* buffers) { + return MG_State_T::bufferState->GenNameN(n, buffers); } GLenum BindBuffer(GLenum target, GLuint buffer) { @@ -181,8 +185,12 @@ namespace MG_State { return MG_State_T::bufferState->CommitStorage(target, size, data, usage); } - bool ValidateBufferHandle(GLuint buffer) { - return MG_State_T::bufferState->ValidateHandle(buffer); + bool ValidateAllocatedBufferHandle(GLuint buffer) { + return MG_State_T::bufferState->ValidateAllocatedHandle(buffer); + } + + bool ValidateGeneratedName(GLuint buffer) { + return MG_State_T::bufferState->ValidateGeneratedName(buffer); } void DeleteBuffer(GLuint buffer) { diff --git a/MG/MG_GL/State/Core/GLState.h b/MG/MG_GL/State/Core/GLState.h index e86b040b..5b667071 100644 --- a/MG/MG_GL/State/Core/GLState.h +++ b/MG/MG_GL/State/Core/GLState.h @@ -58,11 +58,13 @@ namespace MG_State { // Buffer GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr); GLenum ReleaseBufferMemory(GLenum target); - GLenum CreateBuffer(GLuint* buffer); - GLenum CreateBuffers(GLsizei n, GLuint* buffers); + GLenum CreateBuffer(GLuint buffer); +// GLenum CreateBuffers(GLsizei n, GLuint* buffers); + GLenum GenBufferNames(GLsizei n, GLuint* buffers); GLenum BindBuffer(GLenum target, GLuint buffer); GLenum CommitBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage); - bool ValidateBufferHandle(GLuint buffer); + bool ValidateAllocatedBufferHandle(GLuint buffer); + bool ValidateGeneratedName(GLuint buffer); void DeleteBuffer(GLuint buffer); GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params);