From 08e808ef20a785e105dce2d0554532fd802bc503 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 9 Jul 2026 10:04:16 +0000 Subject: [PATCH] [Perf] (MG_State/FastSTL): make object deletion cheap again - GLContext::MarkBufferObjectForDeletion now detaches the deleted buffer only from the currently bound VAO (GL 4.6 5.1.2 semantics; other VAOs keep their shared_ptr attachments alive). The old every-VAO scan was O(VAOs) per delete - with one VAO per chunk section, vanilla chunk churn made it dominate the render thread and FPS decay over minutes. - Bump FastSTL: erase(key) destroys in place instead of building the discarded successor iterator (a linear bucket-array scan), and switch the buffer/framebuffer/renderbuffer deletion paths to the key overload. Together these removed the 34% render-thread deletion overhead measured in aged vanilla sessions (simpleperf, Adreno 830 / DirectVulkan). Co-Authored-By: Claude Fable 5 --- .../MG_State/GLState/BufferState/BufferState.cpp | 4 +++- MobileGL/MG_State/GLState/Core.cpp | 13 +++++++++---- .../GLState/FramebufferState/FramebufferState.cpp | 2 +- .../GLState/RenderbufferState/RenderbufferState.cpp | 2 +- include/FastSTL | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/MobileGL/MG_State/GLState/BufferState/BufferState.cpp b/MobileGL/MG_State/GLState/BufferState/BufferState.cpp index 3be5c606..1b3fec1e 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferState.cpp +++ b/MobileGL/MG_State/GLState/BufferState/BufferState.cpp @@ -64,7 +64,9 @@ namespace MobileGL::MG_State::GLState { } } } - m_bufferObjects.erase(it); + // Key-based erase skips FastSTL's successor-iterator scan, which is + // pure overhead here and dominates delete-heavy frames. + m_bufferObjects.erase(index); } m_indexGenerator.Delete(index); } diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 086e615f..30a7851e 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -80,11 +80,16 @@ namespace MobileGL::MG_State { void GLContext::MarkBufferObjectForDeletion(Uint index) { if (ValidateBufferObject(index)) { + // GL semantics: deleting a buffer detaches it only from the CURRENT + // context's bindings, including the currently bound VAO's attachment + // points; attachments in other VAOs must survive (the shared_ptr keeps + // the data object alive, matching the spec's deferred deletion). The + // previous every-VAO scan was wrong per spec and O(VAOs) per delete — + // with one VAO per chunk section, vanilla's steady buffer churn made it + // dominate the render thread and FPS decay over session time. auto bufferObject = m_bufferState.GetBufferObject(index); - auto& vaos = m_vertexArrayState.GetAllVertexArrays(); - for (auto& vao : vaos) { - if (vao == nullptr) continue; - + const auto& vao = m_vertexArrayState.GetBoundVertexArray(); + if (vao != nullptr) { if (vao->GetIndexBufferBindingSlot().GetBoundObject() == bufferObject) { vao->GetIndexBufferBindingSlot().Bind(nullptr); } diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp index 618dd157..e0177788 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp @@ -65,7 +65,7 @@ namespace MobileGL::MG_State::GLState { bindingSlot.Bind(GetFramebufferObject(0)); } } - m_framebufferObjects.erase(it); + m_framebufferObjects.erase(index); } m_indexGenerator.Delete(index); } diff --git a/MobileGL/MG_State/GLState/RenderbufferState/RenderbufferState.cpp b/MobileGL/MG_State/GLState/RenderbufferState/RenderbufferState.cpp index b2b30d9a..53de346b 100644 --- a/MobileGL/MG_State/GLState/RenderbufferState/RenderbufferState.cpp +++ b/MobileGL/MG_State/GLState/RenderbufferState/RenderbufferState.cpp @@ -57,7 +57,7 @@ namespace MobileGL::MG_State::GLState { bindingSlot.Bind(nullptr); } } - m_renderbufferObjects.erase(it); + m_renderbufferObjects.erase(index); } m_indexGenerator.Delete(index); } diff --git a/include/FastSTL b/include/FastSTL index 644b3b01..34f55f9d 160000 --- a/include/FastSTL +++ b/include/FastSTL @@ -1 +1 @@ -Subproject commit 644b3b01e6e7dcb6a67818289d2fb9bbe85232f2 +Subproject commit 34f55f9df26be2c0d618252dd9c4ff6ec1741b23