mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 05:38:31 +09:00
[Refactor] (Espryt): answer a readback through the reverse channel and bump the mutation epoch after it, never before
This commit is contained in:
@@ -497,7 +497,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
for (SizeT i = 0; i < bindingPointCnt; ++i) {
|
for (SizeT i = 0; i < bindingPointCnt; ++i) {
|
||||||
const auto& obj =
|
const auto& obj =
|
||||||
MGB_CTX->GetBufferBindingPoint(BufferTarget::ShaderStorage, i).GetBoundObject();
|
MGB_CTX->GetBufferBindingPoint(BufferTarget::ShaderStorage, i).GetBoundObject();
|
||||||
|
#if MOBILEGL_PIPE_PUSH
|
||||||
|
// P3a (D-D): announced on the reverse channel on the handle arm, poked into
|
||||||
|
// the object on the legacy one. MarkBufferGpuWritten is the one place that
|
||||||
|
// decides, so the three announcement sites stay one line each.
|
||||||
|
MarkBufferGpuWritten(obj);
|
||||||
|
#else
|
||||||
if (obj) obj->MarkGpuWritten();
|
if (obj) obj->MarkGpuWritten();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,7 +548,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// conformance case reads the result back with glMapBufferRange or
|
// conformance case reads the result back with glMapBufferRange or
|
||||||
// glGetBufferSubData - which serve the frontend's CPU shadow until the buffer is
|
// glGetBufferSubData - which serve the frontend's CPU shadow until the buffer is
|
||||||
// flagged (BufferObject::SyncGpuWrites), exactly as for a storage buffer.
|
// flagged (BufferObject::SyncGpuWrites), exactly as for a storage buffer.
|
||||||
|
#if MOBILEGL_PIPE_PUSH
|
||||||
|
MarkBufferGpuWritten(obj);
|
||||||
|
#else
|
||||||
obj->MarkGpuWritten();
|
obj->MarkGpuWritten();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2009,7 +2020,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
auto* textureBuffer =
|
auto* textureBuffer =
|
||||||
static_cast<MG_State::GLState::TextureObjectBuffer*>(imageBinding.Texture.get());
|
static_cast<MG_State::GLState::TextureObjectBuffer*>(imageBinding.Texture.get());
|
||||||
const auto& bufferObject = textureBuffer->GetBufferBindingSlot().GetBoundObject();
|
const auto& bufferObject = textureBuffer->GetBufferBindingSlot().GetBoundObject();
|
||||||
|
#if MOBILEGL_PIPE_PUSH
|
||||||
|
BufferImpl::MarkBufferGpuWritten(bufferObject);
|
||||||
|
#else
|
||||||
if (bufferObject) bufferObject->MarkGpuWritten();
|
if (bufferObject) bufferObject->MarkGpuWritten();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2002,6 +2002,17 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// no longer reaches into the frontend's address space, it ANSWERS. In monolith
|
// no longer reaches into the frontend's address space, it ANSWERS. In monolith
|
||||||
// the client's implementation is one call away, so SyncGpuWrites' caller still
|
// the client's implementation is one call away, so SyncGpuWrites' caller still
|
||||||
// sees the reconciled shadow on return, exactly as before.
|
// sees the reconciled shadow on return, exactly as before.
|
||||||
|
//
|
||||||
|
// THE ORDER FROM HERE IS A CORRECTNESS RULE, NOT A PREFERENCE
|
||||||
|
// (ARCHITECTURE.md 8.2: "写回的 epoch bump 必须在任何后续读该 handle 的命令之前被
|
||||||
|
// server 应用;反向通道需要与正向通道相同的有序保证"):
|
||||||
|
// 1. writeback - the client's shadow takes the bytes,
|
||||||
|
// 2. unmap - the read mapping goes away,
|
||||||
|
// 3. serial stamp- syncedChangeSerial catches up with the record, so the next
|
||||||
|
// draw does not re-upload the readback over itself,
|
||||||
|
// 4. epoch bump - in Ops_H_ReadbackTracked, i.e. strictly AFTER 1-3, so a
|
||||||
|
// draw-clean memo re-probed by the bump can never observe a
|
||||||
|
// half-reconciled resource. The bump must NEVER move earlier.
|
||||||
if (MG_Pipe::gMGPipeCallbacks.OnBufferWriteback != nullptr) {
|
if (MG_Pipe::gMGPipeCallbacks.OnBufferWriteback != nullptr) {
|
||||||
MG_Pipe::gMGPipeCallbacks.OnBufferWriteback(
|
MG_Pipe::gMGPipeCallbacks.OnBufferWriteback(
|
||||||
res, record.Offset,
|
res, record.Offset,
|
||||||
@@ -2230,6 +2241,33 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
return MG_Pipe::MGPipeSlots().FindByLifetimeId(MG_Pipe::MGPipeKind::Buffer,
|
return MG_Pipe::MGPipeSlots().FindByLifetimeId(MG_Pipe::MGPipeKind::Buffer,
|
||||||
bufferObject->GetLifetimeId());
|
bufferObject->GetLifetimeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MarkBufferGpuWritten(const SharedPtr<MG_State::GLState::BufferObject>& bufferObject) {
|
||||||
|
if (!bufferObject) return;
|
||||||
|
if (!ResourceSubsystemEnabled()) {
|
||||||
|
bufferObject->MarkGpuWritten();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const MG_Pipe::MGPipeHandle res = HandleOfBuffer(bufferObject.get());
|
||||||
|
if (MG_Pipe::MGPipeHandleIsNull(res) || MG_Pipe::gMGPipeCallbacks.OnGpuWritten == nullptr) {
|
||||||
|
// Deliberately NOT a fall-back to MarkGpuWritten: on this arm the resource
|
||||||
|
// family is switched over, and quietly reaching into the frontend object again
|
||||||
|
// would hide a missing handle or a missing reverse channel behind a picture
|
||||||
|
// that still looks right - which is what the subsystem A/B exists to expose.
|
||||||
|
MGLOG_E_ONCE("MGPipe: no reverse channel for the GPU-write announcement of buffer %u "
|
||||||
|
"(handle %s, OnGpuWritten %s)",
|
||||||
|
bufferObject->GetExternalIndex(),
|
||||||
|
MG_Pipe::MGPipeHandleIsNull(res) ? "missing" : "present",
|
||||||
|
MG_Pipe::gMGPipeCallbacks.OnGpuWritten == nullptr ? "unset" : "set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// WHOLE RESOURCE, stated rather than implied: the extent is spelled as one range of
|
||||||
|
// kMGPipeWholeBuffer rather than as "zero ranges", because a zero count is the
|
||||||
|
// shape a fully NARROWED announcement will legitimately have once P8/P9 build the
|
||||||
|
// client's conservative set, and the two must not be the same record.
|
||||||
|
const MG_Pipe::MGPRange whole{0, MG_Pipe::kMGPipeWholeBuffer};
|
||||||
|
MG_Pipe::gMGPipeCallbacks.OnGpuWritten(res, 1, &whole);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// See the declaration: re-mints of a live resource's driver id. Written only on
|
// See the declaration: re-mints of a live resource's driver id. Written only on
|
||||||
|
|||||||
@@ -720,6 +720,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
Bool IsBufferDrawCleanByHandle(MG_Pipe::MGPipeHandle res, const GLESBufferResource* resource);
|
Bool IsBufferDrawCleanByHandle(MG_Pipe::MGPipeHandle res, const GLESBufferResource* resource);
|
||||||
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);
|
||||||
|
|
||||||
|
// P3a (D-D): "the GPU wrote through this resource", announced on the reverse channel
|
||||||
|
// instead of poked into the frontend object. ARCHITECTURE.md calls OnGpuWritten a
|
||||||
|
// NARROWING channel - the client builds its pending set conservatively at each
|
||||||
|
// draw/dispatch emission point and this callback only ever takes entries out of it -
|
||||||
|
// so in P3a, where the client's conservative set is exactly what the three
|
||||||
|
// MarkGpuWritten sites marked, the announced set is the whole resource and the
|
||||||
|
// observable behaviour is identical. P8/P9 narrow it; the channel is what they need.
|
||||||
|
//
|
||||||
|
// The legacy arm keeps calling BufferObject::MarkGpuWritten directly, and the pull
|
||||||
|
// build never sees this function at all (G1).
|
||||||
|
void MarkBufferGpuWritten(const SharedPtr<MG_State::GLState::BufferObject>& bufferObject);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Registered as the frontend's BufferBackendOps at backend init and on
|
// Registered as the frontend's BufferBackendOps at backend init and on
|
||||||
|
|||||||
Reference in New Issue
Block a user