Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What is going on with this article?
@nanikore55554

Electron上でVulkanを動かすことに成功しました(しかも現実的な範疇で)

この話の続きです。

要約すると「Electron上でVulkanは動かせたけど、遅すぎて10fpsも出せませんでした。」という話です。

で、今回はなんとか現実的な範疇にまでプログラムを軽くする方法はないかと考え、実際にやってみた結果です。

1. そもそも何故重いのか?

前回も話しましたが、生の画像データ(RGBAのデータがそのまま入ってるconst char*型のデータ)からJpegへの変換が重すぎる事が原因です。とすれば、この部分をなくせば軽くなるはずです。

2. 生の画像データをElectron上で表示する方法

だが、ここで問題があります。Electron(正確にはウェブブラウザ)には生の画像を表示する方法がありません。これがあったからわざわざJpegへデータを変換していたのです。

しかし、回避方法があります。前回も触れたWebGLで表示する方法です。WebGLはUint8Array型のデータをテクスチャとして扱う事ができます。生の画像データを毎フレームごとにテクスチャにして表示すれば一々Jpegで変換する事なく表示する事ができるはずです。

3. 実際にやってみた方法

下記のQiitaにあるソースコードを参考にして作成しました。

このソースコードを改造して作成したソースを一部抜粋します。

sample.js
setInterval(() => {
    //Vulkan部分を実際に表示する関数
    bar.main_loop();
    //Vulkanで生成した画像をスクリーンショットとして撮る関数
    bar.make_ss();
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    //bar.send_raw_imageはスクリーンショットをjs側に送信する関数
    pixels = new Uint8Array(bar.send_raw_image().buffer.slice(0, texWidth*texHeight*4));
    texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    //texWidthは横幅、texHeightは縦幅
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texWidth, texHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.bindTexture(gl.TEXTURE_2D, null);

    gl.clear(gl.COLOR_BUFFER_BIT);
    //シェーダを用意する関数    
    gl.useProgram(program);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.uniform1i(uniforms['u_texture'], 0);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
},32);

4. 結果

普通に30fpsが出ました。それどころか、60fpsも余裕で出来ます。

前回、10fpsも出なかった事を考えれば大きな進化です。

しかし、CPUへの負担は大きく、30fpsで8%、60fpsで20%以上CPUのリソースが使われました。

負担となっているのは
pixels = new Uint8Array(bar.send_raw_image().buffer.slice(0, texWidth*texHeight*4));
の部分です。ここをnew Uint8Array(texWidth*texHeight*4)にしたらCPUの負担が一気に1%以下へ減りました。この部分をどうにかすれば、もっとElectronでVulkanを動かす事が現実的になると考えられます。

5. もっと早くする方法がある?

実はもっと早く出来るかもしれない方法があります。前に述べたNVJpegを使ってエンコードし、Electronで表示する方法です。また試していませんが、libjpeg-turboを使うより早いらしいです。ただし、NVIDIA製のGPUでしか動かない(Electron最大の武器であるクロスプラットフォームが無くなる)という致命的な欠点があるので使って意味があるかどうかは微妙なところです。(どうも調べたら思ったより速度が上がるわけでも無さそうですし)

まぁ、Electronじゃないけど「HTMLで作るアプリは非常に作りやすい」という点だけに着目して専用のプラットフォームだけで動くHTML製ネイティブアプリを動かしている製品もありますけどね。あの携帯型ゲーム機とかゲーム機とかゲーム機とかな。
(詳しく知りたい人は「任○堂 react.js」と検索すると幸せになれるよ)。

6. 前回触れなかったこと

実はVulkanだとスクリーンショットを撮るプログラムが非常に軽い。

本来、スクリーンショットを撮るというのはCPUの負担の大きいものです。
一回だけ撮るのなら問題有りませんが、毎フレームごとに撮るとなるとかなり負担は相当増大します。しかし、今回のプログラムでは非常に軽かったです。

これを生かせばもっとヘンテコで有用なプログラムを作れるかもしれません。

最後に分かった事

1.やっぱりWebGLは凄いと思う
2.ただ、ここまで来たら何かきっかけがあればWebGPUはそんなに必要ないのかも?
3.各ウェブブラウザは生データの画像も表示できるようにすべきだと思う

1
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
1
Help us understand the problem. What is going on with this article?