mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 10:03:23 +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;
|
VertexArrayImpl::BackendVertexArrayObject* vaoTwin = nullptr;
|
||||||
Uint32 vaoConfigVersion = 0;
|
Uint32 vaoConfigVersion = 0;
|
||||||
vaoTwin = VertexArrayImpl::ResolveVaoTwin(MG_Pipe::MGPipeApplier().BoundVertexElements);
|
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
|
// 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
|
// the same reason the twin resolve does: only frontend GL entry points move
|
||||||
// either, and none can run inside this preparation. GetProgramForDraw is a
|
// either, and none can run inside this preparation. GetProgramForDraw is a
|
||||||
|
|||||||
@@ -5138,6 +5138,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
indexBufferSynced = true;
|
indexBufferSynced = true;
|
||||||
}
|
}
|
||||||
if (indexBufferSynced) {
|
if (indexBufferSynced) {
|
||||||
|
m_syncedIndexRes = st.IndexBuffer.Res;
|
||||||
|
m_syncedIndexValid = true;
|
||||||
// The two element-array restore scopes (the restart substitution's and
|
// The two element-array restore scopes (the restart substitution's and
|
||||||
// MultiDrawImpl's) put the DRIVER id back without touching this serial,
|
// MultiDrawImpl's) put the DRIVER id back without touching this serial,
|
||||||
// which is correct: the serial records what the APPLIER last said, and
|
// 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_syncedElementsSerial = rec->ContentSerial;
|
||||||
m_syncedVertexBuffersSerial = st.VertexBuffersSerial;
|
m_syncedVertexBuffersSerial = st.VertexBuffersSerial;
|
||||||
m_hasSyncedElements = true;
|
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) {
|
if (emitAttributes) {
|
||||||
m_syncedFetchBaseInstance = fetchBaseInstance;
|
m_syncedFetchBaseInstance = fetchBaseInstance;
|
||||||
@@ -5159,6 +5170,31 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
m_syncedBufferIdGeneration = currentBufferIdGeneration;
|
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(
|
void BackendVertexArrayObject::SyncClientSideAttributesForDrawArrays(
|
||||||
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count,
|
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count,
|
||||||
Uint32 fetchBaseInstance) {
|
Uint32 fetchBaseInstance) {
|
||||||
@@ -5166,8 +5202,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// This rewrites the driver VAO's arrays behind SyncToBackendFromApplier's gate, so
|
// 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_lastWalkWasPlain = false;
|
||||||
|
m_syncedBuffersValid = false;
|
||||||
|
|
||||||
Bind();
|
Bind();
|
||||||
|
|
||||||
|
|||||||
@@ -1181,6 +1181,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
// overload, not defaulted to null") is what this obeys. The body is unchanged and
|
// 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).
|
// was already record-only - it is this family's existence proof (scout S1 §2).
|
||||||
void SyncToBackendFromApplier();
|
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(
|
void SyncClientSideAttributesForDrawArrays(
|
||||||
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count,
|
const SharedPtr<MG_State::GLState::VertexArrayObject>& stateVAOObject, GLint first, GLsizei count,
|
||||||
Uint32 fetchBaseInstance = 0);
|
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
|
// 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).
|
// for a moved buffer set alone may skip them (SyncToBackendFromApplier).
|
||||||
Bool m_lastWalkWasPlain = false;
|
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>
|
extern TwinRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject, MG_Pipe::MGPipeKind::VertexElementsCso>
|
||||||
|
|||||||
Reference in New Issue
Block a user