mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Perf] (Espryt): a VAO twin adopts an unchanged buffer set and element buffer instead of re-emitting them (rd12 monolith 75.2 -> 80.5 fps).
This commit is contained in:
@@ -4690,6 +4690,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
VertexArrayImpl::BackendVertexArrayObject* vaoTwin = nullptr;
|
||||
Uint32 vaoConfigVersion = 0;
|
||||
vaoTwin = VertexArrayImpl::ResolveVaoTwin(MG_Pipe::MGPipeApplier().BoundVertexElements);
|
||||
if (vaoTwin != nullptr) vaoTwin->AdoptUnchangedBufferSets(MG_Pipe::MGPipeApplier());
|
||||
// One program resolve and one texture-key capture serve the whole draw, for
|
||||
// the same reason the twin resolve does: only frontend GL entry points move
|
||||
// either, and none can run inside this preparation. GetProgramForDraw is a
|
||||
|
||||
@@ -5138,6 +5138,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
indexBufferSynced = true;
|
||||
}
|
||||
if (indexBufferSynced) {
|
||||
m_syncedIndexRes = st.IndexBuffer.Res;
|
||||
m_syncedIndexValid = true;
|
||||
// The two element-array restore scopes (the restart substitution's and
|
||||
// MultiDrawImpl's) put the DRIVER id back without touching this serial,
|
||||
// which is correct: the serial records what the APPLIER last said, and
|
||||
@@ -5151,6 +5153,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
m_syncedElementsSerial = rec->ContentSerial;
|
||||
m_syncedVertexBuffersSerial = st.VertexBuffersSerial;
|
||||
m_hasSyncedElements = true;
|
||||
// The window this walk emitted, for AdoptUnchangedBufferSets.
|
||||
m_syncedBufferStart = st.VertexBufferStart;
|
||||
m_syncedBufferCount = std::min<Uint32>(st.VertexBufferCount,
|
||||
MG_Pipe::kMGPipeMaxVertexAttribs - st.VertexBufferStart);
|
||||
m_syncedBufferBaseInstance = st.VertexFetchBaseInstance;
|
||||
for (Uint32 i = 0; i < m_syncedBufferCount; ++i)
|
||||
m_syncedBuffers[i] = st.VertexBuffers[m_syncedBufferStart + i];
|
||||
m_syncedBuffersValid = st.VertexBufferStart <= MG_Pipe::kMGPipeMaxVertexAttribs;
|
||||
m_syncedContextSerial = st.ContextSerial;
|
||||
}
|
||||
if (emitAttributes) {
|
||||
m_syncedFetchBaseInstance = fetchBaseInstance;
|
||||
@@ -5159,6 +5170,31 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
m_syncedBufferIdGeneration = currentBufferIdGeneration;
|
||||
}
|
||||
|
||||
void BackendVertexArrayObject::AdoptUnchangedBufferSets(const MG_Pipe::MGPipeApplierState& st) {
|
||||
if (!m_hasSyncedElements || m_syncedContextSerial != st.ContextSerial) return;
|
||||
if (m_syncedBuffersValid && m_syncedVertexBuffersSerial != st.VertexBuffersSerial &&
|
||||
st.VertexBufferStart == m_syncedBufferStart && st.VertexFetchBaseInstance == m_syncedBufferBaseInstance &&
|
||||
std::min<Uint32>(st.VertexBufferCount, MG_Pipe::kMGPipeMaxVertexAttribs - st.VertexBufferStart) ==
|
||||
m_syncedBufferCount) {
|
||||
Bool same = true;
|
||||
for (Uint32 i = 0; same && i < m_syncedBufferCount; ++i) {
|
||||
const auto& a = m_syncedBuffers[i];
|
||||
const auto& b = st.VertexBuffers[m_syncedBufferStart + i];
|
||||
same = a.Res == b.Res && a.Offset == b.Offset && a.Stride == b.Stride &&
|
||||
a.Divisor == b.Divisor && a.BindingIndex == b.BindingIndex;
|
||||
}
|
||||
if (same) {
|
||||
if (m_resolvedDrawBuffers.valid && m_resolvedDrawBuffers.buffersSerial == m_syncedVertexBuffersSerial)
|
||||
m_resolvedDrawBuffers.buffersSerial = st.VertexBuffersSerial;
|
||||
m_syncedVertexBuffersSerial = st.VertexBuffersSerial;
|
||||
}
|
||||
}
|
||||
if (m_syncedIndexValid && m_syncedIndexSerial != st.IndexBufferSerial && m_syncedIndexRes == st.IndexBuffer.Res) {
|
||||
if (m_resolvedDrawBuffers.iboSerial == m_syncedIndexSerial) m_resolvedDrawBuffers.iboSerial = st.IndexBufferSerial;
|
||||
m_syncedIndexSerial = st.IndexBufferSerial;
|
||||
}
|
||||
}
|
||||
|
||||
void BackendVertexArrayObject::SyncClientSideAttributesForDrawArrays(
|
||||
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count,
|
||||
Uint32 fetchBaseInstance) {
|
||||
@@ -5166,8 +5202,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return;
|
||||
}
|
||||
// This rewrites the driver VAO's arrays behind SyncToBackendFromApplier's gate, so
|
||||
// the next sync must not take its buffers-only walk.
|
||||
// the next sync must not take its buffers-only walk, nor adopt an equal buffer set.
|
||||
m_lastWalkWasPlain = false;
|
||||
m_syncedBuffersValid = false;
|
||||
|
||||
Bind();
|
||||
|
||||
|
||||
@@ -1181,6 +1181,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// overload, not defaulted to null") is what this obeys. The body is unchanged and
|
||||
// was already record-only - it is this family's existence proof (scout S1 §2).
|
||||
void SyncToBackendFromApplier();
|
||||
// P14: the applier's buffer-set serials move whenever ANY VAO's set is published, so
|
||||
// switching between two VAOs moves them although neither twin's buffers changed. Called
|
||||
// before the draw's syncs: when the window this twin last emitted is the applier's
|
||||
// window value for value, take the new serials as already synced (and carry the
|
||||
// resolved-buffers memo along) instead of re-emitting a driver VAO that already holds
|
||||
// exactly that. Only within the applier context the twin last synced against.
|
||||
void AdoptUnchangedBufferSets(const MG_Pipe::MGPipeApplierState& st);
|
||||
void SyncClientSideAttributesForDrawArrays(
|
||||
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count,
|
||||
Uint32 fetchBaseInstance = 0);
|
||||
@@ -1396,6 +1403,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// path, so the driver VAO's enable flags are exactly the configuration's and a walk
|
||||
// for a moved buffer set alone may skip them (SyncToBackendFromApplier).
|
||||
Bool m_lastWalkWasPlain = false;
|
||||
// P14: the vertex-buffer window and element buffer as last emitted into the driver
|
||||
// VAO, for AdoptUnchangedBufferSets. Handles are {slot, gen}, never reused.
|
||||
Array<MG_Pipe::MGPVertexBuffer, MG_Pipe::kMGPipeMaxVertexAttribs> m_syncedBuffers{};
|
||||
Uint32 m_syncedBufferStart = 0, m_syncedBufferCount = 0, m_syncedBufferBaseInstance = 0;
|
||||
Bool m_syncedBuffersValid = false;
|
||||
MG_Pipe::MGPipeHandle m_syncedIndexRes = MG_Pipe::kMGPipeNullHandle;
|
||||
Bool m_syncedIndexValid = false;
|
||||
Uint64 m_syncedContextSerial = 0;
|
||||
};
|
||||
|
||||
extern TwinRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject, MG_Pipe::MGPipeKind::VertexElementsCso>
|
||||
|
||||
Reference in New Issue
Block a user