Wednesday, March 9, 2022

Qt for WebAssembly on mobile devices

Qt for WebAssembly on mobile devices, specifically phones, has lacked an essential feature - support for the native keyboard. It may or may not have worked. If it worked, it did not work very well. The tricky issue is opening the keyboard when needed and closing when it wasn't. There is no simple API for doing that on any platform we target - iOS, Android and Windows.

Although it feels a bit hacky to me to open the keyboard using javascript , we use Emscripten's C++ interface to create a hidden javascript text input element and set focus to that, which opens the platform keyboard.

Emscripten on Android had one other issue - the usual Emscripten input event API was not working. Nothing being typed on the native virtual keyboard was being handled like on other platforms. I found I could utilize the hidden input element that is used to pop up the keyboard, to listen for input characters and then send them to Qt. 

As it is, this patch adds support for native mobile keyboard for iOS, Android and Windows on Qt for WebAssembly. (now merged into dev as 66a76a5def46d0e4a330f7130ad440c639b87cf7), too late to make it into 6.3.

Other issues on mobile are memory (as usual). Up until recently, Safari limits browser memory to much less than the other browsers. 

Other areas that Qt covers for mobile devices that do not work on Qt for WebAssembly yet are sensors and bluetooth connectivity. Although there is a patch for some sensors support, it has not been merged and probably needs updating. It may not work at all, either.

Bluetooth connectivity for javascript is currently only supported on the Chrome browser and is currently experimental. While I could probably add this support to Qt WebAssembly, it would not get merged and the API might be too changey.

Any areas you find Qt WebAssembly is lacking on mobile, please report to https://bugreports.qt.io/


Friday, January 7, 2022

Qt WebAssembly clipboard

Clipboard use on the desktop platforms is ubiquitous. Most people use it without thinking. Copy, Paste and Cut keyboard strokes are in-grained into muscle memory. 

On the web it can present security issues as someone could read or write to your clipboard without you knowing.

Up until now, Qt for WebAssembly's clipboard was text only and only within the app itself. Qt 6.3 will have better clipboard support between host and app but also adds copy/pasting of images.

WebAssembly is a sandboxed platform like javascript. There are some extra security hurdles in doing some common things such as copy and paste of binary data such as images. One issue is clipboard use between the host platform and the browser sandbox. Allowing the web app to have access to the clipboard in which it could send arbitrary data without the user knowing could be dangerous for the user.

Browsers generally allow clipboard during user generated events such as when a user makes common key sequences such as [ctrl | command] c - the copy keys.

Qt itself has support for programmatically copying text and binary data such as images and works great on the desktop, but which presents issues for web browsers. There are work-arounds, like using a hidden javascript element and the javascript function execCommand to "copy". However, this function has been depreciated. 

By using the asynchronous Clipboard API and making use of javascript clipboard events where possible, we can bring image clipboard support to Qt WebAssembly. The Clipboard API requires a secure context (https) for full feature use. Among other things, the Clipboard API allows image and arbitrary data to be copied and pasted. Whereas before, only text mime types were supported. 

This API is of course implemented in the different browsers in different ways. On Firefox, read() and write() are only partially implemented and is hidden behind about:config settings. As well, copy/paste of arbitrary binary data does not seem to be supported and mostly silently fails.

Here are the ways browsers support Clipboard API:

Firefox 

  • write() is available without permission in secure contexts and browser extensions, but only from user-initiated event callbacks.
  • Clipboard API
    • secure context (https or localhost)
    • dom.events.asyncClipboard
    • dom.events.asyncClipboard.clipboardItem
    • dom.events.asyncClipboard.read
    • dom.events.testing.asyncClipboard
Safari

  • Clipboard API
    • secure context    
Chrome
  • Clipboard API
    • secure context
    • user permissions
  • read() only supports
    • text/html
    • text/png

Also included in the now merged commit f0be152896471aa392bb1b2b649b66feb31480cc  is a clipboard manual test app that can be used on both desktop and webassembly to test clipbpoard use.

You can use the clipboard without a secure https context, but you won't get interaction between host and web app.

Wednesday, August 18, 2021

Qt Multimedia has a new friend...

 QtMultimedia just got a new platform to run on - Qt for WebAssembly!


I am happy to announce a new platform contribution for Qt Multimedia.

