[Fix] (MG_State, P11 B2): glDeleteBuffers moves the bind-point generation of every indexed target it unbinds, and a transform-feedback object swap moves it too - the server's window no longer names a deleted buffer's handle after its slot is reused

This commit is contained in:
2026-09-29 19:32:19 -04:00
parent 4c02279f22
commit 4aec5621a8
2 changed files with 19 additions and 0 deletions
@@ -64,6 +64,18 @@ namespace MobileGL::MG_State::GLState {
if (bindingPoint.GetBoundObject() == it->second) {
bindingPoint.Bind(nullptr);
bindingPoint.ClearRange();
#if MOBILEGL_PIPE_PUSH
// An UNBIND, and the one writer of an indexed point that is not an
// entry point (GL_Buffer.cpp's BindBuffer{Base,Range}_State and
// Core.cpp's transform-feedback writers bump their own): without the
// bump the target's window is never re-sent, the server goes on naming
// this buffer's handle, and once its slot is reused at a newer
// generation the next draw or dispatch that walks the window asks the
// backend for the dead one - Espryt dies with Fatal{ProtocolCorruption,
// "BackendSlotTable.Generation"} (DeletedBoundBufferScenario).
NoteBindPointChanged(BufferBindPointTargets[static_cast<SizeT>(
&bindingPointArray - m_bufferBindPointTargets.data())]);
#endif
}
}
}
+7
View File
@@ -1325,6 +1325,13 @@ namespace MobileGL::MG_State {
}
void GLContext::RestoreBoundTransformFeedbackState() {
#if MOBILEGL_PIPE_PUSH
// The FOURTH writer of the transform-feedback binding points (a bind or a delete of
// the bound transform-feedback object swaps the whole set in): it moves the generation
// like the other three, so bit 17 cannot miss a swap whose two objects happen to carry
// the same capture-span generation.
NoteBufferBindPointChanged(BufferTarget::TransformFeedback);
#endif
const auto& object = m_transformFeedbackObjects[m_boundTransformFeedback];
for (Uint i = 0; i < MAX_TRANSFORM_FEEDBACK_BUFFERS; ++i) {
auto& point = m_bufferState.GetBindingPoint(BufferTarget::TransformFeedback, i);