mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Fix] (DirectVulkan): never stream a buffer whose storage the application holds
AcquirePersistentMap promises the storage it creates is never recreated, because the frontend adopts it in place of the shadow and hands out pointers into it. AcquireStreamedSlice broke that promise: its downgrade path releases the resident storage unconditionally to avoid keeping a second stale copy, so binding such a buffer as a vertex or index source freed the memory the application was still pointing at. It also fed that draw the wrong bytes. The streaming copy is uploaded from the shadow, and a persistently mapped buffer can hold bytes the shadow never saw -- a transform feedback capture writes straight into the resident storage. The next capture into the same buffer then landed in freshly recreated storage while the application kept reading the original, which is how the ping-pong in transform_feedback.draw_xfb_feedbackk_test stalled after its first doubling. Route a persistently mapped resource to the resident path instead, where its single piece of storage is bound directly.
This commit is contained in:
@@ -561,6 +561,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
auto resource = GetOrCreateResource(bufferObject);
|
||||
bufferObject->SyncPersistentMappedRange();
|
||||
|
||||
// A persistently mapped resource's storage IS the application's copy of the bytes -
|
||||
// the frontend adopted it in place of the shadow and hands out pointers into it, and
|
||||
// a shader can have written bytes the shadow never saw (a transform feedback
|
||||
// capture). Streaming a second copy would feed this draw the stale shadow, and the
|
||||
// downgrade below would release the storage the application still points at,
|
||||
// breaking the "never recreated" promise AcquirePersistentMap makes.
|
||||
if (resource->persistentMapped) {
|
||||
return AcquireResidentSlice(kind, bufferObject, outSlice);
|
||||
}
|
||||
|
||||
const VkDeviceSize size = static_cast<VkDeviceSize>(bufferObject->GetSize());
|
||||
if (size == 0) {
|
||||
MGLOG_E("VkBufferManager::AcquireStreamedSlice failed: buffer size is zero");
|
||||
|
||||
Reference in New Issue
Block a user