[Fix] (MG_Backend/DirectGLES): always use native indirect draws with a bound buffer

Adreno (830) exposes no GL_EXT_base_instance, and gating the native path
on it sent Flywheel's whole MDI call to the CPU loop, which reads the
stale shadow instanceCount (0) and draws nothing. A non-zero reserved
word is benign on mobile drivers, instanced arrays were never
baseInstance-offset in the emulation anyway, and the CPU loop can never
see GPU-written commands - native is strictly better.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 13:47:45 +00:00
co-authored by Claude Fable 5
parent 41b15955b0
commit 2395a6ded2
+9 -32
View File
@@ -1042,26 +1042,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
// execute natively on the GPU so commands written by compute shaders (e.g. Flywheel's
// culling pipeline updating instanceCount) are honored; the CPU shadow is still consulted
// for the per-command baseInstance, which is CPU-authored, to feed the mg_BaseInstance
// shader emulation. Falls back to the CPU per-command loop for client-memory commands or
// when the driver cannot consume the command's baseInstance field (no GL_EXT_base_instance).
// shader emulation. Without GL_EXT_base_instance a non-zero baseInstance in the command is
// technically undefined in ES; mobile drivers ignore the reserved word, instanced-array
// fetches were never baseInstance-offset here anyway, and the CPU fallback cannot see
// GPU-written command fields at all - so native is never worse. Only client-memory
// commands take the CPU per-command loop.
static void ExecuteIndexedIndirectCommands(GLenum mode, GLenum type, SizeT indexSize, const Uint8* commandBytes,
SizeT commandOffset, Bool hasIndirectBuffer, GLsizei drawcount,
GLsizei stride, const char* label) {
Bool useNative = hasIndirectBuffer && SupportsNativeIndirectDraws();
if (useNative && !g_GLESCapabilities.SupportsBaseInstance) {
for (GLsizei i = 0; i < drawcount; ++i) {
DrawElementsIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes + static_cast<SizeT>(i) * stride, sizeof(cmd));
if (cmd.baseInstance != 0) {
useNative = false;
MGLOG_W("%s: non-zero baseInstance without GL_EXT_base_instance, falling back to CPU "
"emulation (GPU-written command fields will not be honored)",
label);
break;
}
}
}
(void)label;
const Bool useNative = hasIndirectBuffer && SupportsNativeIndirectDraws();
if (useNative) {
for (GLsizei i = 0; i < drawcount; ++i) {
DrawElementsIndirectCommand cmd{};
@@ -1093,21 +1083,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
static void ExecuteArraysIndirectCommands(GLenum mode, const Uint8* commandBytes, SizeT commandOffset,
Bool hasIndirectBuffer, GLsizei drawcount, GLsizei stride,
const char* label) {
Bool useNative = hasIndirectBuffer && SupportsNativeIndirectDraws();
if (useNative && !g_GLESCapabilities.SupportsBaseInstance) {
for (GLsizei i = 0; i < drawcount; ++i) {
DrawArraysIndirectCommand cmd{};
std::memcpy(&cmd, commandBytes + static_cast<SizeT>(i) * stride, sizeof(cmd));
if (cmd.baseInstance != 0) {
useNative = false;
MGLOG_W("%s: non-zero baseInstance without GL_EXT_base_instance, falling back to CPU "
"emulation (GPU-written command fields will not be honored)",
label);
break;
}
}
}
(void)label;
const Bool useNative = hasIndirectBuffer && SupportsNativeIndirectDraws();
if (useNative) {
for (GLsizei i = 0; i < drawcount; ++i) {
DrawArraysIndirectCommand cmd{};