Firefox和Chrome之间的webgl性能差异

ert95000

我目前正在开发用于Web应用程序的图像处理工具。我需要处理相同大小的png图像,并将它们逐像素组合。到目前为止,我已经建立了一个原型(非常受webglfundamentals.org上的教程启发),该原型可以拍摄两个图像,并将它们的像素相乘。我正在使用来自http://twgljs.org/的webgl的twgl-helper库(不幸的是,我不能把它摆在小提琴里)。

我有以下问题:谁能解释或给出提示,为什么Firefox 78的速度比最近的Chrome慢得多?FF平均每个渲染约34毫秒(在两次采样之间完全刷新和擦除现金),而Chrome平均每个渲染0.27毫秒。这是两个数量级的差异,我无法解释。我已经尝试过webgl2,两者的速度都稍快一些,但保持了两者之间的疯狂差异。

如果需要提供更多信息,请告诉我,我将在星期四回到办公室。感谢您的支持和想法。

function main() {


    // Get A WebGL context
    var canvas = document.getElementById("webgl");
    var gl = canvas.getContext("webgl");
    if (!gl) {
        return;
    }

    var canvas1 = document.getElementById("canvas1");
    var canvas2 = document.getElementById("canvas2");

    // setup GLSL program
    var program = twgl.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    gl.useProgram(program);

    var time0 = performance.now();
    // look up where the vertex data needs to go.
    var positionLocation = gl.getAttribLocation(program, "a_position");
    var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");

    // provide texture coordinates for the rectangle.
    var texCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        0.0, 1.0,
        1.0, 0.0,
        1.0, 1.0]), gl.STATIC_DRAW);

    // vertex attributes need to be turned on explicitly
    gl.enableVertexAttribArray(texCoordLocation);
    gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);

    // lookup uniforms
    var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

    // set the resolution
    gl.uniform2f(resolutionLocation, canvas1.width, canvas1.height);

    // Create a buffer for the position of the rectangle corners.
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.enableVertexAttribArray(positionLocation);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    // Set a rectangle the same size as the image.
    setRectangle(gl, 0, 0, canvas.width, canvas.height);
    // setRectangle(gl, 0, 0, 1000, 1000);


    function setupTexture(canvas, textureUnit, program, uniformName) {
        var tex = gl.createTexture();

        updateTextureFromCanvas(tex, canvas, textureUnit);

        // Set the parameters so we can render any size image.
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        //      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        // mal ausprobieren
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

        var location = gl.getUniformLocation(program, uniformName);
        gl.uniform1i(location, textureUnit);
    }

    function updateTextureFromCanvas(tex, canvas, textureUnit) {
        gl.activeTexture(gl.TEXTURE0 + textureUnit);
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
    }

    var tex1 = setupTexture(canvas1, 0, program, "u_canvas1");
    var tex2 = setupTexture(canvas2, 1, program, "u_canvas2");

    // Draw the rectangle.
    gl.drawArrays(gl.TRIANGLES, 0, 6);

    var time1 = performance.now();
    console.log("Processing image took " + (time1 - time0) + " ms.");
    document.getElementById("performance").innerHTML = "Processing image took " + (time1 - time0) + " ms.";
}

function setRectangle(gl, x, y, width, height) {
    var x1 = x;
    var x2 = x + width;
    var y1 = y;
    var y2 = y + height;
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        x1, y1,
        x2, y1,
        x1, y2,
        x1, y2,
        x2, y1,
        x2, y2]), gl.STATIC_DRAW);
}

const WIDTH = 1600;
const HEIGHT = 900;

addNewImage = function (path, id, width, height) {
    console.log(path)
    let newElement = document.createElement("canvas");
    document.body.appendChild(newElement);
    newElement.id = id;
    let ctx = newElement.getContext("2d");
    ctx.canvas.width = width;
    ctx.canvas.height = height;
    let input = new Image();
    input.crossOrigin = "anonymous";
    input.onload = function () {
        ctx.drawImage(input, 0, 0);
    }
    input.src = path;
}



addNewImage("https://i.imgur.com/KjUybBD.png", "canvas1", WIDTH, HEIGHT);
addNewImage("https://i.imgur.com/ZKMnXce.png", "canvas2", WIDTH, HEIGHT);
canvas {
    border: 2px solid black;
    display: inline-block;
    width: 100%;
}
<script src="twgl.js"></script>
<link rel="stylesheet" type="text/css" href="style.css" />
<button onclick="main()">click</button>

