node-sdl icon indicating copy to clipboard operation
node-sdl copied to clipboard

Boost performance?

Open notcl4y14 opened this issue 1 year ago • 11 comments
trafficstars

Is there a way to boost performance for the canvas version? Or should I choose WebGL instead?

notcl4y14 avatar Jun 25 '24 21:06 notcl4y14

From my personal experience, using @kmamal/gl will be the best choice, although it's harder to use and require knowledge about shader and stuff like that, but you can get way better performance using it. Beside from some GC and memory leak issue you may encounter, it's pretty good!

Also I don't think you can make canvas faster (~~I tried that~~), because most of the Canvas that runs on Node.js are often written in other language (If I'm not mistaken), and I assume they also need to copy the pixel buffer to Node.js, and then node-sdl need to copy it again to sdl, which is definitely not fast.

LmanTW avatar Jun 26 '24 03:06 LmanTW

I think I could make canvas write to the window directly, eliminating some of the buffer copying. I'll keep this issue open to track that effort.

There's also a chance that you are doing something weird with your code that needlessly reduces performance. I'd be happy to have a look if you are able to upload the repo.

Failing that, switching to webgl/gpu is always an option, and there are libraries that make working with them much easier.

kmamal avatar Jun 26 '24 05:06 kmamal

@LmanTW do you think the memory leak you encountered was a bug in kmamal/gl?

kmamal avatar Jun 26 '24 05:06 kmamal

There's also a chance that you are doing something weird with your code that needlessly reduces performance. I'd be happy to have a look if you are able to upload the repo.

Simply, it's just the same 59-60 fps just like an empty canvas on HTML page. But in the code it's just clear the canvas and draw a rectangle, and input check

notcl4y14 avatar Jun 26 '24 06:06 notcl4y14

kmamal

I think it was because I keep using gl.createBuffer() when I want to do gl.bindBuffer and gl.bufferData, and I fixed it by just using the same buffer instead of keep creating new buffers.

Now I think about it it's quite silly, so I don't think it's an issue in kmamal/gl, I was just using it in a wrong way.

LmanTW avatar Jun 26 '24 07:06 LmanTW

I just found out that skia-canvas actually supports rendering the canvas to an OS window. It also has some window events like mousemove, keydown, input, etc...

LmanTW avatar Aug 11 '24 08:08 LmanTW

I just found out that skia-canvas actually supports rendering the canvas to an OS window. It also has some window events like mousemove, keydown, input, etc...

Interesting

notcl4y14 avatar Sep 04 '24 20:09 notcl4y14

Also https://github.com/Brooooooklyn/canvas is node bindings for skia-canvas. Just tested it with this node-sdl package and it works like champ!

I'm even getting decent fps on a bunch of these cheap Anbernic retro game devices (arm64 chips with 1g ram, running knulli linux)

nodesdls

monteslu avatar Dec 03 '24 15:12 monteslu

after some testing, it seems that @napi-rs/canvas is quite a bit faster than skia-canvas

One thing to make sure is that when you're calling window.render do this:

window.render(width, height, stride, 'rgba32', Buffer.from(imageData.data.buffer));

and NOT

window.render(width, height, stride, 'rgba32', Buffer.from(imageData.data));

HUGE performance difference between those two. The latter does a memory copy that is very slow and gets worse in high resolutions.

monteslu avatar Dec 10 '24 20:12 monteslu

once this gets resolved, performance with this library + @napi-rs/canvas is going to be fantastic: https://github.com/Brooooooklyn/canvas/issues/972

@kmamal really greatful to you for working on this library I'm able to do JS game dev on retro handheld devices now: https://www.youtube.com/watch?v=osJsBRPSrM4

monteslu avatar Jan 22 '25 00:01 monteslu

  1. I've made the windows use streaming textures for rendering which should be a bit faster than what was happening before.
  2. I played around with @napi-rs/canvas and it's very fast. I am now using this lib in examples instead of plaincanvas.
  3. I tried to get the canvas lib to render directly to windows. It worked, but it was still much slower than just using @napi-rs/canvas with the buffer copying.
  4. I would like to also get @napi-rs/canvas to render directly to the window, but it's written in Rust which I've never used. This will have to wait.

Is anyone still facing serious performance issues? Let me know if you do, otherwise this issue is on hold for now.

kmamal avatar Mar 09 '25 19:03 kmamal

@napi-rs/canvas is indeed faster, but it starts to have noticeable performance issues when rendering to big screens. 2k resolutions seem to be extremely slow when rendering canvas's buffer to screen.

I still think gl is the best option to make this work for games, else canvas would only be fit for things that don't require constant rerendering.

cunev avatar Apr 07 '25 15:04 cunev

Is using setTimeout(0) in an infinite loop still the recommended way to draw every frame? I want to do animation and motion using @napi-rs/canvas, and when using this code with setTimeout(0):

window.render(pixelWidth, pixelHeight, pixelWidth * 4, 'rgba32', canvas.data(), {
      scaling: 'linear',
      dstRect: { x: 0, y: 0, width: pixelWidth, height: pixelHeight },
    })

the FPS I'm seeing fluctuates a lot around at 60. At times it even goes to 70 or reduces to 30. If I use skia-canvas' own Window, I get a proper 60±1 FPS.

Am I doing something wrong here? Or is this expected?

ajitid avatar Apr 21 '25 08:04 ajitid

@ajitid I can't reproduce that on my system so I'm splitting it into a new issue.

kmamal avatar Apr 21 '25 17:04 kmamal