Sergey
Sergey

Reputation: 8238

Webgl flickering in Chrome on Windows x64 with nvidia GPU

I see a weird flickering of some rendered geometry Chrome on Windows 10 x64 with nVidia chips. I've also tested in in Chrome for Linux, Firefox for both platforms, Android, and with Intel GPU. It works fine everywhere, except the one platform mentioned.

Minimal example looks like this:

Vertex shader:

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];
}

Fragment shader:

precision mediump float;

out vec4 outFragColor;
smooth in vec2 pointCoord;

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

GL state:

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

Rendering code:

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

Working web page with full code is available here.

What I see on affected platforms:

enter image description here

I tried webgl1 context with a vertex attribute, as there is no gl_VertexID variable in glsl 100es, and it produces the same result. I also tried to add glFinish or glFlush at the end of main loop. It reduces flicker frequency, but does not solve the problem.

What is the problem? Is there any undefined behavior in this code, so it works different ways on different platforms? Or is it a bug in Chrome or Angle?

UPD:

Following Nabr's answer, I added a VBO bound to enabled vertex attribute, and constructed another example which flickers on my machines.

UPD2:

Reported a bug to Chromium project: https://bugs.chromium.org/p/chromium/issues/detail?id=836788

Upvotes: 2

Views: 2472

Answers (2)

lex chou
lex chou

Reputation: 95

My project has similar problem, later I found if I comment the gl.depthMask, there would be no flickering.

My final solution is close the development tool, the flicker will gone then.

Upvotes: 0

nabr
nabr

Reputation: 131

no, flicker here. The quad isn't showing at all.

  • Chrome 65
  • Windows 10
  • NVidia GTX 1050

i follow this since months, the implementation from browser (release) to browser and it's platform is different. you can't have a bufferless "shape" crossplatform, my experience.

you on the save side if you bindBuffer, see here: 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>

Upvotes: 1

Related Questions