mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (MG_Backend/DirectVulkan): keep the transient arena's outgrown buffers alive until frame rewind - the transient drain freed them while frame-serial memos still bound them
This commit is contained in:
@@ -111,6 +111,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.IsValid()) {
|
if (buffer.IsValid()) {
|
||||||
|
// Outgrown, not dead: every BufferSlice handed out from this frame's arena so far
|
||||||
|
// still names it, and those slices stay in service until the frame slot is rewound
|
||||||
|
// (VkBufferResource::transientSlice, the converted-vertex-stream cache, the draw
|
||||||
|
// memos). The release therefore has to survive every mid-frame reclaim and land on
|
||||||
|
// the next ResetFrame of this slot - see VkBufferManager::CollectAllDeferredReleases.
|
||||||
m_deferredReleases[frameIndex].push_back(std::move(buffer));
|
m_deferredReleases[frameIndex].push_back(std::move(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,12 +161,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VkBufferManager::CollectAllDeferredReleases() {
|
void VkBufferManager::CollectAllDeferredReleases() {
|
||||||
|
// Per-resource releases only. Every one of them was deferred behind a BumpSliceEpoch,
|
||||||
|
// so no memo can still name the handle, and the caller has proved the GPU is idle.
|
||||||
|
//
|
||||||
|
// The transient arena's releases are deliberately NOT collected here. A buffer lands
|
||||||
|
// there when the arena outgrows it mid-frame (BufferArena::EnsureCapacity), and at
|
||||||
|
// that moment every slice already handed out from this frame's arena still names it -
|
||||||
|
// VkBufferResource::transientSlice above all, which AcquireStreamedSlice keeps
|
||||||
|
// serving for the whole frame serial on the strength of transientFrameSerial alone.
|
||||||
|
// Nothing bumps the slice epoch for those other resources, so freeing the buffer
|
||||||
|
// here left the streamed memo handing a destroyed VkBuffer to vkCmdBindIndexBuffer
|
||||||
|
// (llvmpipe then faulted inside the draw; the Create/Flywheel indirect retrace died
|
||||||
|
// exactly this way). Mid-frame drains do not advance m_frameSerial, so they must not
|
||||||
|
// free arena storage either: the arena's own ResetFrame/BeginFrame is the point where
|
||||||
|
// the slot's slices stop being reachable, and that is where these releases land.
|
||||||
for (Uint32 frameIndex = 0; frameIndex < m_deferredBufferReleases.size(); ++frameIndex) {
|
for (Uint32 frameIndex = 0; frameIndex < m_deferredBufferReleases.size(); ++frameIndex) {
|
||||||
CollectDeferredReleases(frameIndex);
|
CollectDeferredReleases(frameIndex);
|
||||||
}
|
}
|
||||||
for (Uint32 frameIndex = 0; frameIndex < m_transientUploadArena.GetFrameCount(); ++frameIndex) {
|
|
||||||
m_transientUploadArena.CollectDeferredReleases(frameIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkBufferManager::NotifyDeviceIdle() {
|
void VkBufferManager::NotifyDeviceIdle() {
|
||||||
|
|||||||
@@ -102,10 +102,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// Recreate all per-frame transient arenas
|
// Recreate all per-frame transient arenas
|
||||||
Bool RecreateTransientArenas(Uint32 frameCount);
|
Bool RecreateTransientArenas(Uint32 frameCount);
|
||||||
void BeginFrame(Uint32 frameIndex);
|
void BeginFrame(Uint32 frameIndex);
|
||||||
// Drains every frame slot's deferred buffer/resource releases (and the
|
// Drains every frame slot's deferred buffer/resource releases. Only valid when
|
||||||
// transient arena's parked superseded blocks). Only valid when the
|
// the caller has proven every queue submission complete; used by the present-less
|
||||||
// caller has proven every queue submission complete; used by the
|
// frame-boundary drain. Deliberately does NOT touch the transient arena's parked
|
||||||
// present-less frame-boundary drain.
|
// superseded blocks: those are still named by this frame's slices (see the
|
||||||
|
// definition), and only a frame rewind retires them.
|
||||||
void CollectAllDeferredReleases();
|
void CollectAllDeferredReleases();
|
||||||
// All previously submitted GPU work has completed (vkDeviceWaitIdle).
|
// All previously submitted GPU work has completed (vkDeviceWaitIdle).
|
||||||
void NotifyDeviceIdle();
|
void NotifyDeviceIdle();
|
||||||
|
|||||||
Reference in New Issue
Block a user