Skip to content

Commit cea6b82

Browse files
authored
Fix glDrawElements emulation with FULL_ES2 (#22294)
This patch fixes an issue related to defining the buffer size before drawing. It introduces a slight overhead of O(buffersize), but is probably ok in practice, and is necessary for correctness. (Also, this only affects FULL_ES2, which is not on by default.)
1 parent c66e8cf commit cea6b82

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/library_webgl.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3803,19 +3803,47 @@ for (/**@suppress{duplicate}*/var i = 0; i <= {{{ GL_POOL_TEMP_BUFFERS_SIZE }}};
38033803
glDrawElements: (mode, count, type, indices) => {
38043804
#if FULL_ES2
38053805
var buf;
3806+
var vertexes = 0;
38063807
if (!GLctx.currentElementArrayBufferBinding) {
38073808
var size = GL.calcBufLength(1, type, 0, count);
38083809
buf = GL.getTempIndexBuffer(size);
38093810
GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, buf);
38103811
GLctx.bufferSubData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/,
38113812
0,
38123813
HEAPU8.subarray(indices, indices + size));
3814+
3815+
// Calculating vertex count if shader's attribute data is on client side
3816+
if (count > 0) {
3817+
for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
3818+
var cb = GL.currentContext.clientBuffers[i];
3819+
if (cb.clientside && cb.enabled) {
3820+
let arrayClass;
3821+
switch(type) {
3822+
case 0x1401 /* GL_UNSIGNED_BYTE */: arrayClass = Uint8Array; break;
3823+
case 0x1403 /* GL_UNSIGNED_SHORT */: arrayClass = Uint16Array; break;
3824+
#if FULL_ES3
3825+
case 0x1405 /* GL_UNSIGNED_INT */: arrayClass = Uint32Array; break;
3826+
#endif
3827+
default:
3828+
GL.recordError(0x502 /* GL_INVALID_OPERATION */);
3829+
#if GL_ASSERTIONS
3830+
err('type is not supported in glDrawElements');
3831+
#endif
3832+
return;
3833+
}
3834+
3835+
vertexes = new arrayClass(HEAPU8.buffer, indices, count).reduce((max, current) => Math.max(max, current)) + 1;
3836+
break;
3837+
}
3838+
}
3839+
}
3840+
38133841
// the index is now 0
38143842
indices = 0;
38153843
}
38163844

38173845
// bind any client-side buffers
3818-
GL.preDrawHandleClientVertexAttribBindings(count);
3846+
GL.preDrawHandleClientVertexAttribBindings(vertexes);
38193847
#endif
38203848

38213849
GLctx.drawElements(mode, count, type, indices);

test/third_party/cubegeom/cubegeom_pre_vao_es.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,19 @@ int main(int argc, char *argv[])
311311
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
312312
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
313313
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
314-
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
315314

316315
glBindVertexArray(0);
317316

318317
glDeleteVertexArrays(1, &vao);
319318

319+
// Validate glDrawElements when a client side vertex array is used.
320+
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, arrayData);
321+
glEnableVertexAttribArray(0);
322+
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, arrayData + 16);
323+
glEnableVertexAttribArray(1);
324+
325+
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, elementData + 18);
326+
320327
// END
321328

322329
SDL_GL_SwapBuffers();

0 commit comments

Comments
 (0)