As of change https://codereview.qt-project.org/c/qt/qtmultimedia/+/348150 and very much thanks to Qt contributor, Raffaele Pertile, we now have audio play and record on the WebAssembly platform for Qt 6.2.

This is possible  as Emscripten has built-in support for OpenAL, which this patch uses to push audio data around. So now, all your Qt webAssembly apps can have sound effects! \0/

 

 

  

Monday, July 12, 2021

Qt WebAssembly: prompt on exit

 I sometimes get asked if there is a way to let a Qt app ask the user if they really want to close the app when the browser tab or window gets closed by the user.


The answer is yes and no. Yes, in that there is, and no in that it won't be your own Qt dialog/prompt.


We can use javascript in Qt webassembly apps, so the prompt will be opened by the browsers javascript. 


How?

There are two ways to run javascript. By using emscripten macro EM_ASM, or including emscripten/val.h and using straight c++.


EM_ASM:

The is the easiest way but uses a macro.


#include <emscripten.h>

Just add something like this, in your app constructor function:


    EM_ASM(
           window.onbeforeunload = function (e) {
                e = e || window.event;
                return 'Sure';
            };
    );


C++:

This is a bit more complicated, and involves a global static function.

#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <emscripten.h>

static emscripten::val mybrowserBeforeUnload(emscripten::val e)
{
   return emscripten::val("Sure");
}


EMSCRIPTEN_BINDINGS(app) // must be unique name!
{
    function("myBrowserBeforeUnload", &mybrowserBeforeUnload);
}

and in the c'tor:


 emscripten::val::global("window").set("onbeforeunload", emscripten::val::module_property("myBrowserBeforeUnload"));


The key is to return a string. Any string will do.

and it looks something like this:





Sunday, June 13, 2021

(redux) Qt WebAssembly performance enhancement

 In my last post Qt WebAssembly performance enhancement

there were some impressive performance stat speedups. Unfortunately, as my collegue Morten pointed out, both builds were in debug mode.  *sigh*

So I rebuilt them in release mode, and added a few selected benchmarks from the Qt tests/benchmark source directory:

  • tst_affectors
  • tst_emission
  • tst_QGraphicsScene
  • tst_QGraphicsView
  • tst_QGraphicsWidget
  • tst_qanimation
  • tst_QMatrix4x4
  • BlendBench
  • tst_QImageConversion
  • tst_DrawTexture
  • tst_QPainter

Although not as impressive overall, there is still quite a speed up in the image conversions and QPainter areas, for example:

non-simd:

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), circle)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), circle":

     2.3 msecs per iteration (total: 76, iterations: 32)

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), line)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), line":

     2.4 msecs per iteration (total: 77, iterations: 32)

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), solidrect)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), solidrect":

     2.4 msecs per iteration (total: 78, iterations: 32)

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), alpharect)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), alpharect":

     2.4 msecs per iteration (total: 78, iterations: 32)


simd:

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), circle":

     0.95 msecs per iteration (total: 61, iterations: 64)

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), line)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), line":

     0.95 msecs per iteration (total: 61, iterations: 64)

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), solidrect)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), solidrect":

     0.92 msecs per iteration (total: 59, iterations: 64)

PASS   : tst_QPainter::drawPixmap(BGR30 on RGB32, (1000x1000), alpharect)

RESULT : tst_QPainter::drawPixmap():"BGR30 on RGB32, (1000x1000), alpharect":

     0.95 msecs per iteration (total: 61, iterations: 64


non-simd:

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), circle)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), circle":

     1.7 msecs per iteration (total: 56, iterations: 32)

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), line)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), line":

     1.7 msecs per iteration (total: 55, iterations: 32)

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), solidrect)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), solidrect":

     1.7 msecs per iteration (total: 55, iterations: 32)

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), alpharect)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), alpharect":

     3.6 msecs per iteration (total: 58, iterations: 16)


simd:

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), circle)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), circle":

     2.6 msecs per iteration (total: 85, iterations: 32)

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), line)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), line":

     4.0 msecs per iteration (total: 64, iterations: 16)

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), solidrect)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), solidrect":

     2.2 msecs per iteration (total: 71, iterations: 32)

PASS   : tst_QPainter::drawPixmap(ARGB32_pm on RGB32, (1000x1000), alpharect)

RESULT : tst_QPainter::drawPixmap():"ARGB32_pm on RGB32, (1000x1000), alpharect":

     4.5 msecs per iteration (total: 73, iterations: 16)


and image conversions:

non-simd:

PASS   : tst_QImageConversion::convertGenericInplace(argb32 -> argb32pm -> argb32)

RESULT : tst_QImageConversion::convertGenericInplace():"argb32 -> argb32pm -> argb32":

     6.1 msecs per iteration (total: 98, iterations: 16)

PASS   : tst_QImageConversion::convertGenericInplace(argb32 -> rgb32 -> argb32)

RESULT : tst_QImageConversion::convertGenericInplace():"argb32 -> rgb32 -> argb32":

     2.9 msecs per iteration (total: 94, iterations: 32)

PASS   : tst_QImageConversion::convertGenericInplace(argb32 -> rgba8888 -> argb32)

RESULT : tst_QImageConversion::convertGenericInplace():"argb32 -> rgba8888 -> argb32":

     4.6 msecs per iteration (total: 75, iterations: 16)

simd:

PASS   : tst_QImageConversion::convertGenericInplace(argb32 -> argb32pm -> argb32)

RESULT : tst_QImageConversion::convertGenericInplace():"argb32 -> argb32pm -> argb32":

     4.2 msecs per iteration (total: 68, iterations: 16)

PASS   : tst_QImageConversion::convertGenericInplace(argb32 -> rgb32 -> argb32)

RESULT : tst_QImageConversion::convertGenericInplace():"argb32 -> rgb32 -> argb32":

     0.49 msecs per iteration (total: 63, iterations: 128)

PASS   : tst_QImageConversion::convertGenericInplace(argb32 -> rgba8888 -> argb32)

RESULT : tst_QImageConversion::convertGenericInplace():"argb32 -> rgba8888 -> argb32":

     0.90 msecs per iteration (total: 58, iterations: 64)



But others were slower for the simd build. Probably due to emscripten not fully supporting simd instructions and emulating those where it doesn't support.


For full benchmark results get the zip file




Thursday, June 10, 2021

Qt WebAssembly performance enhancement

SIMD is something related to performance stuff. It makes certain things go faster (simply put). Kind of like sticking laughing gas in your petrol car's fuel line.

https://en.wikipedia.org/wiki/SIMD

Emscripten, WebAssembly now have better support for SIMD (to various degrees)

https://emscripten.org/docs/porting/simd.html


Chrome and firefox also support SIMD (to various degrees)

So for Qt 6.3, I have been working to get Qt building and running using those SIMD instructions available for javascript (and thereby WebAssembly) in the web browsers (sorry, Safari.. catch up soon?)


Just configure soon to be qt 6.3 with the -sse2 argument (change has not been reviewed or merged yet)

https://codereview.qt-project.org/c/qt/qtbase/+/343563

To see if it is actually worth adding SIMD support to Qt WebAssembly, I built a couple Qt Quick benchmarks, namely the declarative particles benchmarks - affectors and emission.

I had to put image and qml files into a .qrc resource file so that Qt WebAssembly could find them, as we have no real local file system access.


The results are much better than I expected. Clearly, there is a performance boost by using simd in wasm. 

 Someone else has had similar results with wasm SIMD

https://robaboukhalil.medium.com/webassembly-and-simd-7a7daa4f2ecd

 

Next I want to expand the number and type of benchmarks, but this gives us early baseline results.

Chrome browser
no SIMD:

********* Start testing of tst_affectors *********
Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5852582532b3eb3ea8da51a1e272d8d017bd36c9)), unknown unknown
PASS   : tst_affectors::initTestCase()
Heap resize call from 16777216 to 20185088 took 0.09999999403953552 msecs. Success: true
Heap resize call from 20185088 to 24248320 took 0.10000000894069672 msecs. Success: true
Heap resize call from 24248320 to 29097984 took 0.10000000894069672 msecs. Success: true
Heap resize call from 29097984 to 34930688 took 0.5 msecs. Success: true
PASS   : tst_affectors::test_basic(16ms)
RESULT : tst_affectors::test_basic():"16ms":
     0.29 msecs per iteration (total: 75, iterations: 256)
