Distorted OpenGL graphics in certain models of Intel GPUs under Windows; possible causes? I'm not sure this is the best place to post this, but it definitely seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.

On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.

P.S. If you want to see the code, it's on github at https://github.com/performous/performous

Relevant files most likely would be (under game/) video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh and the actual shaders that live in data/shaders



Edit: actual drawing call, 

void VertexArray::draw(GLint mode) {
    GLErrorChecker glerror("VertexArray::draw");
    if (empty()) return;
    unsigned stride = sizeof(VertexInfo);
    GLint program;
    glGetIntegerv(GL_CURRENT_PROGRAM, &amp;program);
    GLint vertPos = glGetAttribLocation(program, "vertPos");
    GLint vertTexCoord = glGetAttribLocation(program, "vertTexCoord");
    GLint vertNormal = glGetAttribLocation(program, "vertNormal");
    GLint vertColor = glGetAttribLocation(program, "vertColor");
    glerror.check("program and attribs");
    glBindVertexArray(m_vao);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo) * size(), &amp;m_vertices.front(), GL_STATIC_DRAW);
    glerror.check("bind");
    if (vertPos != -1) {
        glEnableVertexAttribArray(vertPos);
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, position) : &amp;m_vertices[0].position;
        glVertexAttribPointer(vertPos, 3, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertTexCoord != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, texCoord) : &amp;m_vertices[0].texCoord;
        glEnableVertexAttribArray(vertTexCoord);
        glVertexAttribPointer(vertTexCoord, 2, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertNormal != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, normal) : &amp;m_vertices[0].normal;
        glEnableVertexAttribArray(vertNormal);
        glVertexAttribPointer(vertNormal, 3, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    if (vertColor != -1) {
        const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, color) : &amp;m_vertices[0].color;
        glEnableVertexAttribArray(vertColor);
        glVertexAttribPointer(vertColor, 4, GL_FLOAT, GL_FALSE, stride, ptr);
    }
    glerror.check("enable arrays");
    glDrawArrays(mode, 0, size());

    if (vertPos != -1) glDisableVertexAttribArray(vertPos);
    if (vertTexCoord != -1) glDisableVertexAttribArray(vertTexCoord);
    if (vertNormal != -1) glDisableVertexAttribArray(vertNormal);
    if (vertColor != -1) glDisableVertexAttribArray(vertColor);
    if (m_vbo) glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}


Client-side vertex struct:

struct VertexInfo {
    glmath::vec3 position{};
    glmath::vec2 texCoord{};
    glmath::vec3 normal{};
    glmath::vec4 color{ 1.0, 1.0, 1.0, 1.0 };
};
As mentioned on a comment, after talking about it on IRC, they helped me realize the bug was in the geometry shader that was being used for Stereo 3D.

Due to the way it was conceived (which was apparently a really bad idea), the shader was always compiled and linked if the hardware reported supporting OpenGL3.30 and GL_arb_viewport_array.

When the stereo3d option was disabled, via a very hacky solution, the shader was put into a "pass-through" mode which is supposed to do nothing but (still not sure if it's a bug in the shader itself or a hardware/driver issue) it was sending a lot of undefined values to the fragment shader, instead.

Here's the offending code:

#version 330 core
#extension GL_ARB_viewport_array : require

uniform float sepFactor;
uniform float z0;

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

struct vData {
    vec3 lightDir;
    vec2 texCoord;
    vec3 normal;
    vec4 color;
};

in vData vertex[];
out vData fragv;

void passthru(int i) {
    gl_Position = gl_in[i].gl_Position;
    fragv = vertex[i];
}

// Process all the vertices, applying code to them before emitting (do-while to convince Nvidia of the code getting executed)
#define PROCESS(code) i = 0; do { passthru(i); code; EmitVertex(); } while (++i &lt; 3); EndPrimitive();

void main() {
    int i = 0;
    if (sepFactor == 0.0) {
        gl_ViewportIndex = 0; PROCESS(;); // No stereo
    } else {
        gl_ViewportIndex = 1; PROCESS(gl_Position.x -= sepFactor * (gl_Position.z - z0));  // Left eye
        gl_ViewportIndex = 2; PROCESS(gl_Position.x += sepFactor * (gl_Position.z - z0));  // Right eye
    }
}


I have sort-of solved it by actually recompiling and relinking the shaders to include the geometry shader or not when stereo3d is toggled.

I've also rewritten the shader to look like this (it still produces skewed geometry but atleast akin to the first screenshot, instead of the second),

#version 330 core
#extension GL_ARB_viewport_array : require

uniform highp float sepFactor;
uniform highp float z0;

layout(triangles) in;
layout(triangle_strip, max_vertices = 6) out;

in vData {
    highp vec3 lightDir;
    highp vec2 texCoord;
    highp vec3 normal;
    highp vec4 color;
} vertices[];

out vData {
    highp vec3 lightDir;
    highp vec2 texCoord;
    highp vec3 normal;
    highp vec4 color;
} fragv;

void passthru(int vp, int i) {
        gl_Position = gl_in[i].gl_Position;
        gl_ViewportIndex = (sepFactor == 0.0) ? 0 : vp;
        gl_Position.x -= (sepFactor * (gl_Position.z - z0));
        fragv.lightDir = vertices[i].lightDir;
        fragv.texCoord = vertices[i].texCoord;
        fragv.normal = vertices[i].normal;
        fragv.color = vertices[i].color;
}

void main() {
        // Render the left eye
    int i = 0;
    do {
        passthru(1, i);
        gl_Position.x -= (sepFactor * (gl_Position.z - z0));
        EmitVertex();       
        } while (++i &lt; 3);
        EndPrimitive();

    i = 0;
        // Render the right eye
    do {
        passthru(2, i);
        gl_Position.x += (sepFactor * (gl_Position.z - z0));
        EmitVertex();       
        } while (++i &lt; 3);
        EndPrimitive();
}


In order to provide a more complete answer, in case somebody faces the same issue: I finally realized the issue appears to be with the way the loop was written. For some reason, not defining i in the loop itself resulted in trying to access undefined members of vertices

Rewriting as follows fixed the issue:

for (int i=0; i &lt; gl_in.length(); i++) {
    passthru(1, i);
    gl_Position = gl_in[i].gl_Position;
    gl_Position.x -= (sepFactor * (gl_in[i].gl_Position.z - z0));
    EmitVertex();   
}