diff --git a/MobileGL/MG_Impl/Pipe/PipeFill.cpp b/MobileGL/MG_Impl/Pipe/PipeFill.cpp index 3e7264a0..ec0755db 100644 --- a/MobileGL/MG_Impl/Pipe/PipeFill.cpp +++ b/MobileGL/MG_Impl/Pipe/PipeFill.cpp @@ -1897,7 +1897,14 @@ namespace MobileGL::MG_Pipe { PublicationLatch().NoteUnpublished(kind, handle); } - void MGPipeForgetAllPublications() { PublicationLatch().Clear(); } + void MGPipeForgetAllPublications() { + PublicationLatch().Clear(); + // The two families whose death asks their own record rather than the latch: vertex + // elements (MGPipeEmitVertexElementsDestroyAndFree's RecordIsPublished) and buffers + // (MGPipeEmitResourceDestroyAndFree's WasPublished). + MGPipeVertexInputEmitterInstance().ForgetAllRecords(); + MGPipeResourceTrackerInstance().ForgetAllPublished(); + } // THE GATE ITSELF, AS AN OBSERVABLE (ID-39, widened by S-3 / ID-41). Every P4a birth hook // below and every `wants()` row in the walk resolve through FamilyIsLive / diff --git a/MobileGL/MG_Impl/Pipe/ResourceTracker.h b/MobileGL/MG_Impl/Pipe/ResourceTracker.h index b77a57cb..6b1ef92e 100644 --- a/MobileGL/MG_Impl/Pipe/ResourceTracker.h +++ b/MobileGL/MG_Impl/Pipe/ResourceTracker.h @@ -340,6 +340,10 @@ namespace MobileGL::MG_Pipe { const SizeT slot = handle.Slot; return slot < m_bySlot.size() && m_bySlot[slot].Published; } + // The session that held every buffer's record is gone (MGPipeForgetAllPublications). + void ForgetAllPublished() { + for (Entry& entry : m_bySlot) entry.Published = false; + } // The sticky everBoundAs mask. Sticky exactly as MGPResourceDesc::ImageBindableHint's // everImageBound is: ORed, never cleared, so a buffer that was an element array once diff --git a/MobileGL/MG_Impl/Pipe/VertexInputEmit.h b/MobileGL/MG_Impl/Pipe/VertexInputEmit.h index dd07b633..5ce743be 100644 --- a/MobileGL/MG_Impl/Pipe/VertexInputEmit.h +++ b/MobileGL/MG_Impl/Pipe/VertexInputEmit.h @@ -351,6 +351,14 @@ namespace MobileGL::MG_Pipe { m_boundLifetimeId = 0; } + // The session that held the records is gone (MGPipeForgetAllPublications): both halves go, + // the record half included, because no applier holds any of them any more. + void ForgetAllRecords() { + for (Latch& latch : m_latch) latch = Latch{}; + m_boundHandle = kMGPipeNullHandle; + m_boundLifetimeId = 0; + } + void ResetCounters() { m_creates = m_binds = m_bufferSets = m_indexSets = 0; } private: