【问题标题】:Webgl flickering in Chrome on Windows x64 with nvidia GPUWebgl 在带有 nvidia GPU 的 Windows x64 上的 Chrome 中闪烁
【发布时间】:2018-04-23 06:11:48
【问题描述】:

我在带有 nVidia 芯片的 Windows 10 x64 上看到一些渲染几何图形 Chrome 奇怪地闪烁。我还在 Chrome for Linux、Firefox 和 Android 以及 Intel GPU 中进行了测试。除了提到的一个平台之外,它在任何地方都可以正常工作。

最小示例如下所示:

顶点着色器:

precision mediump float;
smooth out vec2 pointCoord;

const vec2 vertexCoord[] = vec2[](
    vec2(0.0, 0.0),
    vec2(1.0, 0.0),
    vec2(1.0, 1.0),
    vec2(0.0, 0.0),
    vec2(1.0, 1.0),
    vec2(0.0, 1.0)
);

void main()
{
    gl_Position = vec4(vertexCoord[gl_VertexID], 0.0, 1.0);
    pointCoord = vertexCoord[gl_VertexID];
}

片段着色器:

precision mediump float;

out vec4 outFragColor;
smooth in vec2 pointCoord;

void main()
{
    outFragColor = vec4(pointCoord, 0.0, 1.0);
}

GL 状态:

gl.clearColor(0, 0, 0, 1);
gl.disable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.depthMask(gl.FALSE);
gl.stencilMask(gl.FALSE);

渲染代码:

var mainLoop = function()
{
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    window.requestAnimationFrame(mainLoop);
}
window.requestAnimationFrame(mainLoop);

完整代码的工作网页可用here

我在受影响的平台上看到的:

我尝试了带有顶点属性的 webgl1 上下文,因为 glsl 100es 中没有 gl_VertexID 变量,它产生了相同的结果。我还尝试在主循环末尾添加glFinishglFlush。它降低了闪烁频率,但并不能解决问题。

有什么问题?此代码中是否有任何未定义的行为,因此它在不同平台上的工作方式不同?还是 Chrome 或 Angle 中的错误?

UPD:

按照 Nabr 的回答,我添加了一个绑定到已启用顶点属性的 VBO,并构造了在我的机器上闪烁的 another example

UPD2:

向 Chromium 项目报告了一个错误: https://bugs.chromium.org/p/chromium/issues/detail?id=836788

【问题讨论】:

  • 使用chrome x64 windows 10,这里没有闪烁...
  • @J.vanLangen 我添加了一些关于 GPU 的说明。你用英伟达吗?
  • 这是一款配备 Intel(R) HD Graphics 630 / NVIDIA GeForce 940MX This notebook 的笔记本电脑
  • 你试过火狐吗?
  • @J.vanLangen 是的,我试过 FF,效果很好。我的笔记本也有英特尔和英伟达 GPU,如果我用英特尔 GPU 运行 Chrome,它可以工作,如果我用 Nvidia 运行它,它会闪烁。它是 Intel HD Graphics 620 和 Nvidia 950M。

标签: javascript google-chrome webgl nvidia


【解决方案1】:

不,在这里闪烁。四边形根本没有显示。

  • 铬 65
  • Windows 10
  • 英伟达 GTX 1050

几个月以来我一直遵循这一点,从浏览器(发布)到浏览器的实现及其平台是不同的。我的经验是,您不能拥有无缓冲的“形状”跨平台。

如果您使用 bindBuffer,您将处于保存状态,请参见此处: https://stackoverflow.com/a/44448514

// added a buffer array 
// note: commented some consolelogs out, it looks nicer on stackoverflow


var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl2");
if (!gl) {
  console.log("Could not get context.");
  throw new Error();
}
var checkError = function() {
  if (gl.getError() != gl.NO_ERROR) {
    console.log("Webgl error.");
    throw new Error();
  }
}