Heap resize call from 34930688 to 41943040 took 0.10000000894069672 msecs. Success: true
PASS   : tst_affectors::test_basic(32ms)
RESULT : tst_affectors::test_basic():"32ms":
     0.41 msecs per iteration (total: 53, iterations: 128)
Heap resize call from 41943040 to 50331648 took 0.29999999701976776 msecs. Success: true
PASS   : tst_affectors::test_basic(100ms)
RESULT : tst_affectors::test_basic():"100ms":
     0.87 msecs per iteration (total: 56, iterations: 64)
Heap resize call from 50331648 to 60424192 took 0.3999999910593033 msecs. Success: true
PASS   : tst_affectors::test_basic(500ms)
RESULT : tst_affectors::test_basic():"500ms":
     3.3 msecs per iteration (total: 53, iterations: 16)
Heap resize call from 60424192 to 72548352 took 0.19999998807907104 msecs. Success: true
PASS   : tst_affectors::test_filtered(16ms)
RESULT : tst_affectors::test_filtered():"16ms":
     0.84 msecs per iteration (total: 54, iterations: 64)
PASS   : tst_affectors::test_filtered(32ms)
RESULT : tst_affectors::test_filtered():"32ms":
     0.96 msecs per iteration (total: 62, iterations: 64)
Heap resize call from 72548352 to 87097344 took 0.20000000298023224 msecs. Success: true
PASS   : tst_affectors::test_filtered(100ms)
RESULT : tst_affectors::test_filtered():"100ms":
     1.3 msecs per iteration (total: 89, iterations: 64)
PASS   : tst_affectors::test_filtered(500ms)
RESULT : tst_affectors::test_filtered():"500ms":
     3.7 msecs per iteration (total: 60, iterations: 16)
PASS   : tst_affectors::cleanupTestCase()
Totals: 10 passed, 0 failed, 0 skipped, 0 blacklisted, 15037ms
********* Finished testing of tst_affectors *********

********* Start testing of tst_emission *********
Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5852582532b3eb3ea8da51a1e272d8d017bd36c9)), unknown unknown
PASS   : tst_emission::initTestCase()
Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true
Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true
Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true
PASS   : tst_emission::test_basic(16ms)
RESULT : tst_emission::test_basic():"16ms":
     1.6 msecs per iteration (total: 53, iterations: 32)
Heap resize call from 29097984 to 34930688 took 0.4000000059604645 msecs. Success: true
PASS   : tst_emission::test_basic(32ms)
RESULT : tst_emission::test_basic():"32ms":
     3.1 msecs per iteration (total: 51, iterations: 16)
PASS   : tst_emission::test_basic(100ms)
RESULT : tst_emission::test_basic():"100ms":
     4.5 msecs per iteration (total: 73, iterations: 16)
PASS   : tst_emission::test_basic(500ms)
RESULT : tst_emission::test_basic():"500ms":
     21 msecs per iteration (total: 87, iterations: 4)
Heap resize call from 34930688 to 41943040 took 0.09999999403953552 msecs. Success: true
PASS   : tst_emission::test_basic(1000ms)
RESULT : tst_emission::test_basic():"1000ms":
     22 msecs per iteration (total: 89, iterations: 4)
PASS   : tst_emission::test_basic(10000ms)
RESULT : tst_emission::test_basic():"10000ms":
     23 msecs per iteration (total: 92, iterations: 4)
PASS   : tst_emission::cleanupTestCase()
Totals: 8 passed, 0 failed, 0 skipped, 0 blacklisted, 5398ms
********* Finished testing of tst_emission *********

======================================================================
======================================================================

chrome SIMD


********* Start testing of tst_affectors *********
Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5852582532b3eb3ea8da51a1e272d8d017bd36c9)), unknown unknown
PASS   : tst_affectors::initTestCase()
Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true
Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true
Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true
Heap resize call from 29097984 to 34930688 took 0.3999999761581421 msecs. Success: true
Heap resize call from 34930688 to 41943040 took 0.19999998807907104 msecs. Success: true
PASS   : tst_affectors::test_basic(16ms)
RESULT : tst_affectors::test_basic():"16ms":
     0.059 msecs per iteration (total: 61, iterations: 1024)
Heap resize call from 41943040 to 50331648 took 0.30000001192092896 msecs. Success: true
PASS   : tst_affectors::test_basic(32ms)
RESULT : tst_affectors::test_basic():"32ms":
     0.11 msecs per iteration (total: 59, iterations: 512)
