[Feat] implement renaming for buffer

This commit is contained in:
2025-05-07 15:38:30 +08:00
parent bb45906189
commit 6c1d1e0e7a
6 changed files with 412 additions and 355 deletions
@@ -39,7 +39,14 @@ namespace MG_GL::GL {
void BindBuffer(GLenum target, GLuint buffer) { void BindBuffer(GLenum target, GLuint buffer) {
MG_Util::Debug::LogD("glBindBuffer, target: %d, buffer: %d", target, 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_State::SetError(GL_INVALID_VALUE);
MG_Util::Debug::LogE("Invalid buffer handle: %u", buffer); MG_Util::Debug::LogE("Invalid buffer handle: %u", buffer);
return; return;
@@ -80,9 +87,9 @@ namespace MG_GL::GL {
return; return;
} }
GLenum result = MG_State::CreateBuffers(n, buffers); GLenum result = MG_State::GenBufferNames(n, buffers);
if (result == GL_NO_ERROR) { 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) { for (GLsizei i = 0; i < n; ++i) {
MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]); MG_Util::Debug::LogD(" Buffer[%d] = %u", i, buffers[i]);
} }
@@ -100,7 +107,7 @@ namespace MG_GL::GL {
return GL_FALSE; 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? // Should we report gl error here or in MG_State?
MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid"); MG_Util::Debug::LogD("Buffer %u is %s", buffer, isValid ? "valid" : "invalid");
return isValid ? GL_TRUE : GL_FALSE; return isValid ? GL_TRUE : GL_FALSE;
+296 -288
View File
@@ -180,43 +180,138 @@ namespace MG_GL::GL {
} }
static std::unordered_map<GLuint, void*> s_bufferDirtyFlags_bufferObj; // static std::unordered_map<GLuint, void*> s_bufferDirtyFlags_bufferObj;
void SyncAllBuffersToGLES(BufferState* bufferState) { void SyncAllBuffersToGLES(BufferState* bufferState) {
GLint currentVBO = 0, currentEBO = 0; GLint prev_vbo = 0;
CallAndCheck(::GLES::glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &currentVBO);) CallAndCheck(::GLES::glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prev_vbo);)
CallAndCheck(::GLES::glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &currentEBO);)
for (auto& [mgBufferId, bufferObj] : bufferState->buffers_) {
if (!bufferObj.generated) continue;
// TODO: Check if the buffer changes rather than always update it. for (auto& [mgname, obj] : bufferState->buffers_) {
if (s_bufferMap.find(mgBufferId) == s_bufferMap.end() || true) { if (!obj.generated)
if (s_bufferMap.find(mgBufferId) == s_bufferMap.end()) { continue;
GLuint glBuffer;
CallAndCheck(::GLES::glGenBuffers(1, &glBuffer);) // Gen real buffers at ES
s_bufferMap[mgBufferId] = glBuffer; if (s_bufferMap.find(mgname) == s_bufferMap.end()) {
GLuint glname;
CallAndCheck(::GLES::glGenBuffers(1, &glname);)
s_bufferMap[mgname] = glname;
} }
CallAndCheck(::GLES::glBindBuffer(bufferObj.target, s_bufferMap[mgBufferId]);)
GLuint glname = s_bufferMap[mgname];
// Populate data to ES
CallAndCheck(::GLES::glBindBuffer(GL_ARRAY_BUFFER, glname);)
CallAndCheck(::GLES::glBufferData( CallAndCheck(::GLES::glBufferData(
bufferObj.target, GL_ARRAY_BUFFER,
bufferObj.data.size(), obj.data.size(),
bufferObj.data.data(), obj.data.data(),
bufferObj.usage obj.usage);)
);)
s_bufferDirtyFlags_bufferObj[mgBufferId] = bufferObj.data.data(); // s_bufferDirtyFlags_bufferObj[mgname] = obj.data.data();
} }
} CallAndCheck(::GLES::glBindBuffer(GL_ARRAY_BUFFER, prev_vbo);)
CallAndCheck(::GLES::glBindBuffer(GL_ARRAY_BUFFER, currentVBO);)
CallAndCheck(::GLES::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, currentEBO);)
} }
void DrawArraysSHITTILY(GLenum mode, GLint first, GLsizei count) {
}
static GLuint lastBoundVAO = 0; static GLuint lastBoundVAO = 0;
static GLuint lastBoundProgram = 0; static GLuint lastBoundProgram = 0;
static GLuint lastBoundFBO[2] = {0}; static GLuint lastBoundFBO[2] = {0};
static std::array<GLuint, 32> lastBoundTextures; static std::array<GLuint, 32> 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) { void DrawElementsSHITTILY(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
CommonState* commonState = MG_State_T::commonState; CommonState* commonState = MG_State_T::commonState;
TextureState* textureState = MG_State_T::textureState; TextureState* textureState = MG_State_T::textureState;
@@ -578,95 +673,97 @@ namespace MG_GL::GL {
} }
// Framebuffer // Framebuffer
GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER]; RealizeFBOState(GL_DRAW_FRAMEBUFFER);
if (currentFBO != lastBoundFBO[0]) { // GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER];
GLuint glFBO = 0; // 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) { 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, void BlitFramebuffer(GLint srcX0,
GLint srcY0, GLint srcY0,
GLint srcX1, GLint srcX1,
@@ -801,92 +808,93 @@ namespace MG_GL::GL {
CommonState* commonState = MG_State_T::commonState; CommonState* commonState = MG_State_T::commonState;
FramebufferState* fbState = MG_State_T::framebufferState; FramebufferState* fbState = MG_State_T::framebufferState;
GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER]; // GLuint currentFBO = fbState->currentBindings_[GL_DRAW_FRAMEBUFFER];
if (currentFBO != lastBoundFBO[0]) { // if (currentFBO != lastBoundFBO[0]) {
GLuint glFBO = 0; // GLuint glFBO = 0;
//
if (currentFBO == 0) { // if (currentFBO == 0) {
CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, 0);) // CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, 0);)
glFBO = 0; // glFBO = 0;
} else { // } else {
bool isNewGlesFBO = false; // bool isNewGlesFBO = false;
//
if (s_framebufferMap.find(currentFBO) == s_framebufferMap.end()) { // if (s_framebufferMap.find(currentFBO) == s_framebufferMap.end()) {
CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);) // CallAndCheck(::GLES::glGenFramebuffers(1, &glFBO);)
s_framebufferMap[currentFBO] = glFBO; // s_framebufferMap[currentFBO] = glFBO;
CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) // CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);)
MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); // MG_Util::Debug::LogD("Generated and bound new GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO);
isNewGlesFBO = true; // isNewGlesFBO = true;
} else { // } else {
glFBO = s_framebufferMap[currentFBO]; // glFBO = s_framebufferMap[currentFBO];
CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);) // CallAndCheck(::GLES::glBindFramebuffer(GL_FRAMEBUFFER, glFBO);)
MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO); // MG_Util::Debug::LogD("Bound existing GLES FBO %u for MobileGL FBO %u", glFBO, currentFBO);
} // }
//
if (glFBO != 0) { // if (glFBO != 0) {
FramebufferObject* mgFBO = fbState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER); // FramebufferObject* mgFBO = fbState->GetCurrentFBO(GL_DRAW_FRAMEBUFFER);
if (mgFBO) { // if (mgFBO) {
MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, currentFBO); // MG_Util::Debug::LogD("Checking/Syncing attachments for GLES FBO %u (MobileGL FBO %u)", glFBO, currentFBO);
//
for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) { // for (auto const& [mgAttachmentPoint, mgAtt] : mgFBO->attachments) {
//
if (mgAtt.type != GL_TEXTURE_2D) { // if (mgAtt.type != GL_TEXTURE_2D) {
MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, currentFBO); // MG_Util::Debug::LogW("Skipping non-TEXTURE_2D attachment 0x%X for FBO %u", mgAttachmentPoint, currentFBO);
continue; // continue;
} // }
//
GLuint expectedGLTexId = 0; // GLuint expectedGLTexId = 0;
if (mgAtt.handle != 0) { // if (mgAtt.handle != 0) {
if (s_textureMap.count(mgAtt.handle)) { // if (s_textureMap.count(mgAtt.handle)) {
expectedGLTexId = s_textureMap[mgAtt.handle]; // expectedGLTexId = s_textureMap[mgAtt.handle];
} else { // } 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); // 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) // for (auto const& [key, val] : s_textureMap)
MG_Util::Debug::LogW(" key: %d, val: %d", key, val); // MG_Util::Debug::LogW(" key: %d, val: %d", key, val);
continue; // continue;
} // }
} // }
//
GLint glesAttachedType = 0; // GLint glesAttachedType = 0;
GLint glesAttachedName = 0; // GLint glesAttachedName = 0;
//
CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);) // CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &glesAttachedType);)
//
if (glesAttachedType == GL_TEXTURE) { // if (glesAttachedType == GL_TEXTURE) {
CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);) // CallAndCheck(::GLES::glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, mgAttachmentPoint, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &glesAttachedName);)
} else if (glesAttachedType != GL_NONE) { // } 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); // 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) { // if ((GLuint)glesAttachedName != expectedGLTexId) {
MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...", // MG_Util::Debug::LogD("Syncing FBO %u attachment 0x%X: Expected GLES TexID %u, Found GLES ObjName %d. Attaching/Detaching...",
currentFBO, mgAttachmentPoint, expectedGLTexId, glesAttachedName); // currentFBO, mgAttachmentPoint, expectedGLTexId, glesAttachedName);
//
CallAndCheck(::GLES::glFramebufferTexture2D( // CallAndCheck(::GLES::glFramebufferTexture2D(
GL_FRAMEBUFFER, // GL_FRAMEBUFFER,
mgAttachmentPoint, // mgAttachmentPoint,
GL_TEXTURE_2D, // GL_TEXTURE_2D,
expectedGLTexId, // expectedGLTexId,
mgAtt.mipLevel // mgAtt.mipLevel
);) // );)
} // }
} // }
//
GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER); // GLenum status = ::GLES::glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) { // if (status != GL_FRAMEBUFFER_COMPLETE) {
MG_Util::Debug::LogE("Framebuffer %u (GLES FBO %u) is not complete after sync! Status: 0x%X (%s)", // 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)); // currentFBO, glFBO, status, MG_Util::Debug::GLEnumToString(status));
} // }
//
} else { // } else {
MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", currentFBO); // MG_Util::Debug::LogW("Could not get MobileGL FBO object for ID %u during attachment sync.", currentFBO);
} // }
} // }
} // }
//
lastBoundFBO[0] = currentFBO; // lastBoundFBO[0] = currentFBO;
} // }
RealizeFBOState(GL_DRAW_FRAMEBUFFER);
static GLfloat lastClearColor[4] = {-1.0f, -1.0f, -1.0f, -1.0f}; static GLfloat lastClearColor[4] = {-1.0f, -1.0f, -1.0f, -1.0f};
if (memcmp(lastClearColor, commonState->clearColor, sizeof(lastClearColor)) != 0) { if (memcmp(lastClearColor, commonState->clearColor, sizeof(lastClearColor)) != 0) {
+74 -44
View File
@@ -6,57 +6,80 @@
#include "BufferState.h" #include "BufferState.h"
GLenum BufferState::Create(GLuint* buffer) { GLenum BufferState::GenName(GLuint *buffer) {
MG_Util::Debug::LogD("MG_State: Buffer: Create called"); MG_Util::Debug::LogD("MG_State: Buffer: GenName");
if (!buffer) return GL_INVALID_VALUE; if (!buffer)
return GL_INVALID_VALUE;
GLuint id = 0; GLuint id = 0;
if (!freeIds_.empty()) { if (freeId_.empty()) {
id = *freeIds_.begin(); id = lastId_++;
freeIds_.erase(freeIds_.begin());
} else { } else {
id = ++lastId_; id = freeId_.back();
freeId_.pop_back();
} }
*buffer = id; *buffer = id;
BufferObject& obj = buffers_[id]; MG_Util::Debug::LogD("MG_State: Buffer: Gen new name %d", id);
MG_Util::Debug::LogD("MG_State: Buffer: Create created buffer %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; obj.generated = true;
return GL_NO_ERROR; return GL_NO_ERROR;
} }
GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) { //GLenum BufferState::CreateN(GLsizei n, GLuint* buffers) {
MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n); // MG_Util::Debug::LogD("MG_State: Buffer: CreateN called with n=%d", n);
if (n < 0) return GL_INVALID_VALUE; // if (n < 0) return GL_INVALID_VALUE;
//
for (GLsizei i = 0; i < n; ++i) { // for (GLsizei i = 0; i < n; ++i) {
GLenum result = Create(&buffers[i]); // GLenum result = Create(&buffers[i]);
if (result != GL_NO_ERROR) { // if (result != GL_NO_ERROR) {
MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result); // MG_Util::Debug::LogE("MG_State: Buffer: CreateN create buffer failed with error 0x%x", result);
return result; // return result;
} // }
} // }
MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully"); // MG_Util::Debug::LogD("MG_State: Buffer: CreateN created buffers successfully");
return GL_NO_ERROR; // return GL_NO_ERROR;
} //}
GLenum BufferState::Bind(GLenum target, GLuint buffer) { GLenum BufferState::Bind(GLenum target, GLuint buffer) {
if (!IsValidTarget_(target)) return GL_INVALID_ENUM; // We don't handle unallocated buffer names here, just plain bind
MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=0x%x, buffer=%u", target, buffer);
if (buffer != 0) { if (!IsValidTarget_(target)) return GL_INVALID_ENUM;
auto it = buffers_.find(buffer); MG_Util::Debug::LogD("MG_State: Buffer: Bind called with target=%s, buffer=%u", MG_Util::Debug::GLEnumToString(target), buffer);
if (it == buffers_.end()) {
buffers_[buffer]; if (buffer != 0 && !ValidateAllocatedHandle(buffer)) {
} else { MG_Util::Debug::LogE("MG_State: Buffer: Binding invalid buffer %d to %s", buffer, MG_Util::Debug::GLEnumToString(target));
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; return GL_INVALID_OPERATION;
} }
}
buffers_[buffer].target = target;
}
currentBindings_[target] = buffer; currentBindings_[target] = buffer;
MG_Util::Debug::LogD("MG_State: Buffer: Bind succeed bind buffer %u to target 0x%x", buffer, target); MG_Util::Debug::LogD("MG_State: Buffer: Bind succeed bind buffer %u to target 0x%x", buffer, target);
@@ -119,19 +142,26 @@ GLenum BufferState::ReleaseBufferMemory(GLenum target) {
return GL_NO_ERROR; return GL_NO_ERROR;
} }
bool BufferState::ValidateHandle(GLuint buffer) { bool BufferState::ValidateAllocatedHandle(GLuint buffer) {
bool isvalid = buffers_.count(buffer) > 0; bool isValid = buffers_.find(buffer) != buffers_.end();
MG_Util::Debug::LogD("MG_State: Buffer: ValidateHandle called on buffer %u returns %d", buffer, isvalid); MG_Util::Debug::LogD("MG_State: Buffer: ValidateAllocatedHandle called on buffer %u returns %d", buffer, isValid);
return 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) { void BufferState::Delete(GLuint buffer) {
if (buffers_.erase(buffer)) { buffers_.erase(buffer);
freeIds_.insert(buffer); if (ValidateGeneratedName(buffer))
freeId_.emplace_back(buffer);
for (auto& [target, id] : currentBindings_) { for (auto& [target, id] : currentBindings_) {
if (id == buffer) id = 0; if (id == buffer) id = 0;
} }
}
MG_Util::Debug::LogD("MG_State: Buffer: Delete buffer %u", buffer); 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: case GL_BUFFER_USAGE:
*params = static_cast<GLint>(buffer.usage); *params = static_cast<GLint>(buffer.usage);
break; 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: default:
return GL_INVALID_ENUM; return GL_INVALID_ENUM;
} }
+8 -6
View File
@@ -11,7 +11,6 @@
class BufferState { class BufferState {
public: public:
struct BufferObject { struct BufferObject {
GLenum target = 0;
GLenum usage = GL_STATIC_DRAW; GLenum usage = GL_STATIC_DRAW;
std::vector<GLubyte> data; std::vector<GLubyte> data;
bool isMapped = false; bool isMapped = false;
@@ -20,23 +19,26 @@ public:
}; };
// Return: the validity of the operation, according to OpenGL 3 standard // Return: the validity of the operation, according to OpenGL 3 standard
GLenum Create(GLuint* buffer); GLenum GenName(GLuint* buffer);
GLenum CreateN(GLsizei n, GLuint* buffers); GLenum GenNameN(GLsizei n, GLuint* buffers);
GLenum Create(GLuint buffer);
// GLenum CreateN(GLsizei n, GLuint* buffers);
GLenum Bind(GLenum target, GLuint buffer); GLenum Bind(GLenum target, GLuint buffer);
GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage); GLenum CommitStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer); GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPointer);
GLenum ReleaseBufferMemory(GLenum target); GLenum ReleaseBufferMemory(GLenum target);
GLenum QueryPropertyIntVector(GLenum target, GLenum pname, GLint* params) const; 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); void Delete(GLuint buffer);
GLuint GetCurrentBinding(GLenum target) const; GLuint GetCurrentBinding(GLenum target) const;
std::unordered_map<GLenum, GLuint> currentBindings_; std::unordered_map<GLenum, GLuint> currentBindings_;
std::unordered_map<GLuint, BufferObject> buffers_; std::unordered_map<GLuint, BufferObject> buffers_;
private: private:
std::set<GLuint> freeIds_; std::vector<GLuint> freeId_;
GLuint lastId_ = 0; GLuint lastId_ = 1;
static bool IsValidTarget_(GLenum target); static bool IsValidTarget_(GLenum target);
}; };
+13 -5
View File
@@ -160,12 +160,16 @@ namespace MG_State {
return MG_State_T::bufferState->ReleaseBufferMemory(target); return MG_State_T::bufferState->ReleaseBufferMemory(target);
} }
GLenum CreateBuffer(GLuint* buffer) { GLenum CreateBuffer(GLuint buffer) {
return MG_State_T::bufferState->Create(buffer); return MG_State_T::bufferState->Create(buffer);
} }
GLenum CreateBuffers(GLsizei n, GLuint* buffers) { // GLenum CreateBuffers(GLsizei n, GLuint* buffers) {
return MG_State_T::bufferState->CreateN(n, 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) { GLenum BindBuffer(GLenum target, GLuint buffer) {
@@ -181,8 +185,12 @@ namespace MG_State {
return MG_State_T::bufferState->CommitStorage(target, size, data, usage); return MG_State_T::bufferState->CommitStorage(target, size, data, usage);
} }
bool ValidateBufferHandle(GLuint buffer) { bool ValidateAllocatedBufferHandle(GLuint buffer) {
return MG_State_T::bufferState->ValidateHandle(buffer); return MG_State_T::bufferState->ValidateAllocatedHandle(buffer);
}
bool ValidateGeneratedName(GLuint buffer) {
return MG_State_T::bufferState->ValidateGeneratedName(buffer);
} }
void DeleteBuffer(GLuint buffer) { void DeleteBuffer(GLuint buffer) {
+5 -3
View File
@@ -58,11 +58,13 @@ namespace MG_State {
// Buffer // Buffer
GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr); GLenum AcquireBufferMemory(GLenum target, GLenum access, void** mappedPtr);
GLenum ReleaseBufferMemory(GLenum target); GLenum ReleaseBufferMemory(GLenum target);
GLenum CreateBuffer(GLuint* buffer); GLenum CreateBuffer(GLuint buffer);
GLenum CreateBuffers(GLsizei n, GLuint* buffers); // GLenum CreateBuffers(GLsizei n, GLuint* buffers);
GLenum GenBufferNames(GLsizei n, GLuint* buffers);
GLenum BindBuffer(GLenum target, GLuint buffer); GLenum BindBuffer(GLenum target, GLuint buffer);
GLenum CommitBufferStorage(GLenum target, GLsizeiptr size, const void* data, GLenum usage); 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); void DeleteBuffer(GLuint buffer);
GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params); GLenum QueryBufferPropertyIntVector(GLenum target, GLenum pname, GLint* params);