[MG_Backend] (DirectGLES): the client snapshot's baseInstance shift is the emulated one

The element set a divisor'd client array fetches starts at GL's raw
baseInstance, but the pointer shift that carries it belongs to this backend's
emulation: when the driver applies baseInstance itself (UseNativeBaseInstance),
EmulatedFetchBaseInstance answers 0 and shifting the pointer as well would move
the fetch twice - instance 0 read element 2 instead of element 1, and the
instance that used element 1 read past the snapshot and vanished.

Also drops the two 'continue' statements the indirect executors' lambdas cannot
carry (a lambda is not a loop; 'return' leaves the pass).
This commit is contained in:
2026-09-20 20:50:11 -04:00
parent 62bfe4615d
commit ae418e80a0
@@ -2504,7 +2504,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Pipe::MGPipeClientFetchPlan plan;
if (!plan.Build(inputs, &ReadClientSnapshotBytes, &sources)) return false;
return twin->SyncClientSideAttributesForDraw(currentVAO, plan, baseInstance);
// The element SET is GL's: a divisor'd array's instance elements start at the raw
// baseInstance. The POINTER shift is not - it is this backend's emulation of what the
// driver does natively when it can (EmulatedFetchBaseInstance is the same answer the
// attribute walk uses), and applying both would shift the fetch twice.
return twin->SyncClientSideAttributesForDraw(currentVAO, plan, EmulatedFetchBaseInstance(baseInstance));
}
// The indirect executors' form: the command's own words ARE the draw's fetch, and a
@@ -8436,7 +8440,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
ForEachViewportRoutingPass([&] {
if (!VertexArrayImpl::SyncClientSideVertexArraysForIndirectFetch(
commandBytes, commandOffset, stride, i, static_cast<Uint8>(indexSize), drawIndirectBuffer))
continue;
return;
g_GLESFuncs.glDrawElementsInstancedBaseVertex(
mode, static_cast<GLsizei>(cmd.count), type, reinterpret_cast<const GLvoid*>(indexByteOffset),
static_cast<GLsizei>(cmd.instanceCount), cmd.baseVertex);
@@ -8518,7 +8522,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
ForEachViewportRoutingPass([&] {
if (!VertexArrayImpl::SyncClientSideVertexArraysForIndirectFetch(
commandBytes, commandOffset, stride, i, 0, drawIndirectBuffer))
continue;
return;
g_GLESFuncs.glDrawArraysInstanced(mode, static_cast<GLint>(cmd.first),
static_cast<GLsizei>(cmd.count),
static_cast<GLsizei>(cmd.instanceCount));