From 5fe50e6dac1140ea188c7f52e87cd2655a15d7ec Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 27 Feb 2024 15:58:43 -0800 Subject: [PATCH] Avoid garbage-free WebGL APIs when memory size is over 2gb. Both chrome and firefox see have some issues with passing 2gb+ and 4gb+ offsets to these APIs. Once the browser issues are addressed we can lift these restrictions over time. Fixes: #20533 --- src/library_webgl.js | 130 +++++++++++++++++---------------------- src/library_webgl2.js | 15 ++++- src/settings_internal.js | 6 ++ test/test_browser.py | 19 ++---- tools/link.py | 9 +++ 5 files changed, 93 insertions(+), 86 deletions(-) diff --git a/src/library_webgl.js b/src/library_webgl.js index a167584b09b26..3391ae583a93c 100644 --- a/src/library_webgl.js +++ b/src/library_webgl.js @@ -1518,14 +1518,14 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; glCompressedTexImage2D: (target, level, internalFormat, width, height, border, imageSize, data) => { #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. if (GLctx.currentPixelUnpackBufferBinding || !imageSize) { GLctx.compressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data); - } else { - GLctx.compressedTexImage2D(target, level, internalFormat, width, height, border, HEAPU8, data, imageSize); + return; } +#if WEBGL_USE_GARBAGE_FREE_APIS + GLctx.compressedTexImage2D(target, level, internalFormat, width, height, border, HEAPU8, data, imageSize); return; +#endif } #endif GLctx.compressedTexImage2D(target, level, internalFormat, width, height, border, data ? {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}} : null); @@ -1535,14 +1535,14 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; glCompressedTexSubImage2D: (target, level, xoffset, yoffset, width, height, format, imageSize, data) => { #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. if (GLctx.currentPixelUnpackBufferBinding || !imageSize) { GLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); - } else { - GLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, HEAPU8, data, imageSize); + return; } +#if WEBGL_USE_GARBAGE_FREE_APIS + GLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, HEAPU8, data, imageSize); return; +#endif } #endif GLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data ? {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}} : null); @@ -1637,20 +1637,21 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; } #endif if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. if (GLctx.currentPixelUnpackBufferBinding) { GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels); - } else if (pixels) { + return; + } +#if WEBGL_USE_GARBAGE_FREE_APIS + if (pixels) { var heap = heapObjectForWebGLType(type); GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, heap, toTypedArrayIndex(pixels, heap)); - } else { - GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, null); + return; } - return; +#endif } #endif - GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null); + var pixelData = pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null; + GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixelData); }, glTexSubImage2D__deps: ['$emscriptenWebGLGetTexPixelData' @@ -1670,15 +1671,17 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; } #endif if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. if (GLctx.currentPixelUnpackBufferBinding) { GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); - } else if (pixels) { + return; + } +#if WEBGL_USE_GARBAGE_FREE_APIS + if (pixels) { var heap = heapObjectForWebGLType(type); GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, heap, toTypedArrayIndex(pixels, heap)); return; } +#endif } #endif var pixelData = pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, 0) : null; @@ -1693,16 +1696,16 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; glReadPixels: (x, y, width, height, format, type, pixels) => { #if MAX_WEBGL_VERSION >= 2 if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. if (GLctx.currentPixelPackBufferBinding) { GLctx.readPixels(x, y, width, height, format, type, pixels); - } else { - var heap = heapObjectForWebGLType(type); - var target = toTypedArrayIndex(pixels, heap); - GLctx.readPixels(x, y, width, height, format, type, heap, target); + return; } +#if WEBGL_USE_GARBAGE_FREE_APIS + var heap = heapObjectForWebGLType(type); + var target = toTypedArrayIndex(pixels, heap); + GLctx.readPixels(x, y, width, height, format, type, heap, target); return; +#endif } #endif var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format); @@ -1839,14 +1842,12 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; } #endif -#if MAX_WEBGL_VERSION >= 2 +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. If size is zero, WebGL would interpret - // uploading the whole input arraybuffer (starting from given offset), - // which would not make sense in WebAssembly, so avoid uploading if size - // is zero. However we must still call bufferData to establish a backing - // storage of zero bytes. + // If size is zero, WebGL would interpret uploading the whole input + // arraybuffer (starting from given offset), which would not make sense in + // WebAssembly, so avoid uploading if size is zero. However we must still + // call bufferData to establish a backing storage of zero bytes. if (data && size) { GLctx.bufferData(target, HEAPU8, usage, data, size); } else { @@ -1863,10 +1864,8 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; }, glBufferSubData: (target, offset, size, data) => { -#if MAX_WEBGL_VERSION >= 2 +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. size && GLctx.bufferSubData(target, offset, HEAPU8, data, size); return; } @@ -2429,8 +2428,8 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, 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. +#if WEBGL_USE_GARBAGE_FREE_APIS + if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, count); return; } @@ -2470,8 +2469,8 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, 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. +#if WEBGL_USE_GARBAGE_FREE_APIS + if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, count*2); return; } @@ -2512,8 +2511,8 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, 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. +#if WEBGL_USE_GARBAGE_FREE_APIS + if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, count*3); return; } @@ -2555,9 +2554,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, count*4); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, {{{ getHeapOffset('value', 'i32') }}}, count*4); return; @@ -2601,8 +2598,8 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, 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. +#if WEBGL_USE_GARBAGE_FREE_APIS + if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count); return; } @@ -2642,9 +2639,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*2); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*2); return; @@ -2669,7 +2664,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; }, glUniform3fv__deps: ['$webglGetUniformLocation' -#if GL_POOL_TEMP_BUFFERS && MIN_WEBGL_VERSION == 1 +#if GL_POOL_TEMP_BUFFERS && !(MIN_WEBGL_VERSION >= 2 && WEBGL_USE_GARBAGE_FREE_APIS) , '$miniTempWebGLFloatBuffers' #endif ], @@ -2679,16 +2674,14 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; assert((value % 4) == 0, 'Pointer to float data passed to glUniform3fv must be aligned to four bytes!' + value); #endif -#if MIN_WEBGL_VERSION >= 2 +#if MIN_WEBGL_VERSION >= 2 && WEBGL_USE_GARBAGE_FREE_APIS #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*3); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*3); return; @@ -2731,9 +2724,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*4); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*4); return; @@ -2781,9 +2772,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*4); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniformMatrix2fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*4); return; @@ -2827,9 +2816,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; count && GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*9); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*9); return; @@ -2861,7 +2848,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; }, glUniformMatrix4fv__deps: ['$webglGetUniformLocation' -#if GL_POOL_TEMP_BUFFERS && MIN_WEBGL_VERSION == 1 +#if GL_POOL_TEMP_BUFFERS && !(MIN_WEBGL_VERSION >= 2 && WEBGL_USE_GARBAGE_FREE_APIS) , '$miniTempWebGLFloatBuffers' #endif ], @@ -2871,16 +2858,14 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; assert((value & 3) == 0, 'Pointer to float data passed to glUniformMatrix4fv must be aligned to four bytes!'); #endif -#if MIN_WEBGL_VERSION >= 2 +#if MIN_WEBGL_VERSION >= 2 && WEBGL_USE_GARBAGE_FREE_APIS #if GL_ASSERTIONS assert(GL.currentContext.version >= 2); #endif count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*16); #else -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 provides new garbage-free entry points to call to WebGL. Use - // those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS if ({{{ isCurrentContextWebGL2() }}}) { count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, {{{ getHeapOffset('value', 'float') }}}, count*16); return; @@ -2919,7 +2904,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; var view = {{{ makeHEAPView('F32', 'value', 'value+count*64') }}}; } GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view); -#endif // MIN_WEBGL_VERSION >= 2 +#endif // MIN_WEBGL_VERSION >= 2 && WEBGL_USE_GARBAGE_FREE_APIS }, glBindBuffer: (target, buffer) => { @@ -4155,11 +4140,12 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; } if (!(mapping.access & 0x10)) { /* GL_MAP_FLUSH_EXPLICIT_BIT */ - if ({{{ isCurrentContextWebGL2() }}}) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible. +#if WEBGL_USE_GARBAGE_FREE_APIS + if ({{{ isCurrentContextWebGL2() }}}) { GLctx.bufferSubData(target, mapping.offset, HEAPU8, mapping.mem, mapping.length); - } else { - GLctx.bufferSubData(target, mapping.offset, HEAPU8.subarray(mapping.mem, mapping.mem+mapping.length)); - } + } else +#endif + GLctx.bufferSubData(target, mapping.offset, HEAPU8.subarray(mapping.mem, mapping.mem+mapping.length)); } _free(mapping.mem); mapping.mem = 0; diff --git a/src/library_webgl2.js b/src/library_webgl2.js index 3285e7ce62918..a768c03c01754 100644 --- a/src/library_webgl2.js +++ b/src/library_webgl2.js @@ -118,7 +118,11 @@ var LibraryWebGL2 = { return; } #endif +#if WEBGL_USE_GARBAGE_FREE_APIS size && GLctx.getBufferSubData(target, offset, HEAPU8, data, size); +#else + size && GLctx.getBufferSubData(target, offset, HEAPU8.subarray(data, data+size)); +#endif }, glInvalidateFramebuffer__deps: ['$tempFixedLengthArray'], @@ -147,13 +151,22 @@ var LibraryWebGL2 = { GLctx.invalidateSubFramebuffer(target, list, x, y, width, height); }, - glTexImage3D__deps: ['$heapObjectForWebGLType', '$toTypedArrayIndex'], + glTexImage3D__deps: ['$heapObjectForWebGLType', '$toTypedArrayIndex', +#if !WEBGL_USE_GARBAGE_FREE_APIS + '$emscriptenWebGLGetTexPixelData', +#endif + ], glTexImage3D: (target, level, internalFormat, width, height, depth, border, format, type, pixels) => { if (GLctx.currentPixelUnpackBufferBinding) { GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels); } else if (pixels) { var heap = heapObjectForWebGLType(type); +#if WEBGL_USE_GARBAGE_FREE_APIS GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, heap, toTypedArrayIndex(pixels, heap)); +#else + var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height * depth, pixels, internalFormat); + GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixelData); +#endif } else { GLctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, null); } diff --git a/src/settings_internal.js b/src/settings_internal.js index c27582b27014c..b9fa48def260b 100644 --- a/src/settings_internal.js +++ b/src/settings_internal.js @@ -270,3 +270,9 @@ var MINIFY_WHITESPACE = true; var ASYNCIFY_IMPORTS_EXCEPT_JS_LIBS = []; var WARN_DEPRECATED = true; + +// WebGL 2 provides new garbage-free entry points to call to WebGL. Use +// those always when possible. +// We currently set this to false for memory sizes over 2GB due to browser +// bugs. +var WEBGL_USE_GARBAGE_FREE_APIS = false; diff --git a/test/test_browser.py b/test/test_browser.py index 40eb3a6e17ec0..82cb6ca0acd21 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -1318,7 +1318,6 @@ def test_webgl_parallel_shader_compile(self): self.btest_exit('webgl_parallel_shader_compile.cpp') @requires_graphics_hardware - @no_4gb('readPixels fails: https://crbug.com/324992397') def test_webgl_explicit_uniform_location(self): self.btest_exit('webgl_explicit_uniform_location.c', args=['-sGL_EXPLICIT_UNIFORM_LOCATION', '-sMIN_WEBGL_VERSION=2']) @@ -1327,7 +1326,6 @@ def test_webgl_sampler_layout_binding(self): self.btest_exit('webgl_sampler_layout_binding.c', args=['-sGL_EXPLICIT_UNIFORM_BINDING']) @requires_graphics_hardware - @no_4gb('readPixels fails: https://crbug.com/324992397') def test_webgl2_ubo_layout_binding(self): self.btest_exit('webgl2_ubo_layout_binding.c', args=['-sGL_EXPLICIT_UNIFORM_BINDING', '-sMIN_WEBGL_VERSION=2']) @@ -1529,7 +1527,6 @@ def test_sdl_gl_read(self): self.btest_exit('test_sdl_gl_read.c', args=['-lSDL', '-lGL']) @requires_graphics_hardware - @no_4gb('readPixels fails: https://crbug.com/324992397') def test_sdl_gl_mapbuffers(self): self.btest_exit('test_sdl_gl_mapbuffers.c', args=['-sFULL_ES3', '-lSDL', '-lGL']) @@ -2032,12 +2029,10 @@ def test_gl_stride(self): self.reftest('gl_stride.c', 'gl_stride.png', args=['-sGL_UNSAFE_OPTS=0', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL']) @requires_graphics_hardware - @no_4gb('assertion failure') def test_gl_vertex_buffer_pre(self): self.reftest('gl_vertex_buffer_pre.c', 'gl_vertex_buffer_pre.png', args=['-sGL_UNSAFE_OPTS=0', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL']) @requires_graphics_hardware - @no_4gb('assertion failure') def test_gl_vertex_buffer(self): self.reftest('gl_vertex_buffer.c', 'gl_vertex_buffer.png', args=['-sGL_UNSAFE_OPTS=0', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL'], reference_slack=1) @@ -2779,7 +2774,6 @@ def test_webgl2_pbo(self): @no_firefox('fails on CI likely due to GPU drivers there') @requires_graphics_hardware - @no_4gb('fails to render') def test_webgl2_sokol_mipmap(self): self.reftest('third_party/sokol/mipmap-emsc.c', 'third_party/sokol/mipmap-emsc.png', args=['-sMAX_WEBGL_VERSION=2', '-lGL', '-O1'], reference_slack=2) @@ -4487,12 +4481,13 @@ def test_small_js_flags(self): self.assertLess(abs(size - 4800), 100) # Tests that it is possible to initialize and render WebGL content in a - # pthread by using OffscreenCanvas. -DTEST_CHAINED_WEBGL_CONTEXT_PASSING: - # Tests that it is possible to transfer WebGL canvas in a chain from main - # thread -> thread 1 -> thread 2 and then init and render WebGL content there. - @no_chrome('see https://crbug.com/961765') + # pthread by using OffscreenCanvas. + @no_chrome('https://crbug.com/961765') @parameterized({ '': ([],), + # -DTEST_CHAINED_WEBGL_CONTEXT_PASSING: + # Tests that it is possible to transfer WebGL canvas in a chain from main + # thread -> thread 1 -> thread 2 and then init and render WebGL content there. 'chained': (['-DTEST_CHAINED_WEBGL_CONTEXT_PASSING'],), }) @requires_threads @@ -4563,7 +4558,6 @@ def test_webgl_draw_base_vertex_base_instance(self): '-DWEBGL_CONTEXT_VERSION=2']) @requires_graphics_hardware - @no_4gb('fails to render') def test_webgl_sample_query(self): self.btest_exit('webgl_sample_query.cpp', args=['-sMAX_WEBGL_VERSION=2', '-lGL']) @@ -4621,7 +4615,6 @@ def test_webgl_offscreen_framebuffer_state_restoration(self): # Tests that using an array of structs in GL uniforms works. @requires_graphics_hardware - @no_4gb('fails to render') def test_webgl_array_of_structs_uniform(self): self.reftest('webgl_array_of_structs_uniform.c', 'webgl_array_of_structs_uniform.png', args=['-lGL', '-sMAX_WEBGL_VERSION=2']) @@ -4688,7 +4681,7 @@ def test_webgl_simple_extensions(self, simple_enable_extensions, webgl_version): self.btest_exit('webgl2_simple_enable_extensions.c', args=cmd) @parameterized({ - 'default': ([],), + '': ([],), 'closure': (['-sASSERTIONS', '--closure=1'],), 'main_module': (['-sMAIN_MODULE=1'],), }) diff --git a/tools/link.py b/tools/link.py index 3c135be074e66..a546dbb0f336d 100644 --- a/tools/link.py +++ b/tools/link.py @@ -1611,6 +1611,15 @@ def check_memory_setting(setting): if not settings.MEMORY64 and settings.MAXIMUM_MEMORY > 2 * 1024 * 1024 * 1024: settings.CAN_ADDRESS_2GB = 1 + # Some browsers have issues using the WebGL2 garbage-free APIs when the + # memory offsets are over 2^31 or 2^32 + # For firefox see: https://bugzilla.mozilla.org/show_bug.cgi?id=1838218 + if settings.MIN_FIREFOX_VERSION != feature_matrix.UNSUPPORTED and settings.MAXIMUM_MEMORY > 2 ** 31: + settings.WEBGL_USE_GARBAGE_FREE_APIS = 0 + # For chrome see: https://crbug.com/324992397 + if settings.MIN_CHROME_VERSION != feature_matrix.UNSUPPORTED and settings.MEMORY64 and settings.MAXIMUM_MEMORY > 2 ** 32: + settings.WEBGL_USE_GARBAGE_FREE_APIS = 0 + if settings.MINIMAL_RUNTIME: if settings.EXIT_RUNTIME: settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['proc_exit', '$callRuntimeCallbacks']