diff --git a/src/library_webgl.js b/src/library_webgl.js index 0350f6236c435..57f05fdf847f5 100644 --- a/src/library_webgl.js +++ b/src/library_webgl.js @@ -1503,13 +1503,12 @@ var LibraryGL = { $emscriptenWebGLGetTexPixelData: function(type, format, width, height, pixels, internalFormat) { var heap = heapObjectForWebGLType(type); var shift = heapAccessShiftForWebGLHeap(heap); - var byteSize = 1<> shift) << shift == pixels, 'Pointer to texture data passed to texture get function must be aligned to the byte size of the pixel type!'); + assert({{{ isPtrAligned('pixels', '(1 << shift)') }}}, 'Pointer to texture data passed to texture get function must be aligned to the byte size of the pixel type!'); #endif - return heap.subarray(pixels >> shift, pixels + bytes >> shift); + return heap.subarray({{{ ptrToIdx('pixels', 'shift') }}}, {{{ ptrToIdx('pixels + bytes', 'shift') }}}); }, glTexImage2D__deps: ['$emscriptenWebGLGetTexPixelData' @@ -1543,7 +1542,7 @@ var LibraryGL = { GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); - GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); + GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, heap, {{{ idxToMemory53(ptrToIdx('pixels', 'heapAccessShiftForWebGLHeap(heap)')) }}}); } else { GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, null); } @@ -1574,7 +1573,7 @@ var LibraryGL = { GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); - GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); + GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, heap, {{{ idxToMemory53(ptrToIdx('pixels', 'heapAccessShiftForWebGLHeap(heap)')) }}}); } else { GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, null); } @@ -1598,7 +1597,7 @@ var LibraryGL = { GLctx.readPixels(x, y, width, height, format, type, pixels); } else { var heap = heapObjectForWebGLType(type); - GLctx.readPixels(x, y, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); + GLctx.readPixels(x, y, width, height, format, type, heap, {{{ idxToMemory53(ptrToIdx('pixels', 'heapAccessShiftForWebGLHeap(heap)')) }}}); } return; } @@ -2321,19 +2320,19 @@ var LibraryGL = { glUniform1iv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform1iv', 'location'); - assert((value & 3) == 0, 'Pointer to integer data passed to glUniform1iv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to integer data passed to glUniform1iv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, value>>2, count); + count && GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, value>>2, count); + count && GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count); return; } #endif @@ -2365,19 +2364,19 @@ var LibraryGL = { glUniform2iv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform2iv', 'location'); - assert((value & 3) == 0, 'Pointer to integer data passed to glUniform2iv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to integer data passed to glUniform2iv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, value>>2, count*2); + count && GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*2); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, value>>2, count*2); + count && GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*2); return; } #endif @@ -2410,19 +2409,19 @@ var LibraryGL = { glUniform3iv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform3iv', 'location'); - assert((value & 3) == 0, 'Pointer to integer data passed to glUniform3iv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to integer data passed to glUniform3iv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, value>>2, count*3); + count && GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*3); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, value>>2, count*3); + count && GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*3); return; } #endif @@ -2456,19 +2455,19 @@ var LibraryGL = { glUniform4iv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform4iv', 'location'); - assert((value & 3) == 0, 'Pointer to integer data passed to glUniform4iv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to integer data passed to glUniform4iv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, value>>2, count*4); + count && GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*4); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, value>>2, count*4); + count && GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*4); return; } #endif @@ -2503,19 +2502,19 @@ var LibraryGL = { glUniform1fv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform1fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniform1fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniform1fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, value>>2, count); + count && GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, value>>2, count); + count && GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count); return; } #endif @@ -2547,19 +2546,19 @@ var LibraryGL = { glUniform2fv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform2fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniform2fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniform2fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, value>>2, count*2); + count && GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*2); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, value>>2, count*2); + count && GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*2); return; } #endif @@ -2592,19 +2591,19 @@ var LibraryGL = { glUniform3fv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform3fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniform3fv must be aligned to four bytes!' + value); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniform3fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, value>>2, count*3); + count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*3); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, value>>2, count*3); + count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*3); return; } #endif @@ -2638,19 +2637,19 @@ var LibraryGL = { glUniform4fv: function(location, count, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform4fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniform4fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniform4fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, value>>2, count*4); + count && GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*4); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, value>>2, count*4); + count && GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*4); return; } #endif @@ -2659,15 +2658,14 @@ var LibraryGL = { if (count <= {{{ GL_POOL_TEMP_BUFFERS_SIZE / 4 }}}) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[4*count-1]; - // hoist the heap out of the loop for size and for pthreads+growth. + // hoist the heap out of the loop for pthreads+growth. var heap = HEAPF32; - value >>= 2; + {{{ convertPtrToIdx('value', 2) }}}; for (var i = 0; i < 4 * count; i += 4) { - var dst = value + i; - view[i] = heap[dst]; - view[i + 1] = heap[dst + 1]; - view[i + 2] = heap[dst + 2]; - view[i + 3] = heap[dst + 3]; + view[i] = heap[value++]; + view[i + 1] = heap[value++]; + view[i + 2] = heap[value++]; + view[i + 3] = heap[value++]; } } else #endif @@ -2689,19 +2687,19 @@ var LibraryGL = { glUniformMatrix2fv: function(location, count, transpose, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix2fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix2fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniformMatrix2fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*4); + count && GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*4); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*4); + count && GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*4); return; } #endif @@ -2736,19 +2734,19 @@ var LibraryGL = { glUniformMatrix3fv: function(location, count, transpose, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix3fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix3fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniformMatrix3fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*9); + count && GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*9); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*9); + count && GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*9); return; } #endif @@ -2788,19 +2786,19 @@ var LibraryGL = { glUniformMatrix4fv: function(location, count, transpose, value) { #if GL_ASSERTIONS GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix4fv', 'location'); - assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix4fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('value', 4) }}}, 'Pointer to float data passed to glUniformMatrix4fv must be aligned to four bytes!'); #endif #if MIN_WEBGL_VERSION >= 2 #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif - count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*16); + count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*16); #else #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. - count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*16); + count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ idxToMemory53(ptrToIdx('value', 2)) }}}, count*16); return; } #endif @@ -2809,27 +2807,26 @@ var LibraryGL = { if (count <= {{{ GL_POOL_TEMP_BUFFERS_SIZE / 16 }}}) { // avoid allocation when uploading few enough uniforms var view = miniTempWebGLFloatBuffers[16*count-1]; - // hoist the heap out of the loop for size and for pthreads+growth. + // hoist the heap out of the loop for pthreads+growth. var heap = HEAPF32; - value >>= 2; + {{{ convertPtrToIdx('value', 2) }}}; for (var i = 0; i < 16 * count; i += 16) { - var dst = value + i; - view[i] = heap[dst]; - view[i + 1] = heap[dst + 1]; - view[i + 2] = heap[dst + 2]; - view[i + 3] = heap[dst + 3]; - view[i + 4] = heap[dst + 4]; - view[i + 5] = heap[dst + 5]; - view[i + 6] = heap[dst + 6]; - view[i + 7] = heap[dst + 7]; - view[i + 8] = heap[dst + 8]; - view[i + 9] = heap[dst + 9]; - view[i + 10] = heap[dst + 10]; - view[i + 11] = heap[dst + 11]; - view[i + 12] = heap[dst + 12]; - view[i + 13] = heap[dst + 13]; - view[i + 14] = heap[dst + 14]; - view[i + 15] = heap[dst + 15]; + view[i] = heap[value++]; + view[i + 1] = heap[value++]; + view[i + 2] = heap[value++]; + view[i + 3] = heap[value++]; + view[i + 4] = heap[value++]; + view[i + 5] = heap[value++]; + view[i + 6] = heap[value++]; + view[i + 7] = heap[value++]; + view[i + 8] = heap[value++]; + view[i + 9] = heap[value++]; + view[i + 10] = heap[value++]; + view[i + 11] = heap[value++]; + view[i + 12] = heap[value++]; + view[i + 13] = heap[value++]; + view[i + 14] = heap[value++]; + view[i + 15] = heap[value++]; } } else #endif @@ -2878,38 +2875,40 @@ var LibraryGL = { glVertexAttrib1fv: function(index, v) { #if GL_ASSERTIONS - assert((v & 3) == 0, 'Pointer to float data passed to glVertexAttrib1fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('v', 4) }}}, 'Pointer to float data passed to glVertexAttrib1fv must be aligned to four bytes!'); assert(v != 0, 'Null pointer passed to glVertexAttrib1fv!'); #endif - GLctx.vertexAttrib1f(index, HEAPF32[v>>2]); + GLctx.vertexAttrib1f(index, HEAPF32[{{{ ptrToIdx('v', 2) }}}]); }, glVertexAttrib2fv: function(index, v) { #if GL_ASSERTIONS - assert((v & 3) == 0, 'Pointer to float data passed to glVertexAttrib2fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('v', 4) }}}, 'Pointer to float data passed to glVertexAttrib2fv must be aligned to four bytes!'); assert(v != 0, 'Null pointer passed to glVertexAttrib2fv!'); #endif - GLctx.vertexAttrib2f(index, HEAPF32[v>>2], HEAPF32[v+4>>2]); + {{{ convertPtrToIdx('v', 2) }}}; + GLctx.vertexAttrib2f(index, HEAPF32[v++], HEAPF32[v]); }, glVertexAttrib3fv: function(index, v) { #if GL_ASSERTIONS - assert((v & 3) == 0, 'Pointer to float data passed to glVertexAttrib3fv must be aligned to four bytes!'); + assert({{{ isPtrAligned('v', 4) }}}, 'Pointer to float data passed to glVertexAttrib3fv must be aligned to four bytes!'); assert(v != 0, 'Null pointer passed to glVertexAttrib3fv!'); #endif - GLctx.vertexAttrib3f(index, HEAPF32[v>>2], HEAPF32[v+4>>2], HEAPF32[v+8>>2]); + {{{ convertPtrToIdx('v', 2) }}}; + GLctx.vertexAttrib3f(index, HEAPF32[v++], HEAPF32[v++], HEAPF32[v]); }, glVertexAttrib4fv: function(index, v) { #if GL_ASSERTIONS - assert((v & 3) == 0, 'Pointer to float data passed to glVertexAttrib4fv must be aligned to four bytes!'); assert(v != 0, 'Null pointer passed to glVertexAttrib4fv!'); #endif - GLctx.vertexAttrib4f(index, HEAPF32[v>>2], HEAPF32[v+4>>2], HEAPF32[v+8>>2], HEAPF32[v+12>>2]); + {{{ convertPtrToIdx('v', 2) }}}; + GLctx.vertexAttrib4f(index, HEAPF32[v++], HEAPF32[v++], HEAPF32[v++], HEAPF32[v]); }, glGetAttribLocation: function(program, name) { @@ -3847,9 +3846,9 @@ var LibraryGL = { GLctx.multiDrawWebgl['multiDrawArraysWEBGL']( mode, HEAP32, - firsts >> 2, + {{{ idxToMemory53(ptrToIdx('firsts', 2)) }}}, HEAP32, - counts >> 2, + {{{ idxToMemory53(ptrToIdx('counts', 2)) }}}, drawcount); }, @@ -3859,11 +3858,11 @@ var LibraryGL = { GLctx.multiDrawWebgl['multiDrawArraysInstancedWEBGL']( mode, HEAP32, - firsts >> 2, + {{{ idxToMemory53(ptrToIdx('firsts', 2)) }}}, HEAP32, - counts >> 2, + {{{ idxToMemory53(ptrToIdx('counts', 2)) }}}, HEAP32, - instanceCounts >> 2, + {{{ idxToMemory53(ptrToIdx('instanceCounts', 2)) }}}, drawcount); }, @@ -3874,10 +3873,10 @@ var LibraryGL = { GLctx.multiDrawWebgl['multiDrawElementsWEBGL']( mode, HEAP32, - counts >> 2, + {{{ idxToMemory53(ptrToIdx('counts', 2)) }}}, type, HEAP32, - offsets >> 2, + {{{ idxToMemory53(ptrToIdx('offsets', 2)) }}}, drawcount); }, @@ -3887,12 +3886,12 @@ var LibraryGL = { GLctx.multiDrawWebgl['multiDrawElementsInstancedWEBGL']( mode, HEAP32, - counts >> 2, + {{{ idxToMemory53(ptrToIdx('counts', 2)) }}}, type, HEAP32, - offsets >> 2, + {{{ idxToMemory53(ptrToIdx('offsets', 2)) }}}, HEAP32, - instanceCounts >> 2, + {{{ idxToMemory53(ptrToIdx('instanceCounts', 2)) }}}, drawcount); }, diff --git a/src/library_webgl2.js b/src/library_webgl2.js index 060393a1c7d72..4ba0106d887c0 100644 --- a/src/library_webgl2.js +++ b/src/library_webgl2.js @@ -158,7 +158,7 @@ var LibraryWebGL2 = { GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); - GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); + GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, heap, {{{ ptrToIdx('pixels', 'heapAccessShiftForWebGLHeap(heap)') }}}); } else { GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, null); } @@ -170,7 +170,7 @@ var LibraryWebGL2 = { GLctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); - GLctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap)); + GLctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, heap, {{{ ptrToIdx('pixels', 'heapAccessShiftForWebGLHeap(heap)') }}}); } else { GLctx.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, null); } @@ -634,7 +634,7 @@ var LibraryWebGL2 = { assert((value & 3) == 0, 'Pointer to integer data passed to glClearBufferiv must be aligned to four bytes!'); #endif - GLctx.clearBufferiv(buffer, drawbuffer, HEAP32, value>>2); + GLctx.clearBufferiv(buffer, drawbuffer, HEAP32, {{{ ptrToIdx('value', 2) }}}); }, glClearBufferuiv: function(buffer, drawbuffer, value) { @@ -642,7 +642,7 @@ var LibraryWebGL2 = { assert((value & 3) == 0, 'Pointer to integer data passed to glClearBufferuiv must be aligned to four bytes!'); #endif - GLctx.clearBufferuiv(buffer, drawbuffer, HEAPU32, value>>2); + GLctx.clearBufferuiv(buffer, drawbuffer, HEAPU32, {{{ ptrToIdx('value', 2) }}}); }, glClearBufferfv: function(buffer, drawbuffer, value) { @@ -650,7 +650,7 @@ var LibraryWebGL2 = { assert((value & 3) == 0, 'Pointer to float data passed to glClearBufferfv must be aligned to four bytes!'); #endif - GLctx.clearBufferfv(buffer, drawbuffer, HEAPF32, value>>2); + GLctx.clearBufferfv(buffer, drawbuffer, HEAPF32, {{{ ptrToIdx('value', 2) }}}); }, glFenceSync: function(condition, flags) { @@ -791,7 +791,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform1uiv', 'location'); assert((value & 3) == 0, 'Pointer to integer data passed to glUniform1uiv must be aligned to four bytes!'); #endif - count && GLctx.uniform1uiv(webglGetUniformLocation(location), HEAPU32, value>>2, count); + count && GLctx.uniform1uiv(webglGetUniformLocation(location), HEAPU32, {{{ ptrToIdx('value', 2) }}}, count); }, glUniform2uiv__deps: ['$webglGetUniformLocation'], @@ -800,7 +800,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform2uiv', 'location'); assert((value & 3) == 0, 'Pointer to integer data passed to glUniform2uiv must be aligned to four bytes!'); #endif - count && GLctx.uniform2uiv(webglGetUniformLocation(location), HEAPU32, value>>2, count*2); + count && GLctx.uniform2uiv(webglGetUniformLocation(location), HEAPU32, {{{ ptrToIdx('value', 2) }}}, count*2); }, glUniform3uiv__deps: ['$webglGetUniformLocation'], @@ -809,7 +809,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform3uiv', 'location'); assert((value & 3) == 0, 'Pointer to integer data passed to glUniform3uiv must be aligned to four bytes!'); #endif - count && GLctx.uniform3uiv(webglGetUniformLocation(location), HEAPU32, value>>2, count*3); + count && GLctx.uniform3uiv(webglGetUniformLocation(location), HEAPU32, {{{ ptrToIdx('value', 2) }}}, count*3); }, glUniform4uiv__deps: ['$webglGetUniformLocation'], @@ -818,7 +818,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniform4uiv', 'location'); assert((value & 3) == 0, 'Pointer to integer data passed to glUniform4uiv must be aligned to four bytes!'); #endif - count && GLctx.uniform4uiv(webglGetUniformLocation(location), HEAPU32, value>>2, count*4); + count && GLctx.uniform4uiv(webglGetUniformLocation(location), HEAPU32, {{{ ptrToIdx('value', 2) }}}, count*4); }, glUniformMatrix2x3fv__deps: ['$webglGetUniformLocation'], @@ -827,7 +827,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix2x3fv', 'location'); assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix2x3fv must be aligned to four bytes!'); #endif - count && GLctx.uniformMatrix2x3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*6); + count && GLctx.uniformMatrix2x3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ ptrToIdx('value', 2) }}}, count*6); }, glUniformMatrix3x2fv__deps: ['$webglGetUniformLocation'], @@ -836,7 +836,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix3x2fv', 'location'); assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix3x2fv must be aligned to four bytes!'); #endif - count && GLctx.uniformMatrix3x2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*6); + count && GLctx.uniformMatrix3x2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ ptrToIdx('value', 2) }}}, count*6); }, glUniformMatrix2x4fv__deps: ['$webglGetUniformLocation'], @@ -845,7 +845,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix2x4fv', 'location'); assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix2x4fv must be aligned to four bytes!'); #endif - count && GLctx.uniformMatrix2x4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*8); + count && GLctx.uniformMatrix2x4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ ptrToIdx('value', 2) }}}, count*8); }, glUniformMatrix4x2fv__deps: ['$webglGetUniformLocation'], @@ -854,7 +854,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix4x2fv', 'location'); assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix4x2fv must be aligned to four bytes!'); #endif - count && GLctx.uniformMatrix4x2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*8); + count && GLctx.uniformMatrix4x2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ ptrToIdx('value', 2) }}}, count*8); }, glUniformMatrix3x4fv__deps: ['$webglGetUniformLocation'], @@ -863,7 +863,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix3x4fv', 'location'); assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix3x4fv must be aligned to four bytes!'); #endif - count && GLctx.uniformMatrix3x4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*12); + count && GLctx.uniformMatrix3x4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ ptrToIdx('value', 2) }}}, count*12); }, glUniformMatrix4x3fv__deps: ['$webglGetUniformLocation'], @@ -872,7 +872,7 @@ var LibraryWebGL2 = { GL.validateGLObjectID(GLctx.currentProgram.uniformLocsById, location, 'glUniformMatrix4x3fv', 'location'); assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix4x3fv must be aligned to four bytes!'); #endif - count && GLctx.uniformMatrix4x3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*12); + count && GLctx.uniformMatrix4x3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ ptrToIdx('value', 2) }}}, count*12); }, glVertexAttribI4iv: function(index, v) { @@ -880,7 +880,8 @@ var LibraryWebGL2 = { assert((v & 3) == 0, 'Pointer to integer data passed to glVertexAttribI4iv must be aligned to four bytes!'); assert(v != 0, 'Null pointer passed to glVertexAttribI4iv!'); #endif - GLctx.vertexAttribI4i(index, HEAP32[v>>2], HEAP32[v+4>>2], HEAP32[v+8>>2], HEAP32[v+12>>2]); + {{{ convertPtrToIdx('v', 2) }}} + GLctx.vertexAttribI4i(index, HEAP32[v++], HEAP32[v++], HEAP32[v++], HEAP32[v]); }, glVertexAttribI4uiv: function(index, v) { @@ -888,7 +889,8 @@ var LibraryWebGL2 = { assert((v & 3) == 0, 'Pointer to integer data passed to glVertexAttribI4uiv must be aligned to four bytes!'); assert(v != 0, 'Null pointer passed to glVertexAttribI4uiv!'); #endif - GLctx.vertexAttribI4ui(index, HEAPU32[v>>2], HEAPU32[v+4>>2], HEAPU32[v+8>>2], HEAPU32[v+12>>2]); + {{{ convertPtrToIdx('v', 2) }}} + GLctx.vertexAttribI4ui(index, HEAPU32[v++], HEAPU32[v++], HEAPU32[v++], HEAPU32[v]); }, glProgramParameteri: function(program, pname, value) { @@ -985,13 +987,13 @@ var LibraryWebGL2 = { GLctx.mdibvbi['multiDrawArraysInstancedBaseInstanceWEBGL']( mode, HEAP32, - firsts >> 2, + {{{ ptrToIdx('firsts', 2) }}}, HEAP32, - counts >> 2, + {{{ ptrToIdx('counts', 2) }}}, HEAP32, - instanceCounts >> 2, + {{{ ptrToIdx('instanceCounts', 2) }}}, HEAPU32, - baseInstances >> 2, + {{{ ptrToIdx('baseInstances', 2) }}}, drawCount); }, glMultiDrawArraysInstancedBaseInstanceANGLE: 'glMultiDrawArraysInstancedBaseInstanceWEBGL', @@ -1001,16 +1003,16 @@ var LibraryWebGL2 = { GLctx.mdibvbi['multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL']( mode, HEAP32, - counts >> 2, + {{{ ptrToIdx('counts', 2) }}}, type, HEAP32, - offsets >> 2, + {{{ ptrToIdx('offsets', 2) }}}, HEAP32, - instanceCounts >> 2, + {{{ ptrToIdx('instanceCounts', 2) }}}, HEAP32, - baseVertices >> 2, + {{{ ptrToIdx('baseVertices', 2) }}}, HEAPU32, - baseInstances >> 2, + {{{ ptrToIdx('baseInstances', 2) }}}, drawCount); }, glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE: 'glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL', diff --git a/src/parseTools.js b/src/parseTools.js index 715b7228a3f51..ddbf22b14cbfd 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -887,8 +887,59 @@ function from64(x) { } function to64(x) { - if (!MEMORY64) return x; - return `BigInt(${x})`; + if (MEMORY64) return /^\d+$/.test(x) ? `${x}n` : `BigInt(${x})`; + return x; +} + +// Generates an expression that tests whether a pointer (either a BigInt or a signed int32 JS Number) is aligned to the given byte multiple. +function isPtrAligned(ptr, alignment) { + if (MEMORY64) return /^\d+$/.test(alignment) ? `${ptr} % ${alignment}n == 0` : `${ptr} % BigInt(${alignment}) == 0`; + return `${ptr} % ${alignment} == 0`; +} + +const MAX_MEMORY53 = 2 ** 53; // == 9007199254740992 + +// Converts a pointer (either a BigInt or a signed int32 JS Number) in-place to an index on the heap (a BigInt or an unsigned JS Number). +// N.B. in ASSERTIONS mode may generate two statements (in form "a;b;"). +function convertPtrToIdx(ptr, accessWidth) { + const assertPointerAlignment = ASSERTIONS ? `${isPtrAligned(ptr, accessWidth)};` : ''; + + let conversion; + if (MEMORY64) { + // if our address space would ever get larger than 53 bits, we could do something like this: + // if (MAXIMUM_MEMORY > MAX_MEMORY53) conversion = /^\d+$/.test(accessWidth) ? `${ptr} >>= ${accessWidth}n` : `${ptr} >>= BigInt(${accessWidth})`; + assert(MAXIMUM_MEMORY <= MAX_MEMORY53); + conversion = `${ptr} = Number(${ptr}) / ${1 << accessWidth}`; + } else if (MAXIMUM_MEMORY > 2 * 1024 * 1024 * 1024) { + conversion = `${ptr} >>>= ${accessWidth}`; + } else { + conversion = accessWidth ? `${ptr} >>= ${accessWidth}` : ''; + } + + return assertPointerAlignment + conversion; +} + +// Returns a pointer (either a BigInt or a signed int32 JS Number) shifted to an index on the heap (a BigInt or an unsigned JS Number). +function ptrToIdx(ptr, accessWidth) { + if (MEMORY64) { + assert(MAXIMUM_MEMORY <= MAX_MEMORY53); + return `Number(${ptr}) / ${1 << accessWidth}`; + } + if (MAXIMUM_MEMORY > 2 * 1024 * 1024 * 1024) return `${ptr} >>> ${accessWidth}`; + return accessWidth ? `${ptr} >> ${accessWidth}` : ptr; +} + +// Converts a given JS Number (e.g. a pointer offset) to a heap index type (either a BigInt or a JS Number) +function createHeapIdx(number) { + if (MAXIMUM_MEMORY > MAX_MEMORY53) return /^-?\d+$/.test(number) ? `${number}n` : `BigInt(${number})`; + return number; +} + +// Browsers might not support passing BigInts to different API entry points that take in addresses, so convert those to Number()s before calling into the browser APIs. +function idxToMemory53(heapIndex) { + if (MAXIMUM_MEMORY <= MAX_MEMORY53) return heapIndex; // If not building with large 64-bit memory, heap indices will not be BigInts. + if (ASSERTIONS) return `BigInt(Number(${heapIndex})) == ${heapIndex} ? abort('Invalid pointer that does not fit in 53-bits address space!') : Number(${heapIndex})`; + return `Number(${heapIndex})`; } // Add assertions to catch common errors when using the Promise object we