为什么 webgl canvas 上下文比 2d canvas 使用更多的内存?

why webgl canvas context use much more memory than 2d canvas?

1024x1024 2d canvas 可能使用大约 1024 * 1024 * 4 = 4M 内存,但 webGL 上下文使用至少 5-10 倍的内存。

<!DOCTYPE html>
<html>
    <body>
    
        <div style="display:inline-block ;overflow: hidden;width: 512px;height: 512px;">
            <canvas id="canvas" width="1024" height="1024" style="border: red 1px solid;transform: scale(0.5); transform-origin: 0 0;">old version need update</canvas>
        </div>
    </body>

    <script>
        var ctx = window.document.getElementById("canvas").getContext("webgl")
        var gl = canvas.getContext("experimental-webgl");

    </script>

</html>

可能有多种原因

默认情况下,webgl canvas 是 anti-aliased。

浏览器选择金额但检查

const gl = document.createElement('canvas').getContext('webgl');
const samples = gl.getParameter(gl.SAMPLES) || 1;
console.log(`samples is ${samples} so this canvas is actually ${gl.canvas.width * samples} x ${gl.canvas.height * samples} pixels big internally`);

在我的机器上 300x150 canvas 实际上是 1200x600 因为那是 how a GPU's built in antialiasing works

您可以通过在创建上下文时传入antialias: false来关闭anti-aliasing

const gl = document.createElement('canvas').getContext('webgl', {
  antialias: false,
});
const samples = gl.getParameter(gl.SAMPLES) || 1;
console.log(`samples is ${samples} so this canvas is actually ${gl.canvas.width * samples} x ${gl.canvas.height * samples} pixels big internally`);

WebGL 是双缓冲的

所以总会分配至少 2 个缓冲区,绘图缓冲区(您渲染到的缓冲区)和一个用于渲染页面的副本。因此,即使关闭抗锯齿功能,也会有 2 个缓冲区,其中 2D canvas 可能只有 1 个(这取决于浏览器对 canvas 2D 的作用)

WebGL 需要 GL 上下文和相关支持

WebGL 在浏览器内部创建某种上下文来跟踪所有状态。该状态是每个 WebGL 上下文。换句话说,如果您创建 2 个 WebGL 上下文,浏览器需要跟踪 2 组 WebGL 状态。在 Chrome 中,包括命令缓冲区和其他缓冲区,用于将命令和数据从进程 运行 网页传输到与 GPU 对话的进程。这本身可以是 2-4 兆。 Canvas 另一方面,2D 最有可能分配该信息一次并在所有 canvases 之间共享。在查看内存使用情况时甚至可能不会考虑它。