<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
attribute vec2 a_texCoord;

uniform vec2 u_resolution;

varying vec2 v_texCoord;

void main() {
   // convert the rectangle from pixels to 0.0 to 1.0
   vec2 zeroToOne = a_position / u_resolution;

   // convert from 0->1 to 0->2
   vec2 zeroToTwo = zeroToOne * 2.0;

   // convert from 0->2 to -1->+1 (clipspace)
   vec2 clipSpace = zeroToTwo - 1.0;

   gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);

   // pass the texCoord to the fragment shader
   // The GPU will interpolate this value between points.
   v_texCoord = a_texCoord;
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    // our 2 canvases
    uniform sampler2D u_canvas1;
    uniform sampler2D u_canvas2;

    // the texCoords passed in from the vertex shader.
    // note: we're only using 1 set of texCoords which means
    //   we're assuming the canvases are the same size.
    varying vec2 v_texCoord;

    void main() {
         // Look up a pixel from first canvas
         vec4 color1 = texture2D(u_canvas1, v_texCoord);

         // Look up a pixel from second canvas
         vec4 color2 = texture2D(u_canvas2, v_texCoord);

         // return the 2 colors multiplied
         gl_FragColor = color1 * color2;
    }
</script>

<!-- <canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas> -->
<div id="performance"></div>
<canvas id="webgl" width="1600" height="900"></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>

man

实际上不可能指望具有类似性能的浏览器。在许多测试中,一种浏览器的速度是另一种浏览器的2倍至40倍。

在这种情况下,我不知道为什么现代的Firefox比Chrome慢。Chrome是多进程的(我认为Firefox在这一点上也是,但也许不是),因此在Chrome中,计时只是计时将命令插入命令缓冲区以从正在运行网页的进程与单独的进程进行对话所花费的时间。与GPU对话。计时与网页并行运行的命令实际上需要花费多长时间。

如果我在抽奖电话之后添加此内容

// Force the webpage to wait for the GPU process
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));

然后我得到了Chrome(27ms)和Firefox(32ms)的可比时间

function main() {


    // Get A WebGL context
    var canvas = document.getElementById("webgl");
    var gl = canvas.getContext("webgl");
    if (!gl) {
        return;
    }

    var canvas1 = document.getElementById("canvas1");
    var canvas2 = document.getElementById("canvas2");

    // setup GLSL program
    var program = twgl.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    gl.useProgram(program);

    var time0 = performance.now();
    // look up where the vertex data needs to go.
    var positionLocation = gl.getAttribLocation(program, "a_position");
    var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");

    // provide texture coordinates for the rectangle.
    var texCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        0.0, 0.0,
        1.0, 0.0,
        0.0, 1.0,
        0.0, 1.0,
        1.0, 0.0,
        1.0, 1.0]), gl.STATIC_DRAW);

    // vertex attributes need to be turned on explicitly
    gl.enableVertexAttribArray(texCoordLocation);
    gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);

    // lookup uniforms
    var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

    // set the resolution
    gl.uniform2f(resolutionLocation, canvas1.width, canvas1.height);

    // Create a buffer for the position of the rectangle corners.
    var buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.enableVertexAttribArray(positionLocation);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    // Set a rectangle the same size as the image.
    setRectangle(gl, 0, 0, canvas.width, canvas.height);
    // setRectangle(gl, 0, 0, 1000, 1000);


    function setupTexture(canvas, textureUnit, program, uniformName) {
        var tex = gl.createTexture();

        updateTextureFromCanvas(tex, canvas, textureUnit);

        // Set the parameters so we can render any size image.
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        //      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        // mal ausprobieren
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

        var location = gl.getUniformLocation(program, uniformName);
        gl.uniform1i(location, textureUnit);
    }

    function updateTextureFromCanvas(tex, canvas, textureUnit) {
        gl.activeTexture(gl.TEXTURE0 + textureUnit);
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
    }

    var tex1 = setupTexture(canvas1, 0, program, "u_canvas1");
    var tex2 = setupTexture(canvas2, 1, program, "u_canvas2");

    // Draw the rectangle.
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    // Force the webpage to wait for the GPU process
    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));

    var time1 = performance.now();
    console.log("Processing image took " + (time1 - time0) + " ms.");
    document.getElementById("performance").innerHTML = "Processing image took " + (time1 - time0) + " ms.";
}

