diff --git a/.circleci/config.yml b/.circleci/config.yml index 101cc88b34970..a32fb2718b2ee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -786,6 +786,7 @@ jobs: browser64.test_emscripten_async_wget_* browser64.test_wasm_worker_* browser64.test_sdl_* + browser64.test_sdl1_* browser64.test_egl* browser64.test_gl_* browser64.test_glgears* @@ -793,6 +794,7 @@ jobs: browser64.test_glew browser64.test_idbstore* browser64.test_fs_idbfs* + browser64.test_webgl* " test-browser-firefox: executor: bionic diff --git a/src/library_pthread.js b/src/library_pthread.js index 764465fef1eb1..0f2d08f80a348 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -143,7 +143,7 @@ var LibraryPThread = { #if PTHREADS_PROFILING getThreadName(pthreadPtr) { - var profilerBlock = {{{ makeGetValue('pthreadPtr', C_STRUCTS.pthread.profilerBlock, POINTER_TYPE) }}}; + var profilerBlock = {{{ makeGetValue('pthreadPtr', C_STRUCTS.pthread.profilerBlock, '*') }}}; if (!profilerBlock) return ""; return UTF8ToString(profilerBlock + {{{ C_STRUCTS.thread_profiler_block.name }}}); }, @@ -162,7 +162,7 @@ var LibraryPThread = { }, threadStatusAsString(pthreadPtr) { - var profilerBlock = {{{ makeGetValue('pthreadPtr', C_STRUCTS.pthread.profilerBlock, POINTER_TYPE) }}}; + var profilerBlock = {{{ makeGetValue('pthreadPtr', C_STRUCTS.pthread.profilerBlock, '*') }}}; var status = (profilerBlock == 0) ? 0 : Atomics.load(HEAPU32, {{{ getHeapOffset('profilerBlock + ' + C_STRUCTS.thread_profiler_block.threadStatus, 'i32') }}}); return PThread.threadStatusToString(status); }, @@ -761,7 +761,7 @@ var LibraryPThread = { // Deduce which WebGL canvases (HTMLCanvasElements or OffscreenCanvases) should be passed over to the // Worker that hosts the spawned pthread. // Comma-delimited list of CSS selectors that must identify canvases by IDs: "#canvas1, #canvas2, ..." - var transferredCanvasNames = attr ? {{{ makeGetValue('attr', C_STRUCTS.pthread_attr_t._a_transferredcanvases, POINTER_TYPE) }}} : 0; + var transferredCanvasNames = attr ? {{{ makeGetValue('attr', C_STRUCTS.pthread_attr_t._a_transferredcanvases, '*') }}} : 0; #if OFFSCREENCANVASES_TO_PTHREAD // Proxied canvases string pointer -1 is used as a special token to fetch // whatever canvases were passed to build in -s diff --git a/src/library_strings.js b/src/library_strings.js index 3e84803d258d5..0773172718ba9 100644 --- a/src/library_strings.js +++ b/src/library_strings.js @@ -116,7 +116,7 @@ addToLibrary({ #endif $UTF8ToString: (ptr, maxBytesToRead) => { #if ASSERTIONS - assert(typeof ptr == 'number'); + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); #endif #if CAN_ADDRESS_2GB ptr >>>= 0; @@ -158,7 +158,7 @@ addToLibrary({ outIdx >>>= 0; #endif #if ASSERTIONS - assert(typeof str === 'string'); + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); #endif // Parameter maxBytesToWrite is not optional. Negative values, 0, null, // undefined and false each don't write out any bytes. diff --git a/src/library_webgl.js b/src/library_webgl.js index 9a0b7b7a17b03..ed0d5612ec6ae 100644 --- a/src/library_webgl.js +++ b/src/library_webgl.js @@ -1168,7 +1168,7 @@ var LibraryGL = { #endif } #endif - ret = s && stringToNewUTF8(s); + ret = s ? stringToNewUTF8(s) : 0; break; #if GL_EMULATE_GLES_VERSION_STRING_FORMAT @@ -1783,7 +1783,7 @@ var LibraryGL = { }, // Queries EXT - glGenQueriesEXT__sig: 'vii', + glGenQueriesEXT__sig: 'vip', glGenQueriesEXT: (n, ids) => { for (var i = 0; i < n; i++) { var query = GLctx.disjointTimerQueryExt['createQueryEXT'](); @@ -1802,7 +1802,7 @@ var LibraryGL = { } }, - glDeleteQueriesEXT__sig: 'vii', + glDeleteQueriesEXT__sig: 'vip', glDeleteQueriesEXT: (n, ids) => { for (var i = 0; i < n; i++) { var id = {{{ makeGetValue('ids', 'i*4', 'i32') }}}; @@ -1844,7 +1844,7 @@ var LibraryGL = { GLctx.disjointTimerQueryExt['queryCounterEXT'](GL.queries[id], target); }, - glGetQueryivEXT__sig: 'viii', + glGetQueryivEXT__sig: 'viip', glGetQueryivEXT: (target, pname, params) => { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense @@ -1858,7 +1858,7 @@ var LibraryGL = { {{{ makeSetValue('params', '0', 'GLctx.disjointTimerQueryExt[\'getQueryEXT\'](target, pname)', 'i32') }}}; }, - glGetQueryObjectivEXT__sig: 'viii', + glGetQueryObjectivEXT__sig: 'viip', glGetQueryObjectivEXT: (id, pname, params) => { if (!params) { // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense @@ -1884,7 +1884,7 @@ var LibraryGL = { }, glGetQueryObjectuivEXT: 'glGetQueryObjectivEXT', - glGetQueryObjecti64vEXT__sig: 'viii', + glGetQueryObjecti64vEXT__sig: 'viip', glGetQueryObjecti64vEXT__deps: ['$writeI53ToI64'], glGetQueryObjecti64vEXT: (id, pname, params) => { if (!params) { @@ -3840,7 +3840,7 @@ var LibraryGL = { drawcount); }, - glMultiDrawArraysInstancedWEBGL__sig: 'viiiii', + glMultiDrawArraysInstancedWEBGL__sig: 'vipppi', glMultiDrawArraysInstancedANGLE: 'glMultiDrawArraysInstancedWEBGL', glMultiDrawArraysInstancedWEBGL: (mode, firsts, counts, instanceCounts, drawcount) => { GLctx.multiDrawWebgl['multiDrawArraysInstancedWEBGL']( @@ -3854,10 +3854,31 @@ var LibraryGL = { drawcount); }, +#if MEMORY64 + $convertOffsets__internal: true, + $convertOffsets: (offsets, count) => { + var offsets32 = stackAlloc(count * 4); + var i64ptr = offsets >> 3; + var i32ptr = offsets32 >> 2; + for (var i = 0; i < count; i++, i32ptr++, i64ptr++) { + var i64val = HEAPU64[i64ptr]; + assert(i64val >= 0 && i32ptr <= 0xffffffff); + HEAPU32[i32ptr] = Number(i64val); + } + return offsets32; + }, +#endif + glMultiDrawElementsWEBGL__sig: 'vipipi', glMultiDrawElements: 'glMultiDrawElementsWEBGL', glMultiDrawElementsANGLE: 'glMultiDrawElementsWEBGL', + glMultiDrawElementsWEBGL__deps: ['$convertOffsets'], glMultiDrawElementsWEBGL: (mode, counts, type, offsets, drawcount) => { +#if MEMORY64 + var stack = stackSave(); + offsets = convertOffsets(offsets, drawcount); +#endif + console.error(mode, counts, type, offsets, drawcount) GLctx.multiDrawWebgl['multiDrawElementsWEBGL']( mode, HEAP32, @@ -3866,11 +3887,19 @@ var LibraryGL = { HEAP32, offsets >> 2, drawcount); +#if MEMORY64 + stackRestore(stack); +#endif }, - glMultiDrawElementsInstancedWEBGL__sig: 'viiiiii', + glMultiDrawElementsInstancedWEBGL__sig: 'vipippi', glMultiDrawElementsInstancedANGLE: 'glMultiDrawElementsInstancedWEBGL', + glMultiDrawElementsInstancedWEBGL__deps: ['$convertOffsets'], glMultiDrawElementsInstancedWEBGL: (mode, counts, type, offsets, instanceCounts, drawcount) => { +#if MEMORY64 + var stack = stackSave(); + offsets = convertOffsets(offsets, drawcount); +#endif GLctx.multiDrawWebgl['multiDrawElementsInstancedWEBGL']( mode, HEAP32, @@ -3881,6 +3910,9 @@ var LibraryGL = { HEAP32, instanceCounts >> 2, drawcount); +#if MEMORY64 + stackRestore(stack); +#endif }, // As a small peculiarity, we currently allow building with -sFULL_ES3 to emulate client side arrays, diff --git a/test/test_browser.py b/test/test_browser.py index 1454e7a82eef0..b18972f145169 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -1286,6 +1286,7 @@ def test_glfw_joystick(self): self.btest_exit('test_glfw_joystick.c', args=['-O2', '--minify=0', '-o', 'page.html', '--pre-js', 'pre.js', '-lGL', '-lglfw3', '-sUSE_GLFW=3']) @requires_graphics_hardware + def test_webgl_context_attributes(self): # Javascript code to check the attributes support we want to test in the WebGL implementation # (request the attribute, create a context and check its value afterwards in the context attributes). @@ -1330,7 +1331,8 @@ def test_webgl_context_attributes(self): # perform tests with attributes activated self.btest_exit('test_webgl_context_attributes_glut.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglut', '-lGLEW']) self.btest_exit('test_webgl_context_attributes_sdl.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lSDL', '-lGLEW']) - self.btest_exit('test_webgl_context_attributes_sdl2.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-sUSE_SDL=2', '-lGLEW']) + if not self.is_wasm64(): + self.btest_exit('test_webgl_context_attributes_sdl2.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-sUSE_SDL=2', '-lGLEW']) self.btest_exit('test_webgl_context_attributes_glfw.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglfw', '-lGLEW']) # perform tests with attributes desactivated @@ -2749,14 +2751,15 @@ def test_webgl_unmasked_vendor_webgl(self): self.btest_exit('webgl_unmasked_vendor_webgl.c', args=['-lGL']) @requires_graphics_hardware - def test_webgl2(self): - for opts in [ - ['-sMIN_CHROME_VERSION=0', '-Wno-transpile'], - ['-O2', '-g1', '--closure=1', '-sWORKAROUND_OLD_WEBGL_UNIFORM_UPLOAD_IGNORED_OFFSET_BUG'], - ['-sFULL_ES2'], - ]: - print(opts) - self.btest_exit('webgl2.cpp', args=['-sMAX_WEBGL_VERSION=2', '-lGL'] + opts) + @parameterized({ + 'legacy_browser': (['-sMIN_CHROME_VERSION=0', '-Wno-transpile'],), + 'closure': (['-O2', '-g1', '--closure=1', '-sWORKAROUND_OLD_WEBGL_UNIFORM_UPLOAD_IGNORED_OFFSET_BUG'],), + 'full_es2': (['-sFULL_ES2'],), + }) + def test_webgl2(self, args): + if '-sMIN_CHROME_VERSION=0' in args and self.is_wasm64(): + self.skipTest('wasm64 not supported by legacy browsers') + self.btest_exit('webgl2.cpp', args=['-sMAX_WEBGL_VERSION=2', '-lGL'] + args) # Tests the WebGL 2 glGetBufferSubData() functionality. @requires_graphics_hardware @@ -4502,6 +4505,7 @@ def test_small_js_flags(self): @requires_threads @requires_offscreen_canvas @requires_graphics_hardware + @no_wasm64('TODO: wasm64 + OFFSCREENCANVAS') def test_webgl_offscreen_canvas_in_pthread(self, args): self.btest('gl_in_pthread.cpp', expected='1', args=args + ['-pthread', '-sPTHREAD_POOL_SIZE=2', '-sOFFSCREENCANVAS_SUPPORT', '-lGL']) @@ -4521,6 +4525,7 @@ def test_webgl_offscreen_canvas_in_mainthread_after_pthread(self, args): @requires_threads @requires_offscreen_canvas @requires_graphics_hardware + @no_wasm64('TODO: wasm64 + OFFSCREENCANVAS') def test_webgl_offscreen_canvas_only_in_pthread(self): self.btest_exit('gl_only_in_pthread.cpp', args=['-pthread', '-sPTHREAD_POOL_SIZE', '-sOFFSCREENCANVAS_SUPPORT', '-lGL', '-sOFFSCREEN_FRAMEBUFFER']) @@ -4533,15 +4538,16 @@ def test_webgl_from_client_side_memory_without_default_enabled_extensions(self): # For testing WebGL draft extensions like this, if using chrome as the browser, # We might want to append the --enable-webgl-draft-extensions to the EMTEST_BROWSER env arg. @requires_graphics_hardware - def test_webgl_multi_draw(self): - self.btest('webgl_multi_draw_test.c', reference='browser/webgl_multi_draw.png', - args=['-lGL', '-sOFFSCREEN_FRAMEBUFFER', '-DMULTI_DRAW_ARRAYS=1', '-DEXPLICIT_SWAP=1']) - self.btest('webgl_multi_draw_test.c', reference='browser/webgl_multi_draw.png', - args=['-lGL', '-sOFFSCREEN_FRAMEBUFFER', '-DMULTI_DRAW_ARRAYS_INSTANCED=1', '-DEXPLICIT_SWAP=1']) - self.btest('webgl_multi_draw_test.c', reference='browser/webgl_multi_draw.png', - args=['-lGL', '-sOFFSCREEN_FRAMEBUFFER', '-DMULTI_DRAW_ELEMENTS=1', '-DEXPLICIT_SWAP=1']) - self.btest('webgl_multi_draw_test.c', reference='browser/webgl_multi_draw.png', - args=['-lGL', '-sOFFSCREEN_FRAMEBUFFER', '-DMULTI_DRAW_ELEMENTS_INSTANCED=1', '-DEXPLICIT_SWAP=1']) + @parameterized({ + 'arrays': (['-DMULTI_DRAW_ARRAYS'],), + 'arrays_instanced': (['-DMULTI_DRAW_ARRAYS_INSTANCED'],), + 'elements': (['-DMULTI_DRAW_ELEMENTS'],), + 'elements_instanced': (['-DMULTI_DRAW_ELEMENTS_INSTANCED'],), + }) + def test_webgl_multi_draw(self, args): + self.btest('webgl_multi_draw_test.c', + reference='browser/webgl_multi_draw.png', + args=['-lGL', '-sOFFSCREEN_FRAMEBUFFER', '-DEXPLICIT_SWAP'] + args) # Tests for base_vertex/base_instance extension # For testing WebGL draft extensions like this, if using chrome as the browser, @@ -4580,6 +4586,7 @@ def test_webgl_timer_query(self, args): # Tests that -sOFFSCREEN_FRAMEBUFFER rendering works. @requires_graphics_hardware + @no_wasm64('TODO: wasm64 + OFB') def test_webgl_offscreen_framebuffer(self): # Tests all the different possible versions of libgl for threads in [[], ['-pthread', '-sPROXY_TO_PTHREAD']]: @@ -4632,6 +4639,7 @@ def test_webgl_array_of_structs_uniform(self): @requires_threads @requires_offscreen_canvas @requires_graphics_hardware + @no_wasm64('TODO: wasm64 + OFFSCREENCANVAS') def test_webgl_offscreen_canvas_in_proxied_pthread(self, asyncify): cmd = ['-pthread', '-sOFFSCREENCANVAS_SUPPORT', '-lGL', '-sGL_DEBUG', '-sPROXY_TO_PTHREAD'] if asyncify: @@ -4648,6 +4656,7 @@ def test_webgl_offscreen_canvas_in_proxied_pthread(self, asyncify): @requires_threads @requires_graphics_hardware @requires_offscreen_canvas + @no_wasm64('TODO: wasm64 + OFFSCREENCANVAS') def test_webgl_resize_offscreencanvas_from_main_thread(self, args): for args2 in [[], ['-DTEST_SYNC_BLOCKING_LOOP=1']]: for args3 in [[], ['-sOFFSCREENCANVAS_SUPPORT', '-sOFFSCREEN_FRAMEBUFFER']]: