GlGetError未捕获错误

yrefmtwq  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(149)

我正在尝试使用计算着色器使用OpenGL渲染图像。我创建了一个计算着色器并为其编程,然后创建了一个顶点着色器和片段着色器,以及一个为它们编写的程序。然后我创建一个纹理和两个三角形,并在三角形上渲染纹理。到目前为止,我一直无法让着色器正确地执行任何操作,因为glCompileShader似乎没有捕捉到着色器编译不正确时的情况,所以我无法判断哪里出了问题。我在每个编译和链接步骤之后添加了glGetError调用,以查看问题可能是什么,但它们都没有抛出错误;所发生的只是glUseProgram引发invalid operation错误。

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()
}

Vertex ShaderSource:


# 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代码(删除多余的注解和不相关的代码):

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)

很明显,我的计算着色器(请参见renderShaderSource)是这个场景中的问题,我的意思是它有不匹配的{}东西。但当我运行程序时,glUseProgram错误而不是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,)
)

为什么所有glGetError调用都没有捕获计算着色器未能编译的情况?

在Ubuntu 20.04、集成了GPU的英特尔酷睿i3-1005G1上运行的Python3.8。OpenGL 4.6 MESA 21.2.6.OpenGL视区是一个PyQt6 QOpenGLWidget

ua4mk5z4

ua4mk5z41#

无法使用glGetError获取着色器编译错误。您必须调用glGetShaderiv/glGetShaderInfoLog来获取编译错误。例如:

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

可以使用glGetProgramiv/glGetProgramInfoLog获取程序链接错误。例如:

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

我也推荐Debug Output。例如:

@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)

相关问题