function setRectangle(gl, x, y, width, height) {
    var x1 = x;
    var x2 = x + width;
    var y1 = y;
    var y2 = y + height;
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        x1, y1,
        x2, y1,
        x1, y2,
        x1, y2,
        x2, y1,
        x2, y2]), gl.STATIC_DRAW);
}

const WIDTH = 1600;
const HEIGHT = 900;

addNewImage = function (path, id, width, height) {
    console.log(path)
    let newElement = document.createElement("canvas");
    document.body.appendChild(newElement);
    newElement.id = id;
    let ctx = newElement.getContext("2d");
    ctx.canvas.width = width;
    ctx.canvas.height = height;
    let input = new Image();
    input.crossOrigin = "anonymous";
    input.onload = function () {
        ctx.drawImage(input, 0, 0);
    }
    input.src = path;
}



addNewImage("https://i.imgur.com/KjUybBD.png", "canvas1", WIDTH, HEIGHT);
addNewImage("https://i.imgur.com/ZKMnXce.png", "canvas2", WIDTH, HEIGHT);
canvas {
    border: 2px solid black;
    display: inline-block;
    width: 100%;
}
<script src="twgl.js"></script>
<link rel="stylesheet" type="text/css" href="style.css" />
<button onclick="main()">click</button>

<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
attribute vec2 a_texCoord;

uniform vec2 u_resolution;

varying vec2 v_texCoord;

void main() {
   // convert the rectangle from pixels to 0.0 to 1.0
   vec2 zeroToOne = a_position / u_resolution;

   // convert from 0->1 to 0->2
   vec2 zeroToTwo = zeroToOne * 2.0;

   // convert from 0->2 to -1->+1 (clipspace)
   vec2 clipSpace = zeroToTwo - 1.0;

   gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);

   // pass the texCoord to the fragment shader
   // The GPU will interpolate this value between points.
   v_texCoord = a_texCoord;
}
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    // our 2 canvases
    uniform sampler2D u_canvas1;
    uniform sampler2D u_canvas2;

    // the texCoords passed in from the vertex shader.
    // note: we're only using 1 set of texCoords which means
    //   we're assuming the canvases are the same size.
    varying vec2 v_texCoord;

    void main() {
         // Look up a pixel from first canvas
         vec4 color1 = texture2D(u_canvas1, v_texCoord);

         // Look up a pixel from second canvas
         vec4 color2 = texture2D(u_canvas2, v_texCoord);

         // return the 2 colors multiplied
         gl_FragColor = color1 * color2;
    }
</script>

<!-- <canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas> -->
<div id="performance"></div>
<canvas id="webgl" width="1600" height="900"></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>

当然,Chrome正在另一个进程中运行命令这一事实意味着您可以免费获得一些并行处理。我认为大多数情况下,Chrome WebGL性能要胜过Firefox WebGL性能,但并非总是如此。

剩下的速度差异唯一想到的另一件事是浏览器如何将画布转换为纹理。有很多可能性

首先,2D画布将其数据保留为预乘alpha,但WebGL默认为不预乘alpha,因此

  1. 浏览器在ram中具有2D画布。它必须将该数据转换为未预乘的alpha,然后通过glTexImage2D上载它。(慢)

  2. 浏览器在vram中具有2D画布。它将下载到ram,将其转换为未预乘的alpha,然后通过glTexImage2D(甚至更慢)上传

  3. 浏览器在vram中具有2D画布。它将纹理附加到帧缓冲区,并使用不预乘Alpha的着色器将画布渲染到其中。

我很肯定Chrome会采用最后一种方法。我知道它的代码存在。我不知道确保使用该代码所需的所有条件,但我非常有信心1900x600画布会采用该路径(在某个点上,某个尺寸小于256x256的画布是在CPU上完成的,而不是在GPU上完成,但我不知道那是否仍然是真的)

Firefox可能会或可能不会做相同的事情,但是如果不是,那可能就是为什么当我们通过调用暂停GPU进程时Chrome在27ms内执行此操作而Firefox在32ms内执行此操作的原因gl.readPixels

不过,更大的一点是,浏览器可以以许多不同的方式进行优化,并且不能保证它们会或不会进行优化。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

<Pre> Firefox和Chrome之间的呈现差异

来自分类Dev

Chrome和Firefox之间的JavaScript范围差异

来自分类Dev

?? 之间的性能差异 和 ==

来自分类Dev

Firefox和Chrome / Safari之间的Div-padding-top差异

来自分类Dev

Chrome / Safari和Firefox之间的CSS定位差异

来自分类Dev

Firefox和Chrome之间的CSS图像对齐方式差异

来自分类Dev

javascript Date() 计算中 Chrome/Firefox 和 IE 之间的差异

来自分类Dev

OpenGL和WebGL之间的Alpha渲染差异

来自分类Dev

管道和流程替代之间的性能差异

来自分类Dev

Linux和Windows之间的numpy性能差异

来自分类Dev

阵列,堆栈和队列之间的性能差异

来自分类Dev

管道和流程替代之间的性能差异

来自分类Dev

drawBitmap和createScaledBitmap之间的性能差异

来自分类Dev

并行和嵌套IF条件之间的性能差异

来自分类Dev

Chrome和Firefox之间的布局差异,与浮动和显示有关:表格

来自分类Dev

带有Firefox和Chrome的WebGL

来自分类Dev

Firefox和Chrome之间的CSS3过滤器差异

来自分类Dev

Firefox 23.0.1 Chrome 23.0.1271.64和IE 8之间占位符差异的字体颜色

来自分类Dev

fireFox和Chrome之间图像的transform属性的css过渡渲染的差异

来自分类Dev

fireFox和Chrome之间图像的transform属性的css过渡渲染的差异

来自分类Dev

使用 rem 的 chrome 和 firefox 之间的字体大小差异

来自分类Dev

C#和Javascript之间的性能和内存差异?

来自分类Dev

Java 8 lambda和匿名内部类之间的性能差异

来自分类Dev

Perl中while(每个)和foreach之间的性能差异

来自分类Dev

Numpy和Pandas之间有性能差异吗?

来自分类Dev

Android中query()和rawQuery()方法之间的性能差异

来自分类Dev

std :: count和std :: find之间的性能差异

来自分类Dev

Array和ArrayList之间的性能或内存消耗差异

来自分类Dev

之间存在性能差异?和.where.present?

Related 相关文章

  1. 1

    <Pre> Firefox和Chrome之间的呈现差异

  2. 2

    Chrome和Firefox之间的JavaScript范围差异

  3. 3

    ?? 之间的性能差异 和 ==

  4. 4

    Firefox和Chrome / Safari之间的Div-padding-top差异

  5. 5

    Chrome / Safari和Firefox之间的CSS定位差异

  6. 6

    Firefox和Chrome之间的CSS图像对齐方式差异

  7. 7

    javascript Date() 计算中 Chrome/Firefox 和 IE 之间的差异

  8. 8

    OpenGL和WebGL之间的Alpha渲染差异

  9. 9

    管道和流程替代之间的性能差异

  10. 10

    Linux和Windows之间的numpy性能差异

  11. 11

    阵列,堆栈和队列之间的性能差异

  12. 12

    管道和流程替代之间的性能差异

  13. 13

    drawBitmap和createScaledBitmap之间的性能差异

  14. 14

    并行和嵌套IF条件之间的性能差异

  15. 15

    Chrome和Firefox之间的布局差异,与浮动和显示有关:表格

  16. 16

    带有Firefox和Chrome的WebGL

  17. 17

    Firefox和Chrome之间的CSS3过滤器差异

  18. 18

    Firefox 23.0.1 Chrome 23.0.1271.64和IE 8之间占位符差异的字体颜色

  19. 19

    fireFox和Chrome之间图像的transform属性的css过渡渲染的差异

  20. 20

    fireFox和Chrome之间图像的transform属性的css过渡渲染的差异

  21. 21

    使用 rem 的 chrome 和 firefox 之间的字体大小差异

  22. 22

    C#和Javascript之间的性能和内存差异?

  23. 23

    Java 8 lambda和匿名内部类之间的性能差异

  24. 24

    Perl中while(每个)和foreach之间的性能差异

  25. 25

    Numpy和Pandas之间有性能差异吗?

  26. 26

    Android中query()和rawQuery()方法之间的性能差异

  27. 27

    std :: count和std :: find之间的性能差异

  28. 28

    Array和ArrayList之间的性能或内存消耗差异

  29. 29

    之间存在性能差异?和.where.present?

热门标签

归档