mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (Espryt): a partial buffer flush no longer takes the range-invalidating map while an upload-ring copy into the same store may still be queued - Adreno 830 loses the queued copy, and create-instancing drew whole Embeddium terrain sections empty
This commit is contained in:
@@ -899,8 +899,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// shadow's to rewrite. Widening to page bounds looked free and was
|
||||
// not - the widened bytes clobbered GPU-written data (an SSBO
|
||||
// counter beside the app's SubData) with the stale shadow.
|
||||
//
|
||||
// A partial range-invalidating map must not overtake a ring copy into
|
||||
// this store the GPU has not run yet. Adreno 830 answers such a map on
|
||||
// a store with a copy still queued by losing the copy: the Embeddium
|
||||
// section meshes create-instancing staged through the ring came out
|
||||
// empty (whole terrain sections missing, SSIM 0.870), and routing the
|
||||
// map ranges behind the copies - the ring tier, GPU-ordered after them -
|
||||
// brings every one back. The whole-buffer orphan-map is exempt: it
|
||||
// rewrites every byte from the shadow the queued copies were taken from.
|
||||
const Bool wholeBuffer = start == 0 && end == limit && limit == resource.storageSize;
|
||||
if (mapUsable && (wholeBuffer || size >= kInvalidateRangeMinBytes)) {
|
||||
const Bool ringCopyInFlight = resource.ringCopyRetireSerial > DirectGLES::CompletedFrameSerial();
|
||||
if (mapUsable && (wholeBuffer || (size >= kInvalidateRangeMinBytes && !ringCopyInFlight))) {
|
||||
BindBufferId(TempBufferTarget, resource.id);
|
||||
const GLbitfield access =
|
||||
GL_MAP_WRITE_BIT |
|
||||
@@ -921,6 +931,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
BindBufferId(GL_COPY_WRITE_BUFFER, resource.id);
|
||||
g_GLESFuncs.glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||
(GLintptr)ringOffset, (GLintptr)start, (GLsizeiptr)size);
|
||||
// Commands recorded now retire with the fence the next Present inserts.
|
||||
resource.ringCopyRetireSerial = DirectGLES::CurrentFrameSerial() + 1;
|
||||
} else {
|
||||
UploadRangeNow(resource, bufferObject, start, end);
|
||||
}
|
||||
|
||||
@@ -478,6 +478,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// (the UBO binding walk) skip the probe while their pre-pass epoch read
|
||||
// matches, exactly like the per-VAO memo stamps.
|
||||
Uint64 drawCleanEpoch = 0;
|
||||
// Frame serial whose completion retires the last glCopyBufferSubData the upload
|
||||
// ring staged INTO this store (FlushPendingRangesNow's ring tier); 0 = none. Until
|
||||
// it retires, FlushPendingRangesNow keeps every partial range off the
|
||||
// range-invalidating map: on Adreno 830 that map, on a store with a queued copy,
|
||||
// loses the copy (see FlushPendingRangesNow). Draw thread only, like the flush.
|
||||
Uint64 ringCopyRetireSerial = 0;
|
||||
// Zero-copy coherent persistent map (EXT_buffer_storage): the GL store is
|
||||
// immutable, persistently+coherently mapped, and persistentPtr is what the app
|
||||
// (and the frontend PipeResource) write into directly. While set, draw-time
|
||||
|
||||
Reference in New Issue
Block a user