glGetError not catching errors

Question:

I am trying to render images with OpenGL using a compute shader. I create a compute shader and program for it, then a vertex shader and fragment shader, as well as a program for them. I then create a texture and two triangles and render the texture on the triangles. So far, I have been unable to get the shaders to do anything properly, since glCompileShader seems to not catch when shaders compile incorrectly, so I can’t tell what’s wrong. I have added glGetError calls after each of my compiling and linking steps to see what the problem might be, but none of them throw errors; all that happens is glUseProgram raises an invalid operation error.

renderShaderSource:

#version 460 core
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(rgba32f, binding = 0) uniform image2D screen;

void main()
}

vertexShaderSource:

#version 460 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 uvs;
out vec2 UVs;

void main()
{
    gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
    UVs = uvs;
}

fragmentShaderSource:

#version 460 core
out vec4 FragColor;
uniform sampler2D screen;
in vec2 UVs;

void main()
{
    FragColor = texture(screen, UVs);
}

Python code (with excess comments and irrelevant code removed):

class GLWidget(QOpenGLWidget):
    width = 100
    height = 100

    def initializeGL(self):
        print('--initializeGL--')
        print('GL version', glGetString(GL_VERSION))
        # Render shader
        renderShader = glCreateShader(GL_COMPUTE_SHADER)
        glShaderSource(renderShader, renderShaderSource)
        glCompileShader(renderShader)
        status = glGetError()
        if status != GL_NO_ERROR: raise RuntimeError('Error {} compiling renderShader'.format(status))

        # Render program
        renderProgram = glCreateProgram()
        glAttachShader(renderProgram, renderShader)
        glLinkProgram(renderProgram)
        status = glGetError()
        if status != GL_NO_ERROR: raise RuntimeError('Error {} linking renderProgram'.format(status))

        # Vertex shader
        vertexShader = glCreateShader(GL_VERTEX_SHADER)
        glShaderSource(vertexShader, vertexShaderSource)
        glCompileShader(vertexShader)
        status = glGetError()
        if status != GL_NO_ERROR: raise RuntimeError('Error {} compiling vertexShader'.format(status))

        # Fragment shader
        fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
        glShaderSource(fragmentShader, fragmentShaderSource)
        glCompileShader(fragmentShader)
        status = glGetError()
        if status != GL_NO_ERROR: raise RuntimeError('Error {} compiling fragmentShader'.format(status))

        # Display program
        displayProgram = glCreateProgram()
        glAttachShader(displayProgram, vertexShader)
        glAttachShader(displayProgram, fragmentShader)
        glLinkProgram(displayProgram)
        status = glGetError()
        if status != GL_NO_ERROR: raise RuntimeError('Error {} linking displayProgram'.format(status))

        # Texture to render to
        screenTex = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, screenTex)
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, self.width, self.height)
        glBindImageTexture(0, screenTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F)

        # Shape to render texture on
        self.vertices = numpy.array([
            -1.0, -1.0, 0.0, 0.0, 0.0,
            -1.0, 1.0, 0.0, 0.0, 1.0,
            1.0, 1.0, 0.0, 1.0, 1.0,
            1.0, -1.0, 0.0, 1.0, 0.0
        ], dtype='float32')

        # Buffers for rendering shape
        vertexArray = glGenVertexArrays(1)
        vertexBuffer = glGenBuffers(1)

        glBindVertexArray(vertexArray)

        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer)
        glBufferData(GL_ARRAY_BUFFER, 4 * len(self.vertices), self.vertices, GL_STATIC_DRAW)

        glVertexAttribPointer(0, 3, GL_FLOAT, False, 4 * 3, None)
        glEnableVertexAttribArray(0)

        # Unbind from the vertex buffer and vertex array
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindVertexArray(0)

        self.renderProgram = renderProgram
        self.displayProgram = displayProgram
        self.vertexArray = vertexArray
        self.vertexBuffer = vertexBuffer

    def resizeGL(self, width, height):
        print('--resizeGL--')
        self.width = width
        self.height = height

        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-1, 1, 1, -1, -1, 1)

    def paintGL(self):
        print('--paintGL--')
        # Run render portion
        glUseProgram(self.renderProgram)
        glDispatchCompute(self.width, self.height, 1)
        glMemoryBarrier(GL_ALL_BARRIER_BITS)

        # Run display portion
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)
        glUseProgram(self.displayProgram)
        glBindVertexArray(self.vertexArray)
        glDrawArrays(GL_TRIANGLES, 0, 6)

It’s fairly clear that my compute shader (see renderShaderSource) is the problem in this scenario, I mean it’s got mismatched { } things. But when I run the program, glUseProgram errors instead of glGetError:

--initUI--
--initializeGL--
GL version b'4.6 (Compatibility Profile) Mesa 21.2.6'
--resizeGL--
--paintGL--
Traceback (most recent call last):
  File "gl.py", line 146, in paintGL
    glUseProgram(self.renderProgram)
  File "/home/aweso/.local/lib/python3.8/site-packages/OpenGL/platform/baseplatform.py", line 415, in __call__
    return self( *args, **named )
  File "/home/aweso/.local/lib/python3.8/site-packages/OpenGL/error.py", line 230, in glCheckError
    raise self._errorClass(
OpenGL.error.GLError: GLError(
    err = 1282,
    description = b'invalid operation',
    baseOperation = glUseProgram,
    cArguments = (2,)
)
--paintGL--
Traceback (most recent call last):
  File "gl.py", line 146, in paintGL
    glUseProgram(self.renderProgram)
  File "/home/aweso/.local/lib/python3.8/site-packages/OpenGL/error.py", line 230, in glCheckError
    raise self._errorClass(
OpenGL.error.GLError: GLError(
    err = 1282,
    description = b'invalid operation',
    baseOperation = glUseProgram,
    cArguments = (2,)
)

Why did none of the glGetError calls catch that the compute shader failed to compile?

Python 3.8 on Ubuntu 20.04, Intel Core i3-1005G1 with integrated GPU. OpenGL 4.6 Mesa 21.2.6. OpenGL viewport is a PyQt6 QOpenGLWidget

Asked By: AwesomeCronk

||

Answers:

Shader compile errors can’t be get with glGetError. You have to call glGetShaderiv/glGetShaderInfoLog to get the compile errors. e.g.:

glCompileShader(renderShader)
if not glGetShaderiv(renderShader, GL_COMPILE_STATUS):
    raise RuntimeError(glGetShaderInfoLog(renderShader).replace(b'\n', b'n'))

Program link errors can be get with glGetProgramiv/glGetProgramInfoLog. e.g.:

glLinkProgram(displayProgram)
if not glGetProgramiv(displayProgram, GL_LINK_STATUS):
    raise RuntimeError(glGetProgramInfoLog(displayProgram).replace(b'\n', b'n'))

I also recommend Debug Output. e.g.:

@GLDEBUGPROC
def __CB_OpenGL_DebugMessage(source, type, id, severity, length, message, userParam):
    msg = message[0:length]
    print(msg.decode("utf-8"))
glDebugMessageCallback(__CB_OpenGL_DebugMessage, None)
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, None, GL_TRUE)
glEnable(GL_DEBUG_OUTPUT)
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS)
Answered By: Rabbid76
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.