Heap resize call from 50331648 to 60424192 took 0.30000001192092896 msecs. Success: true
PASS   : tst_affectors::test_basic(100ms)
RESULT : tst_affectors::test_basic():"100ms":
     0.15 msecs per iteration (total: 81, iterations: 512)
Heap resize call from 60424192 to 72548352 took 0.30000001192092896 msecs. Success: true
PASS   : tst_affectors::test_basic(500ms)
RESULT : tst_affectors::test_basic():"500ms":
     0.58 msecs per iteration (total: 75, iterations: 128)
Heap resize call from 72548352 to 87097344 took 0.3999999761581421 msecs. Success: true
PASS   : tst_affectors::test_filtered(16ms)
RESULT : tst_affectors::test_filtered():"16ms":
     0.10 msecs per iteration (total: 52, iterations: 512)
Heap resize call from 87097344 to 104529920 took 0.30000001192092896 msecs. Success: true
PASS   : tst_affectors::test_filtered(32ms)
RESULT : tst_affectors::test_filtered():"32ms":
     0.12 msecs per iteration (total: 64, iterations: 512)
PASS   : tst_affectors::test_filtered(100ms)
RESULT : tst_affectors::test_filtered():"100ms":
     0.19 msecs per iteration (total: 51, iterations: 256)
Heap resize call from 104529920 to 125435904 took 0.20000001788139343 msecs. Success: true
PASS   : tst_affectors::test_filtered(500ms)
RESULT : tst_affectors::test_filtered():"500ms":
     0.61 msecs per iteration (total: 79, iterations: 128)
PASS   : tst_affectors::cleanupTestCase()
Totals: 10 passed, 0 failed, 0 skipped, 0 blacklisted, 9728ms
********* Finished testing of tst_affectors *********

********* Start testing of tst_emission *********
Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5852582532b3eb3ea8da51a1e272d8d017bd36c9)), unknown unknown
PASS   : tst_emission::initTestCase()
Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true
Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true
Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true
Heap resize call from 29097984 to 34930688 took 0.29999998211860657 msecs. Success: true
PASS   : tst_emission::test_basic(16ms)
RESULT : tst_emission::test_basic():"16ms":
     0.046 msecs per iteration (total: 95, iterations: 2048)
Heap resize call from 34930688 to 41943040 took 0 msecs. Success: true
PASS   : tst_emission::test_basic(32ms)
RESULT : tst_emission::test_basic():"32ms":
     0.090 msecs per iteration (total: 93, iterations: 1024)
Heap resize call from 41943040 to 50331648 took 0.29999998211860657 msecs. Success: true
PASS   : tst_emission::test_basic(100ms)
RESULT : tst_emission::test_basic():"100ms":
     0.27 msecs per iteration (total: 70, iterations: 256)
Heap resize call from 50331648 to 60424192 took 0.4000000059604645 msecs. Success: true
PASS   : tst_emission::test_basic(500ms)
RESULT : tst_emission::test_basic():"500ms":
     1.3 msecs per iteration (total: 85, iterations: 64)
Heap resize call from 60424192 to 72548352 took 0.4000000059604645 msecs. Success: true
PASS   : tst_emission::test_basic(1000ms)
RESULT : tst_emission::test_basic():"1000ms":
     1.3 msecs per iteration (total: 87, iterations: 64)
PASS   : tst_emission::test_basic(10000ms)
RESULT : tst_emission::test_basic():"10000ms":
     1.3 msecs per iteration (total: 86, iterations: 64)
PASS   : tst_emission::cleanupTestCase()
Totals: 8 passed, 0 failed, 0 skipped, 0 blacklisted, 6017ms
********* Finished testing of tst_emission *********


Firefox has similar results:


firefox nosimd:

    ********* Start testing of tst_affectors *********
    Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/opt/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5f3c99085d4c2ebf57fd0586b013b02e32a8e20b)), unknown unknown
    PASS   : tst_affectors::initTestCase()
    Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
    Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
    Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
    PASS   : tst_affectors::test_basic(16ms)
    RESULT : tst_affectors::test_basic():"16ms":
         0.81 msecs per iteration (total: 52, iterations: 64)
    PASS   : tst_affectors::test_basic(32ms)
    RESULT : tst_affectors::test_basic():"32ms":
         1.1 msecs per iteration (total: 76, iterations: 64)
    PASS   : tst_affectors::test_basic(100ms)
    RESULT : tst_affectors::test_basic():"100ms":
         2.4 msecs per iteration (total: 79, iterations: 32)
    Heap resize call from 29097984 to 34930688 took 17 msecs. Success: true qtloader.js line 443 > eval:11829:17
    PASS   : tst_affectors::test_basic(500ms)
    RESULT : tst_affectors::test_basic():"500ms":
         9.1 msecs per iteration (total: 73, iterations: 8)
    PASS   : tst_affectors::test_filtered(16ms)
    RESULT : tst_affectors::test_filtered():"16ms":
         2.3 msecs per iteration (total: 74, iterations: 32)
    PASS   : tst_affectors::test_filtered(32ms)
    RESULT : tst_affectors::test_filtered():"32ms":
         2.6 msecs per iteration (total: 86, iterations: 32)
    PASS   : tst_affectors::test_filtered(100ms)
    RESULT : tst_affectors::test_filtered():"100ms":
         3.8 msecs per iteration (total: 62, iterations: 16)
    Heap resize call from 34930688 to 41943040 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
    PASS   : tst_affectors::test_filtered(500ms)
    RESULT : tst_affectors::test_filtered():"500ms":
         11 msecs per iteration (total: 88, iterations: 8)
    PASS   : tst_affectors::cleanupTestCase()
    Totals: 10 passed, 0 failed, 0 skipped, 0 blacklisted, 16781ms
    ********* Finished testing of tst_affectors *********    
        
     ********* Start testing of tst_emission *********
     Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/opt/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5f3c99085d4c2ebf57fd0586b013b02e32a8e20b)), unknown unknown
     PASS   : tst_emission::initTestCase()
     Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
     Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
     Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true qtloader.js line 443 > eval:11829:17
     PASS   : tst_emission::test_basic(16ms)
     RESULT : tst_emission::test_basic():"16ms":
          2.1 msecs per iteration (total: 70, iterations: 32)
     PASS   : tst_emission::test_basic(32ms)
     RESULT : tst_emission::test_basic():"32ms":
          4.1 msecs per iteration (total: 67, iterations: 16)
     PASS   : tst_emission::test_basic(100ms)
     RESULT : tst_emission::test_basic():"100ms":
          8.1 msecs per iteration (total: 65, iterations: 8)
     PASS   : tst_emission::test_basic(500ms)
     RESULT : tst_emission::test_basic():"500ms":
          43 msecs per iteration (total: 87, iterations: 2)
     PASS   : tst_emission::test_basic(1000ms)
     RESULT : tst_emission::test_basic():"1000ms":
          43 msecs per iteration (total: 86, iterations: 2)
     PASS   : tst_emission::test_basic(10000ms)
     RESULT : tst_emission::test_basic():"10000ms":
          43 msecs per iteration (total: 86, iterations: 2)
     PASS   : tst_emission::cleanupTestCase()
     Totals: 8 passed, 0 failed, 0 skipped, 0 blacklisted, 4178ms
     ********* Finished testing of tst_emission *********
                
