mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Fix] (Espryt): keep the live-map question in the handle arm's draw-clean probe instead of a record field P3a pins false
This commit is contained in:
@@ -612,7 +612,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
Bool allClean = true;
|
Bool allClean = true;
|
||||||
for (Uint i = 0; i < memo->count; ++i) {
|
for (Uint i = 0; i < memo->count; ++i) {
|
||||||
auto& entry = memo->entries[i];
|
auto& entry = memo->entries[i];
|
||||||
if (IsBufferDrawCleanByHandle(entry.handle, entry.resource)) continue;
|
// entry.frontend is the same object the legacy arm probes and is kept
|
||||||
|
// alive by the VAO attribute's SharedPtr for as long as this memo is
|
||||||
|
// valid; it answers the live-map question no record carries in P3a.
|
||||||
|
if (IsBufferDrawCleanByHandle(entry.handle, entry.resource, entry.frontend)) continue;
|
||||||
allClean = false;
|
allClean = false;
|
||||||
entry.resource =
|
entry.resource =
|
||||||
EnsureBufferResource(currentVAOObject->GetAttribute(entry.attribIndex).Buffer);
|
EnsureBufferResource(currentVAOObject->GetAttribute(entry.attribIndex).Buffer);
|
||||||
@@ -787,7 +790,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
if (memo && memo->iboHandle == iboHandle && memo->iboCleanEpoch == bufferEpoch) {
|
if (memo && memo->iboHandle == iboHandle && memo->iboCleanEpoch == bufferEpoch) {
|
||||||
// probed fully clean at this epoch; nothing can have dirtied it
|
// probed fully clean at this epoch; nothing can have dirtied it
|
||||||
} else if (memo && memo->iboHandle == iboHandle &&
|
} else if (memo && memo->iboHandle == iboHandle &&
|
||||||
IsBufferDrawCleanByHandle(iboHandle, memo->iboResource)) {
|
IsBufferDrawCleanByHandle(iboHandle, memo->iboResource,
|
||||||
|
possibleIBO.get())) {
|
||||||
memo->iboCleanEpoch = bufferEpoch;
|
memo->iboCleanEpoch = bufferEpoch;
|
||||||
} else {
|
} else {
|
||||||
auto* resource = EnsureBufferResource(possibleIBO);
|
auto* resource = EnsureBufferResource(possibleIBO);
|
||||||
|
|||||||
@@ -2426,13 +2426,25 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// identity the slot table's twin at this handle, not GetBackendResource()
|
// identity the slot table's twin at this handle, not GetBackendResource()
|
||||||
// size record.Desc.Width, not GetSize()
|
// size record.Desc.Width, not GetSize()
|
||||||
// freshness record.Serial vs syncedChangeSerial, not GetChangeSerial()
|
// freshness record.Serial vs syncedChangeSerial, not GetChangeSerial()
|
||||||
// map state record.HasLiveHostWrites, not IsMapped()
|
// map state record.HasLiveHostWrites AND the frontend's IsMapped() - see below
|
||||||
// the rest unchanged, and server-side to begin with
|
// the rest unchanged, and server-side to begin with
|
||||||
//
|
//
|
||||||
// HasLiveHostWrites is ALWAYS FALSE in P3a and is written by nobody; it is here so the
|
// HasLiveHostWrites is ALWAYS FALSE in P3a and is written by nobody; it is here so the
|
||||||
// phase that pushes persistent-mapped host writes can set it with no new record kind,
|
// phase that pushes persistent-mapped host writes can set it with no new record kind,
|
||||||
// and the assertion below is what stops that phase landing a silent semantic change.
|
// and the assertion below is what stops that phase landing a silent semantic change.
|
||||||
Bool IsBufferDrawCleanByHandle(MG_Pipe::MGPipeHandle res, const GLESBufferResource* resource) {
|
//
|
||||||
|
// BECAUSE it is pinned false, it CANNOT stand in for the frontend's IsMapped() yet, and
|
||||||
|
// the probe still asks the object: an EMULATED (non-adopted) persistent map - under the
|
||||||
|
// 16 MiB adoption threshold, or with DisableLargeBufferAdoption, or with no
|
||||||
|
// EXT_buffer_storage - mutates the client's shadow with no call, no serial and no epoch,
|
||||||
|
// which is the entire reason the legacy probe asks a map question instead of a serial
|
||||||
|
// one. Answering only HasLiveHostWrites made such a buffer read draw-clean forever, so
|
||||||
|
// SyncPersistentMappedRange (D-N keeps it on the ensure path for all of P3a) was never
|
||||||
|
// reached again and the frame drew the last uploaded bytes with no diagnostic anywhere.
|
||||||
|
// The frontend read retires the moment P5 gives HasLiveHostWrites a producer, and it is
|
||||||
|
// the last frontend read in this function.
|
||||||
|
Bool IsBufferDrawCleanByHandle(MG_Pipe::MGPipeHandle res, const GLESBufferResource* resource,
|
||||||
|
const MG_State::GLState::BufferObject* frontend) {
|
||||||
if (!resource) return false;
|
if (!resource) return false;
|
||||||
const auto* twin = g_backendBufferResources.FindByHandle(res);
|
const auto* twin = g_backendBufferResources.FindByHandle(res);
|
||||||
if (twin == nullptr || twin->get() != resource) return false;
|
if (twin == nullptr || twin->get() != resource) return false;
|
||||||
@@ -2448,6 +2460,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
"MGPipeResourceRecord::HasLiveHostWrites is set, but P3a has no producer for it");
|
"MGPipeResourceRecord::HasLiveHostWrites is set, but P3a has no producer for it");
|
||||||
#endif
|
#endif
|
||||||
if (record->HasLiveHostWrites) return false;
|
if (record->HasLiveHostWrites) return false;
|
||||||
|
// The same question the legacy arm asks at this exact point in the order, for the
|
||||||
|
// reason written at the top of this function. A null object is the "no frontend to
|
||||||
|
// ask" case (nothing reaches this probe without one today) and is treated as "not
|
||||||
|
// mapped", which is what the record already says.
|
||||||
|
if (frontend != nullptr && frontend->IsMapped()) return false;
|
||||||
if (resource->pendingRespecify || !resource->storageInitialized) return false;
|
if (resource->pendingRespecify || !resource->storageInitialized) return false;
|
||||||
if (!resource->pendingRanges.empty()) return false;
|
if (!resource->pendingRanges.empty()) return false;
|
||||||
if (resource->storageSize != static_cast<SizeT>(record->Desc.Width)) return false;
|
if (resource->storageSize != static_cast<SizeT>(record->Desc.Width)) return false;
|
||||||
@@ -2458,7 +2475,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
Bool IsBufferDrawClean(const MG_State::GLState::BufferObject* frontend, const GLESBufferResource* resource) {
|
Bool IsBufferDrawClean(const MG_State::GLState::BufferObject* frontend, const GLESBufferResource* resource) {
|
||||||
#if MOBILEGL_PIPE_PUSH
|
#if MOBILEGL_PIPE_PUSH
|
||||||
if (ResourceSubsystemEnabled()) {
|
if (ResourceSubsystemEnabled()) {
|
||||||
return IsBufferDrawCleanByHandle(HandleOfBuffer(frontend), resource);
|
return IsBufferDrawCleanByHandle(HandleOfBuffer(frontend), resource, frontend);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Identity first: a respecify path can hand the frontend a NEW resource; the
|
// Identity first: a respecify path can hand the frontend a NEW resource; the
|
||||||
|
|||||||
@@ -721,7 +721,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// asks the applier the same five questions IsBufferDrawClean asks the frontend object,
|
// asks the applier the same five questions IsBufferDrawClean asks the frontend object,
|
||||||
// with identical semantics (D-A4); EnsureBufferResourceForHandle is the ensure path
|
// with identical semantics (D-A4); EnsureBufferResourceForHandle is the ensure path
|
||||||
// driven by the applier's descriptor and the shadow base the call carried.
|
// driven by the applier's descriptor and the shadow base the call carried.
|
||||||
Bool IsBufferDrawCleanByHandle(MG_Pipe::MGPipeHandle res, const GLESBufferResource* resource);
|
//
|
||||||
|
// `frontend` supplies the ONE question the applier's record cannot answer in P3a: an
|
||||||
|
// emulated (non-adopted) persistent map is written through its pointer with no call, so
|
||||||
|
// MGPipeResourceRecord::HasLiveHostWrites - the field that will carry it - is pinned
|
||||||
|
// false and the probe still has to ask the object. It retires with P5. See the long note
|
||||||
|
// at the definition; passing null means "no live map", not "unknown".
|
||||||
|
Bool IsBufferDrawCleanByHandle(MG_Pipe::MGPipeHandle res, const GLESBufferResource* resource,
|
||||||
|
const MG_State::GLState::BufferObject* frontend);
|
||||||
GLESBufferResource* EnsureBufferResourceForHandle(
|
GLESBufferResource* EnsureBufferResourceForHandle(
|
||||||
const SharedPtr<MG_State::GLState::BufferObject>& bufferObject, MG_Pipe::MGPipeHandle res);
|
const SharedPtr<MG_State::GLState::BufferObject>& bufferObject, MG_Pipe::MGPipeHandle res);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user