// GL setup
gl.clearColor(0, 0, 0, 1);
gl.disable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
gl.depthMask(gl.FALSE);
gl.stencilMask(gl.FALSE);

// Shader
var vertexSource = document.getElementById("vertexShader").text;
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
// console.log("Vertex log: " + gl.getShaderInfoLog(vertexShader));

var fragmentSource = document.getElementById("fragmentShader").text;
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
// console.log("Fragment log: " + gl.getShaderInfoLog(fragmentShader));

var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
// console.log("Link log: " + gl.getProgramInfoLog(program));
checkError();
gl.useProgram(program);
var time_loc = gl.getUniformLocation(program, "time");

// CHANGED
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  0.0, 0.0,
  1.0, 0.0,
  1.0, 1.0,
  0.0, 0.0,
  1.0, 1.0,
  0.0, 1.0
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.bindVertexArray(null);

var tick = 0;

var mainLoop = function(tick) {
  tick *= 0.001;

  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 6);
  gl.uniform1f(time_loc, tick);
  window.requestAnimationFrame(mainLoop);
}

window.requestAnimationFrame(mainLoop);
<style>canvas {
  width: 100%;
  height: 500px;
}

</style>
<script id="vertexShader" type="x-shader/x-vertex">#version 300 es 
precision mediump float; 
in vec2 vertexCoord; 
uniform float time; 
smooth out vec2 pointCoord; 
void main() { 

gl_Position = vec4(vec2[](vertexCoord)[ gl_VertexID ], 0.0, 1.0); 

// for testig purposes suffix likely to fail in the past on firefox 56 windows 7 
pointCoord = vec3[3u](vec3(1.f, 1.f*sin(time), 0.f), vec3(0.0), vec3(0.0))[gl_VertexID%int(mod(time,3.))].xy; 

}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">#version 300 es 
precision mediump float; 
out vec4 outFragColor; 
smooth in vec2 pointCoord; void main() { 
outFragColor = vec4(pointCoord,0.0, 1.0); 
}
</script>
<canvas id="canvas" style="width:100vw;height:100vh;display:block"></canvas>

【讨论】:

  • 感谢您的反馈!我尝试在顶点着色器中使用缓冲区而不是硬编码的顶点数组,并得到了相同的结果。
  • 我添加了一个带有 VBO 绑定的闪烁示例:sergeyext.github.io/sergeyext/flicker_vbo.html
  • 好的。当 chrome://gpu/ 设置为 WebGL2 时,似乎出现了错误:硬件加速和 GLSL 中的平滑插值限定符(默认)可能的修复:jsfiddle.net/qdxfLj9q/7 我不知道,可能的浮点 javascript - glsl 覆盖错误,似乎 gl.uniform2f(beginPosition, 0.0, 0.0);在标准化设备坐标中插值时不为 0.0。希望对你有帮助
  • 更好的解决方法:jsfiddle.net/nabr/au06x7a8 如果您考虑一下,这是有道理的
  • 第二个变体没有解决问题,因为它包含一个错误:TypeError: Argument 1 of WebGL2RenderingContext.useProgram is not an object.。所以它只是停止循环,闪烁消失。如果我用gl.useProgram(null); 替换gl.useProgram(0);,它会以不同的频率闪烁。但是第一个变体似乎有效!谢谢!
【解决方案2】:

我的项目也有类似的问题,后来发现如果我注释掉gl.depthMask,就没有闪烁了。

我的最终解决方案是关闭开发工具,然后闪烁就会消失。

【讨论】:

  • 反正是ANGLE的BUG,所以如果你的case和我的概念不同,请向相关issue举报。
猜你喜欢
  • 1970-01-01
  • 2016-07-05
  • 2018-07-22
  • 2021-04-07
  • 1970-01-01
  • 2011-03-28
  • 2011-05-17
  • 2011-11-04
  • 2014-03-19
相关资源
最近更新 更多