【Unity】Unity 6で誰も触れてないWebGPUのパフォーマンスを見てみた【WebGPU】

# 自己紹介
Unityを用いてポートフォリオサイトを作ろうとしている大学生です。
three.jsを使えとは言ってはいけません。

# 今回やること
今回は、WebGPUの実力を見てやろうと思ったので、WebGLと比べてみます。
ベンチマークらしいことをするのは始めてなので正しい結果かどうかは不明です。

## 結論
結果的にはWebGPUのほうがFPSがでませんでした。
、、、、なんでや！まぁ最後に考察も書きますので、どうぞお楽しみに

# 使用したスクリプト
<details>
<summary>Spawner.cs</summary>

```csharp:Spawner.cs
using System;
using R3;
using Cysharp.Threading.Tasks;
using UnityEngine;
using Random = UnityEngine.Random;

public class Spawner : MonoBehaviour
{
    [SerializeField] private Cube _cube;
    private void Start()
    {
        Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(0.01f)).Subscribe(_ =>
        {
            SpawnCube();
        }).AddTo(this);
    }

    private async void SpawnCube()
    {
        var positionX = Random.Range(-10f, 10f);
        var positionY = Random.Range(-6f, 6f);
        var positionZ = Random.Range(0f, 40f);

        var obj = Instantiate(_cube);
        obj.transform.position = new(positionX, positionY, positionZ);

        await UniTask.Delay(TimeSpan.FromSeconds(10f));
        
        Destroy(obj.gameObject);
    }
}

```
</details>

<details>
<summary>StatusUI.cs</summary>

```Csharp:StatusUI.cs
using System;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;

public class StatusUI : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI _fpsText;
    [SerializeField] private TextMeshProUGUI _aveFpsText;
    [SerializeField] private TextMeshProUGUI _graphicsApi;

    private int _frameCount;
    private float _prevTime;
    private int _fpsCount;
    private float _fpsSum;

    private void Start()
    {
        _graphicsApi.SetText(Enum.GetName(typeof(GraphicsDeviceType), SystemInfo.graphicsDeviceType));
    }
        
    private void Update()
    {
        _frameCount++;
        float time = Time.realtimeSinceStartup - _prevTime;

        if (time >= 0.5f)
        {
            _fpsCount++;
            
            var fps = _frameCount / time;
            _fpsText.SetText("{0}fps", fps);
            
            _fpsSum += fps;
            _aveFpsText.SetText("ave: {0}", _fpsSum / _fpsCount);
            
            _frameCount = 0;
            _prevTime = Time.realtimeSinceStartup;
        }
    }
}
```

</details>

<details>
<summary>Cube.cs</summary>

```Csharp:Cube.cs
using UnityEngine;

public class Cube : MonoBehaviour
{
    
}
```

</details>

## どういうベンチマーク？
とりあえず、Cubeを生成してしばらくしたら消すを高速にやります。
目的としては、GPU側に負荷がかかるようにしたいと思ってやりました。
ドローコールが多いのでCPU側にも負担がありますが、総合的には上手くGPUに負荷をかけれたのではないでしょうか。

## FPSの平均値について
平均値の算出方法は結構適当で、あまり参考になりません。（体感値）
ただ、今回に関しては比較できればOKということで、許してください。

# 結果
## 環境
結果の前に環境を示しておきます。
- Unity 6 Beta (6000.0b16)
- UniTask 2.5.4
- R3 1.1.11
- URP 17.0.3
- Google Chrome

各種画像の左上のGraphics APIはUnityで自動検出していますので、正確なはずです。
## WebGL
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/cb9a65e7-0505-f3ea-42b4-eb0b0fb2966e.png)

FPS：130~140FPS前後
ave：140FPS前後

## WebGPU
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/023529b3-cbb5-a5f4-c37f-7798e4def7ac.png)

FPS：100~110FPS
ave：110FPS前後

## まとめ
結構顕著な差が出たかなと思います。
流石に何かがおかしいと何度もやってみたりはしましたが、残念ながら結果は同様でした。

また、ブラウザは「Edge」「Chrome」「Firefox」を試しましたが同様でした。

## 考察
色々試した結果、GPU使用率がWebGPUの場合上がりきっていませんでした。
### WebGL
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/74ef1dbb-957e-c2ac-23b6-e355cbb07e11.png)

### WebGPU
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/57601357-eb44-7af3-e3e0-4c28e3da9fef.png)

そのため、ブラウザ側もしくはURPの最適化不足といったところでしょうか。
## ブレイク
URP 17でRender Graphへの移行が行われました。
ということで、Render Graphをオンにしてやってみよう！

結果は、、、、、変わらず。
Render Graphに関しては深く理解していませんが、単純に軽くなったわけではないんですかね？

# さいごに
最後にポートフォリオをUnityで作ろうと思ってますので、お楽しみに！
ではまた、どこかでお会いしましょう。

## 参考
https://forum.unity.com/threads/early-access-to-the-new-webgpu-backend-in-unity-2023-3.1516621/

https://zenn.dev/sansyoku_gyokai/articles/bdce53aa0f2f5a

## 使用したリポジトリ

https://github.com/AtsuAtsu0120/WebGPU-PerformanceTest