mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-14 07:08:32 +09:00
[Fix, Test] (MG_State, MG_Backend/DirectVulkan, MG_Backend/DirectGLES, MG_IntegrationTest): a respecified capture buffer left the transform feedback writing one store and the readback reading another
This commit is contained in:
@@ -603,7 +603,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
void Ops_Respecify(BufferObject& bufferObject) {
|
||||
auto* resource = ResourceOf(bufferObject);
|
||||
if (!resource) return; // lazy: EnsureBufferResource full-uploads on creation
|
||||
if (resource->persistentMapped) return; // immutable persistent storage is never respecified
|
||||
if (resource->persistentMapped) {
|
||||
// The frontend writes straight into the storage mapped here, and it
|
||||
// renewed that mapping for the redefined store before writing to it
|
||||
// (BufferObject::RedefineStorage), so the new contents already are
|
||||
// where a respecification would put them.
|
||||
if (bufferObject.IsBackendPersistentMapped()) return;
|
||||
// Renewal declined (a zero-sized store, or the map could not be
|
||||
// retaken): the buffer is back on its CPU shadow and needs the
|
||||
// ordinary respecification below.
|
||||
resource->persistentMapped = false;
|
||||
resource->persistentPtr = nullptr;
|
||||
}
|
||||
if (!CanTouchGLNow() || resource->id == 0 ||
|
||||
resource->contextGeneration != g_bufferContextGeneration) {
|
||||
resource->pendingRespecify = true;
|
||||
|
||||
@@ -379,6 +379,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
BumpSliceEpoch(*resource);
|
||||
// Any cached streaming slice refers to the previous contents.
|
||||
resource->transientFrameSerial = 0;
|
||||
if (resource->persistentMapped) {
|
||||
if (bufferObject.IsBackendPersistentMapped()) {
|
||||
// The frontend renewed its adoption of this storage for the redefined
|
||||
// store before writing a byte of it (BufferObject::RedefineStorage), so
|
||||
// the new contents are already HERE and there is no second copy to
|
||||
// update. Swapping the storage is what must not happen: the mapping the
|
||||
// frontend holds, and every read that resolves through it, would keep
|
||||
// addressing the storage being released - which is how a transform
|
||||
// feedback capture came to be written to one buffer and read back out
|
||||
// of another.
|
||||
return;
|
||||
}
|
||||
// The renewal did not happen (a zero-sized store, or the storage could not
|
||||
// be created): the frontend is back on its CPU shadow, so this is an
|
||||
// ordinary resident buffer again and the handling below applies.
|
||||
resource->persistentMapped = false;
|
||||
}
|
||||
if (!resource->buffer.IsValid()) {
|
||||
return; // streaming-only resource: shadow + serial are enough
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user