======================================================================
======================================================================
                
                                         
firefox SIMD:


    ********* Start testing of tst_affectors *********
    Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5852582532b3eb3ea8da51a1e272d8d017bd36c9)), unknown unknown
    PASS   : tst_affectors::initTestCase()
    Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true
    Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true
    Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true
    Heap resize call from 29097984 to 34930688 took 0 msecs. Success: true
    PASS   : tst_affectors::test_basic(16ms)
    RESULT : tst_affectors::test_basic():"16ms":
         0.14 msecs per iteration (total: 73, iterations: 512)
    Heap resize call from 34930688 to 41943040 took 0 msecs. Success: true
    Heap resize call from 41943040 to 50331648 took 1 msecs. Success: true
    PASS   : tst_affectors::test_basic(32ms)
    RESULT : tst_affectors::test_basic():"32ms":
         0.21 msecs per iteration (total: 54, iterations: 256)
    Heap resize call from 50331648 to 60424192 took 5 msecs. Success: true
    PASS   : tst_affectors::test_basic(100ms)
    RESULT : tst_affectors::test_basic():"100ms":
         0.45 msecs per iteration (total: 58, iterations: 128)
    PASS   : tst_affectors::test_basic(500ms)
    RESULT : tst_affectors::test_basic():"500ms":
         1.8 msecs per iteration (total: 60, iterations: 32)
    Heap resize call from 60424192 to 72548352 took 7 msecs. Success: true
    PASS   : tst_affectors::test_filtered(16ms)
    RESULT : tst_affectors::test_filtered():"16ms":
         0.28 msecs per iteration (total: 73, iterations: 256)
    Heap resize call from 72548352 to 87097344 took 0 msecs. Success: true
    PASS   : tst_affectors::test_filtered(32ms)
    RESULT : tst_affectors::test_filtered():"32ms":
         0.35 msecs per iteration (total: 90, iterations: 256)
    PASS   : tst_affectors::test_filtered(100ms)
    RESULT : tst_affectors::test_filtered():"100ms":
         0.60 msecs per iteration (total: 77, iterations: 128)
    Heap resize call from 87097344 to 104529920 took 0 msecs. Success: true
    PASS   : tst_affectors::test_filtered(500ms)
    RESULT : tst_affectors::test_filtered():"500ms":
         2.0 msecs per iteration (total: 66, iterations: 32)
    PASS   : tst_affectors::cleanupTestCase()
    Totals: 10 passed, 0 failed, 0 skipped, 0 blacklisted, 6411ms
    ********* Finished testing of tst_affectors *********
                                                
    ********* Start testing of tst_emission *********
    Config: Using QtTest library 6.2.0, Qt 6.2.0 (wasm-little_endian-ilp32 static debug build; by Clang 13.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-github.com-llvm-llvm--project 5852582532b3eb3ea8da51a1e272d8d017bd36c9)), unknown unknown
    PASS   : tst_emission::initTestCase()
    Heap resize call from 16777216 to 20185088 took 0 msecs. Success: true
    Heap resize call from 20185088 to 24248320 took 0 msecs. Success: true
    Heap resize call from 24248320 to 29097984 took 0 msecs. Success: true
    Heap resize call from 29097984 to 34930688 took 0 msecs. Success: true
    PASS   : tst_emission::test_basic(16ms)
    RESULT : tst_emission::test_basic():"16ms":
         0.12 msecs per iteration (total: 65, iterations: 512)
    PASS   : tst_emission::test_basic(32ms)
    RESULT : tst_emission::test_basic():"32ms":
         0.24 msecs per iteration (total: 63, iterations: 256)
    Heap resize call from 34930688 to 41943040 took 0 msecs. Success: true
    PASS   : tst_emission::test_basic(100ms)
    RESULT : tst_emission::test_basic():"100ms":
         0.75 msecs per iteration (total: 97, iterations: 128)
    Heap resize call from 41943040 to 50331648 took 1 msecs. Success: true
    PASS   : tst_emission::test_basic(500ms)
    RESULT : tst_emission::test_basic():"500ms":
         3.6 msecs per iteration (total: 58, iterations: 16)
    Heap resize call from 50331648 to 60424192 took 4 msecs. Success: true
    PASS   : tst_emission::test_basic(1000ms)
    RESULT : tst_emission::test_basic():"1000ms":
         3.6 msecs per iteration (total: 58, iterations: 16)
    PASS   : tst_emission::test_basic(10000ms)
    RESULT : tst_emission::test_basic():"10000ms":
         3.6 msecs per iteration (total: 58, iterations: 16)
    PASS   : tst_emission::cleanupTestCase()
    Totals: 8 passed, 0 failed, 0 skipped, 0 blacklisted, 3339ms
    ********* Finished testing of tst_emission *********



Friday, April 2, 2021

Qt 6 WebAssembly QtQuick3d or, NOT April fools

 I am so happy right now! As of sha 4972fdb350fe79e18b0413e74028cd9b9803f96b (1 April), you can build Qt 6 for WebAssembly!

Not only that, because QtQuick3d in Qt 6 now supports OpenGL ES2/3, it will run in a web browser!

Here is a video of the helloquick3d example, running in Firefox: [edit] running at 62 fps

 
 
if that does not work, try this link:
 
Now I can get on with my life and stop working on build system stuff!