mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Refactor] (Espryt): key the narrowed fp64 vertex stream on the buffer's handle instead of its lifetime id
This commit is contained in:
@@ -218,8 +218,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
VertexArrayImpl::g_backendVertexArrayObjects.DestroyByLifetimeId(lifetimeId);
|
VertexArrayImpl::g_backendVertexArrayObjects.DestroyByLifetimeId(lifetimeId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Buffer already has its own death signal (BufferBackendOps::OnDestroy) and
|
// Buffer death crosses as ResourceDestroy (P3a): the catalogue has a call for
|
||||||
// every other kind has no backend twin table here.
|
// it, so no seventh NotifyStateObjectDestroyed raiser is added. The notice
|
||||||
|
// exists for kinds that have NO such call - it carries {kind, lifetimeId} and
|
||||||
|
// not the object, and one entry point serves all of them because the answer is
|
||||||
|
// the same. The order at the buffer's death is fixed and not negotiable:
|
||||||
|
// resource_destroy first (the applier clears Live, the backend retires the
|
||||||
|
// twin), then MGPipeSlots().Free - the allocator erases its lifetimeId -> slot
|
||||||
|
// mapping on Free, so a notice resolved twice finds nothing the second time.
|
||||||
|
// On the legacy arm the signal is still BufferBackendOps::OnDestroy. Every
|
||||||
|
// other kind has no backend twin table here.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2243,6 +2251,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SizeT ResourceWidthForHandle(MG_Pipe::MGPipeHandle res) { return ResourceWidthOf(res); }
|
SizeT ResourceWidthForHandle(MG_Pipe::MGPipeHandle res) { return ResourceWidthOf(res); }
|
||||||
|
Uint64 ResourceSerialForHandle(MG_Pipe::MGPipeHandle res) { return ResourceSerialOf(res); }
|
||||||
|
|
||||||
void MarkBufferGpuWritten(const SharedPtr<MG_State::GLState::BufferObject>& bufferObject) {
|
void MarkBufferGpuWritten(const SharedPtr<MG_State::GLState::BufferObject>& bufferObject) {
|
||||||
if (!bufferObject) return;
|
if (!bufferObject) return;
|
||||||
@@ -4028,6 +4037,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MOBILEGL_PIPE_LEGACY_MEMOS
|
||||||
Bool BackendVertexArrayObject::SyncFloat64AttributeAsFloat32(
|
Bool BackendVertexArrayObject::SyncFloat64AttributeAsFloat32(
|
||||||
Uint attribIndex, const MG_State::GLState::VertexAttribute& attrib, Uint32 fetchBaseInstance) {
|
Uint attribIndex, const MG_State::GLState::VertexAttribute& attrib, Uint32 fetchBaseInstance) {
|
||||||
#ifdef TRACY_ENABLE
|
#ifdef TRACY_ENABLE
|
||||||
@@ -4147,6 +4157,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
(const void*)(firstElement * convertedElementSize));
|
(const void*)(firstElement * convertedElementSize));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif // MOBILEGL_PIPE_LEGACY_MEMOS
|
||||||
|
|
||||||
#if MOBILEGL_PIPE_PUSH
|
#if MOBILEGL_PIPE_PUSH
|
||||||
Bool BackendVertexArrayObject::SyncFloat64AttributeAsFloat32ByHandle(
|
Bool BackendVertexArrayObject::SyncFloat64AttributeAsFloat32ByHandle(
|
||||||
@@ -4199,7 +4210,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& stream = m_convertedAttributeStreams[attribIndex];
|
||||||
Uint& convertedBufferId = m_convertedAttributeBufferIds[attribIndex];
|
Uint& convertedBufferId = m_convertedAttributeBufferIds[attribIndex];
|
||||||
|
const Uint64 sourceSerial = BufferImpl::ResourceSerialForHandle(binding.Res);
|
||||||
|
// The memo, re-keyed: the pin is the source buffer's {slot, gen} instead of a
|
||||||
|
// frontend lifetime id, and the freshness input is the applier's server-owned
|
||||||
|
// Serial instead of the frontend change serial. A PERSISTENTLY MAPPED source is
|
||||||
|
// still never trusted - it is written through the pointer with no call at all, so
|
||||||
|
// no serial on either side can prove the converted copy is current.
|
||||||
|
const Bool memoHit = stream.valid && convertedBufferId != 0 && !resource->persistentMapped &&
|
||||||
|
stream.sourceHandle == binding.Res &&
|
||||||
|
stream.sourceChangeSerial == sourceSerial &&
|
||||||
|
stream.sourceOffset == static_cast<SizeT>(attrib.Offset) &&
|
||||||
|
stream.sourceStride == sourceStride &&
|
||||||
|
stream.componentCount == componentCount && stream.elementCount == elementCount;
|
||||||
|
if (!memoHit) {
|
||||||
if (convertedBufferId == 0) {
|
if (convertedBufferId == 0) {
|
||||||
g_GLESFuncs.glGenBuffers(1, &convertedBufferId);
|
g_GLESFuncs.glGenBuffers(1, &convertedBufferId);
|
||||||
if (convertedBufferId == 0) {
|
if (convertedBufferId == 0) {
|
||||||
@@ -4209,10 +4234,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// NO MEMO YET on this arm: its key is the source buffer's identity plus its change
|
|
||||||
// serial, and re-keying ConvertedFloat64Stream onto the buffer's {slot, gen} is the
|
|
||||||
// next commit's whole subject. Until then every walk reconverts, which is correct
|
|
||||||
// and slower on a path that only 64-bit vertex arrays reach.
|
|
||||||
Vector<Float> converted;
|
Vector<Float> converted;
|
||||||
NarrowDoubleStreamToFloat32(sourceBase + attrib.Offset, sourceStride, componentCount, elementCount,
|
NarrowDoubleStreamToFloat32(sourceBase + attrib.Offset, sourceStride, componentCount, elementCount,
|
||||||
converted);
|
converted);
|
||||||
@@ -4223,6 +4244,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
MG_Util::PipeStats::AddBytes(MG_Util::PipeStats::ByteClass::StageVertexClient,
|
MG_Util::PipeStats::AddBytes(MG_Util::PipeStats::ByteClass::StageVertexClient,
|
||||||
static_cast<Uint64>(converted.size() * sizeof(Float)));
|
static_cast<Uint64>(converted.size() * sizeof(Float)));
|
||||||
}
|
}
|
||||||
|
stream.valid = true;
|
||||||
|
stream.sourceHandle = binding.Res;
|
||||||
|
stream.sourceChangeSerial = sourceSerial;
|
||||||
|
stream.sourceOffset = static_cast<SizeT>(attrib.Offset);
|
||||||
|
stream.sourceStride = sourceStride;
|
||||||
|
stream.componentCount = componentCount;
|
||||||
|
stream.elementCount = elementCount;
|
||||||
|
MGLOG_D("DirectGLES: narrowed the 64-bit vertex array at attribute %u to %zu float32 element(s).",
|
||||||
|
attribIndex, elementCount);
|
||||||
|
}
|
||||||
|
|
||||||
const SizeT convertedElementSize = componentCount * sizeof(Float);
|
const SizeT convertedElementSize = componentCount * sizeof(Float);
|
||||||
if (neverAdvances) {
|
if (neverAdvances) {
|
||||||
|
|||||||
@@ -741,6 +741,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// thing outside BufferImpl that needs it is the fp64 narrowing, whose source extent
|
// thing outside BufferImpl that needs it is the fp64 narrowing, whose source extent
|
||||||
// used to be BufferObject::GetSize().
|
// used to be BufferObject::GetSize().
|
||||||
SizeT ResourceWidthForHandle(MG_Pipe::MGPipeHandle res);
|
SizeT ResourceWidthForHandle(MG_Pipe::MGPipeHandle res);
|
||||||
|
// The applier's server-owned mutation serial for this resource, 0 when it has no
|
||||||
|
// record. It is what the narrowed-fp64 memo keys its freshness on now that the
|
||||||
|
// frontend change serial is gone from the backend's view.
|
||||||
|
Uint64 ResourceSerialForHandle(MG_Pipe::MGPipeHandle res);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Registered as the frontend's BufferBackendOps at backend init and on
|
// Registered as the frontend's BufferBackendOps at backend init and on
|
||||||
@@ -1008,8 +1012,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// dropping it. Returns false when the stream cannot be built, in which case the
|
// dropping it. Returns false when the stream cannot be built, in which case the
|
||||||
// caller must DISABLE the array - leaving a 64-bit array enabled with no pointer is
|
// caller must DISABLE the array - leaving a 64-bit array enabled with no pointer is
|
||||||
// what the Adreno driver turns into a SIGSEGV at the next draw.
|
// what the Adreno driver turns into a SIGSEGV at the next draw.
|
||||||
|
#if MOBILEGL_PIPE_LEGACY_MEMOS
|
||||||
Bool SyncFloat64AttributeAsFloat32(Uint attribIndex, const MG_State::GLState::VertexAttribute& attrib,
|
Bool SyncFloat64AttributeAsFloat32(Uint attribIndex, const MG_State::GLState::VertexAttribute& attrib,
|
||||||
Uint32 fetchBaseInstance);
|
Uint32 fetchBaseInstance);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MOBILEGL_PIPE_PUSH
|
#if MOBILEGL_PIPE_PUSH
|
||||||
// The handle arm of the whole vertex-elements half. Everything it needs arrives in
|
// The handle arm of the whole vertex-elements half. Everything it needs arrives in
|
||||||
@@ -1030,7 +1036,24 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// is part of the key, so a glBufferSubData into the source invalidates it.
|
// is part of the key, so a glBufferSubData into the source invalidates it.
|
||||||
struct ConvertedFloat64Stream {
|
struct ConvertedFloat64Stream {
|
||||||
Bool valid = false;
|
Bool valid = false;
|
||||||
|
#if MOBILEGL_PIPE_LEGACY_MEMOS
|
||||||
|
// The pre-handle pin: a FRONTEND lifetime id, i.e. the key
|
||||||
|
// ARCHITECTURE.md 9.5 lists for deletion as "ConvertedVertexStreamKey's
|
||||||
|
// sourcePin". Kept compiled for the legacy arm (and therefore present in
|
||||||
|
// every pull build, which is what keeps sizeof(this) still).
|
||||||
Uint64 sourceLifetimeId = 0;
|
Uint64 sourceLifetimeId = 0;
|
||||||
|
#endif
|
||||||
|
#if MOBILEGL_PIPE_PUSH
|
||||||
|
// What replaces it: the source buffer's {slot, gen}. It is the SAME identity
|
||||||
|
// the rest of the backend now keys on, it cannot be reproduced by a recycled
|
||||||
|
// frontend address, and it costs the walk no allocator probe - the handle is
|
||||||
|
// already in the vertex-buffer entry that named the source.
|
||||||
|
MG_Pipe::MGPipeHandle sourceHandle = MG_Pipe::kMGPipeNullHandle;
|
||||||
|
#endif
|
||||||
|
// On the handle arm this is the applier's server-owned Serial rather than the
|
||||||
|
// frontend change serial; both answer the same question - "have the source
|
||||||
|
// bytes moved since the conversion" - and neither is trusted for a
|
||||||
|
// persistently mapped buffer, which is written with no call at all.
|
||||||
Uint64 sourceChangeSerial = 0;
|
Uint64 sourceChangeSerial = 0;
|
||||||
SizeT sourceOffset = 0;
|
SizeT sourceOffset = 0;
|
||||||
SizeT sourceStride = 0;
|
SizeT sourceStride = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user