HTML canvas is incredibly slow and just a generally bad API. Using it from WASM is a mistake. It uses strings for everything and has a particularly slow imperative API, and the spec/de-facto-spec behaviors perform very slowly even on high-end hardware. I've seen relatively simple 2D canvas-based games drop frames in chrome on a GTX 2080ti because canvas is that bad.
The slow downs usually comes from abstraction layers. If you just use the api it will be fast. But if you create 1 million new objects and have 2 million function calls in excess on every frame it will be slow. Eg. If you dont like imperative style it will be slow. A compilation step and a bunch of optimization runs could make anything fast thought.
It really is not. If you want to set the current color you have to assemble a css color string from your color values. There is no way to make this fast. When you ship production 2D games using canvas, stuff like this shows up in your profiles and there's no way to optimize it out other than not using canvas. (Many people switch to using WebGL to do 2D themselves for this reason - it's faster.)
If setting the color is the bottleneck you can for example paint all red shapes, then paint the blue shapes, etc, instead of setting the color for every shape. You can also use different canvases . Offscreen and worker canvases is in experimental which enables further optimizations. 2d canvas has some very expensive calls, the trick is to only call them once, not for each object, not even for each frame. If you have 3d objects eg. Z-index its better to use 3d canvas. Yes 2d canvas is slow, but 2d scenes should be able to be optimized by only painting stuff once, then translate, rotate, reset and reuse. Set some upper limit of moving parts on the screen, then use pooling and caching. Put all canvas calls in the same file/ function then it will be easy to see what code can be removed/re-ordered eg. set the color once, not 1000 times after each other.
"HTML canvas ... generally bad API"
Agree on that. But this is not about Canvas::Graphics.
The original post appeared to be suggesting just using HTML Canvas (since it's backed by Skia). Was it suggesting something else?
There is no guarantee that canvas is hardware accelerated, or how whatever they are optimized, so a low level software rendering library might turn out to execute faster, regardless of the browser.
This is not about Canvas but rather set of primitives that browser uses for rendering web pages.
Like in my Sciter (https://sciter.com) where you can do
var anyEl = …;
anyEl.paintBackground = function(gfx) {
gfx.fillColor(rgb(0,0,0))
.rectangle(0,0,100cm,100cm);
return true; // to suppress CSS background drawing
}
paintBackground/Content/Foreground methods are called while rendering HTML tree and the `gfx` passed to that function is the very same graphics that is used for rendering HTML/CSS tree.That thing allows to combine immediate mode graphics a la ImGui with retained one to achieve more performant solution at the end.
The same approach can be used with WASM I think.
Re:CanvasKit – Skia and WebAssembly
by hackcasual on Friday July 19, 2019 @02:00PM
(#20480982)
What if you want a common C++ code base that can run on web or desktop?
If you want that you will create set of C++ classes wrapping Skia, Direct2D or Cairo with the same API as browser provides.
That is actually what I did in Sciter that is using these libraries for rendering on different platforms - they all have very close feature set - umbrella wrapper is quite simple.
Re:CanvasKit – Skia and WebAssembly
by hackcasual on Friday July 19, 2019 @02:58PM
(#20481510)
Sure, and that's actually what FireFox does, but not everyone is going to prioritize that approach.
So it is doable. QED.
Re:CanvasKit – Skia and WebAssembly
by hackcasual on Friday July 19, 2019 @05:02PM
(#20482405)
So because someone can abstract away the underlying graphics library, CanvasKit shouldn't exist?
Any browser already includes the very same set of graphic primitives that Skia provides. Just to render what you see on the screen right now.
Why not just to expose all that as API for WASM or whatever?