-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 5.0.3 (285c424)
clang version 23.0.0git (https:/github.com/llvm/llvm-project e5927fecf8a6ce89e1a4eac5b828e7d42676452a)
Target: wasm32-unknown-emscripten
Thread model: posix
Minimal example to demonstrate the problem visually
https://gist.github.com/paradust7/cd6610b76939b9756b6ee561a929164d
Compile with:
emcc -g -O0 -s USE_SDL=2 -s FULL_ES2=1 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -o index.html minimal.c
And then serve with python3 -m http.server 8080 (or other).
Explanation
The problem originates from here:
emscripten/src/lib/libwebgl.js
Lines 3853 to 3908 in cb060ca
| glDrawElements: (mode, count, type, indices) => { | |
| #if FULL_ES2 | |
| var buf; | |
| var vertexes = 0; | |
| if (!GLctx.currentElementArrayBufferBinding) { | |
| var size = GL.calcBufLength(1, type, 0, count); | |
| buf = GL.getTempIndexBuffer(size); | |
| GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, buf); | |
| GLctx.bufferSubData(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, | |
| 0, | |
| HEAPU8.subarray(indices, indices + size)); | |
| // Calculating vertex count if shader's attribute data is on client side | |
| if (count > 0) { | |
| for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) { | |
| var cb = GL.currentContext.clientBuffers[i]; | |
| if (cb.clientside && cb.enabled) { | |
| let arrayClass; | |
| switch(type) { | |
| case 0x1401 /* GL_UNSIGNED_BYTE */: arrayClass = Uint8Array; break; | |
| case 0x1403 /* GL_UNSIGNED_SHORT */: arrayClass = Uint16Array; break; | |
| #if FULL_ES3 | |
| case 0x1405 /* GL_UNSIGNED_INT */: arrayClass = Uint32Array; break; | |
| #endif | |
| default: | |
| GL.recordError(0x502 /* GL_INVALID_OPERATION */); | |
| #if GL_ASSERTIONS | |
| err('type is not supported in glDrawElements'); | |
| #endif | |
| return; | |
| } | |
| vertexes = new arrayClass(HEAPU8.buffer, indices, count).reduce((max, current) => Math.max(max, current)) + 1; | |
| break; | |
| } | |
| } | |
| } | |
| // the index is now 0 | |
| indices = 0; | |
| } | |
| // bind any client-side buffers | |
| GL.preDrawHandleClientVertexAttribBindings(vertexes); | |
| #endif | |
| GLctx.drawElements(mode, count, type, indices); | |
| #if FULL_ES2 | |
| GL.postDrawHandleClientVertexAttribBindings(count); | |
| if (!GLctx.currentElementArrayBufferBinding) { | |
| GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null); | |
| } | |
| #endif | |
| }, |
When !currentElementArrayBufferBinding, "vertexes" (the maximum vertex count) is calculated using the indices data. Otherwise, vertexes is never calculated and remains 0, so vertex data is never copied.