RHI: Reset attribute instancing properly for OpenGL ES

Enabling instanced drawing will set glVertexAttribDivisor to 1 for the
PerInstance attributes. This is of course a persistent state, because
GL, so it will apply to all subsequent draw calls that uses attributes
with the same location number, introducing weird and wonderful randomness.

Therefore, make sure we set the divisor back to 0 for non-instanced attributes.

Change-Id: I2d9115369fa24e8d57396d2a5f88d1435fe98971
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Paul Olav Tvete 2020-11-23 12:50:48 +01:00
parent 5023c0beb5
commit 6493b93b48

View File

@ -2135,8 +2135,10 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
int binding = 0;
} lastBindVertexBuffer;
static const int TRACKED_ATTRIB_COUNT = 16;
bool enabledAttribArrays[TRACKED_ATTRIB_COUNT];
memset(enabledAttribArrays, 0, sizeof(enabledAttribArrays));
bool enabledAttribArrays[TRACKED_ATTRIB_COUNT] = {};
bool nonzeroAttribDivisor[TRACKED_ATTRIB_COUNT] = {};
bool instancedAttributesUsed = false;
int maxUntrackedInstancedAttribute = 0;
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
const QGles2CommandBuffer::Command &cmd(*it);
@ -2304,8 +2306,19 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
enabledAttribArrays[locationIdx] = true;
f->glEnableVertexAttribArray(GLuint(locationIdx));
}
if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing)
if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
f->glVertexAttribDivisor(GLuint(locationIdx), GLuint(inputBinding->instanceStepRate()));
if (Q_LIKELY(locationIdx < TRACKED_ATTRIB_COUNT))
nonzeroAttribDivisor[locationIdx] = true;
else
maxUntrackedInstancedAttribute = qMax(maxUntrackedInstancedAttribute, locationIdx);
instancedAttributesUsed = true;
} else if ((locationIdx < TRACKED_ATTRIB_COUNT && nonzeroAttribDivisor[locationIdx])
|| Q_UNLIKELY(locationIdx >= TRACKED_ATTRIB_COUNT && locationIdx <= maxUntrackedInstancedAttribute)) {
f->glVertexAttribDivisor(GLuint(locationIdx), 0);
if (locationIdx < TRACKED_ATTRIB_COUNT)
nonzeroAttribDivisor[locationIdx] = false;
}
}
} else {
qWarning("No graphics pipeline active for setVertexInput; ignored");
@ -2623,6 +2636,14 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
}
}
if (instancedAttributesUsed) {
for (int i = 0; i < TRACKED_ATTRIB_COUNT; ++i) {
if (nonzeroAttribDivisor[i])
f->glVertexAttribDivisor(GLuint(i), 0);
}
for (int i = TRACKED_ATTRIB_COUNT; i <= maxUntrackedInstancedAttribute; ++i)
f->glVertexAttribDivisor(GLuint(i), 0);
}
}
void QRhiGles2::executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD)