Python: OpenGL 错误 1280 无效枚举与 glEnd()

Python: OpenGL Error 1280 Invalid Enumerant with glEnd()

我正在 Python 中使用 Numba 为我的内核和 OpenGL(下面的代码)创建一个手电筒应用程序。它非常接近完成,但是当我 运行 它时,我 运行 出现错误,glEnd 错误 1280。代码为 运行 时的终端输出也在下面。我无法弄清楚到底是什么导致了这个问题,帮助缩小问题范围会很有帮助。

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL.ARB.vertex_buffer_object import *
from OpenGL.GL.ARB.pixel_buffer_object import *

import numpy as np
import sys
import pycuda.gl as cuda_gl
import pycuda.driver as cuda_driver

import math
from numba import jit, cuda as nbcuda

W = 600
H = 600
loc = np.array([W/2, H/2], dtype = 'float32')
dragMode = False

TX = 32
TY = 32

pbo, tex, pycuda_pbo, distanceKernel = [None] * 4

class ExternalMemory(object):
    """
    Provide an externally managed memory.

    Interface requirement: __cuda_memory__, device_ctypes_pointer, _cuda_memize_
    """
    __cuda_memory__ = True

    def __init__(self, ptr, size):
        self.device_ctypes_pointer = ctypes.c_void_p(ptr)
        self._cuda_memsize_ = size

def render():
    global pycuda_pbo, pbo
    assert pbo is not None

    pycuda_pbo.unregister()

    glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, long(pbo))

    pycuda_pbo = cuda_gl.BufferObject(long(pbo))

    pbo_mapping = pycuda_pbo.map()

    source_ptr = ExternalMemory(pbo_mapping.device_ptr(), W*H * 4)

    d_out = nbcuda.devicearray.DeviceNDArray(shape = W*H * 4,
                                             strides = (1,),
                                             dtype = np.dtype('uint8'),
                                             gpu_data = source_ptr)

    blockSize = (TX, TY)
    gridSize = ((W + TX - 1)/TX, (H + TY - 1)/TY)
    distanceKernel[gridSize, blockSize](d_out, W, H, loc)

    cuda_driver.Context.synchronize()

    pbo_mapping.unmap()

    glBindTexture(GL_TEXTURE_2D, tex)

def drawTexture():
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, H, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
    glEnable(GL_TEXTURE_2D)
    glBegin(GL_TEXTURE_2D)
    glBegin(GL_QUADS)
    glTexCoord2f(0.0, 0.0); glVertex2f(0,0)
    glTexCoord2f(0.0, 1.0); glVertex2f(0,H) 
    glTexCoord2f(1.0, 1.0); glVertex2f(W,H)
    glTexCoord2f(1.0, 0.0); glVertex2f(W,0)
    glEnd()
    glDisable(GL_TEXTURE_2D)

def display():
    render()
    drawTexture()
    glutSwapBuffers()

def create_PBO():
    global pbo, pycuda_pbo

    data = np.zeros((W*H,4), dtype = 'uint8')

    pbo = glGenBuffers(1)   
    glBindBuffer(GL_ARRAY_BUFFER, pbo)
    glBufferData(GL_ARRAY_BUFFER, data, GL_DYNAMIC_DRAW)
    glBindBuffer(GL_ARRAY_BUFFER, 0)
    pycuda_pbo = cuda_gl.BufferObject(long(pbo))

def create_texture():
    global tex

    tex = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, tex)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

def exitfunc():
    glBindBuffer(GL_ARRAY_BUFFER, long(pbo))
    glDeleteBuffers(1, long(pbo));
    glBindBuffer(GL_ARRAY_BUFFER, 0)
    pbo = None

    glDeleteTextures(tex);
    tex = None

def keyboard(key, x, y):
    if key == '3': #3 is escape key
        exit()
    elif key == 'a':
        dragMode = not dragMode
    elif key == 27:
        exit()
    glutPostRedisplay()

def mouseMove(x, y):
    if dragMode == True:
        loc[0] = x
        loc[1] = y
    glutPostRedisplay()

def mouseDrag(x, y):
    if dragMode == False:
        loc[0] = x
        loc[1] = y
    glutPostRedisplay()

def handleSpecialKeypress(key, x, y):
    if key == GLUT_KEY_LEFT:
        loc[0] -= DELTA
    if key == GLUT_KEY_RIGHT:
        loc[0] += DELTA
    if key == GLUT_KEY_UP:
        loc[1] -= DELTA
    if key == GLUT_KEY_DOWN:
        loc[1] += DELTA
    glutPostRedisplay()

def printInstructions():
    print "flashlight instructions"
    print "a: toggle mouse tracking mode"
    print "arrow keys: move ref location"
    print "esc: close graphics window"

def main():
    global cuda_gl, cuda_driver, distanceKernel

    printInstructions();
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE)
    glutCreateWindow("flashlight: distance image display app")
    gluOrtho2D(0, W, H, 0)
    glutDisplayFunc(display)
    glutKeyboardFunc(keyboard)
    glutSpecialFunc(handleSpecialKeypress)
    glutPassiveMotionFunc(mouseMove)
    glutMotionFunc(mouseDrag)

    create_texture()

    #Sets up GL interop
    import pycuda.gl.autoinit
    import pycuda.gl
    cuda_gl = pycuda.gl
    cuda_driver = pycuda.driver

    # force compilation here
    @nbcuda.jit(device = True)
    def clip(n):
        if n > 255:
            n = 255
        elif n < 0:
            n = 0
        return n

    @nbcuda.jit("(uint8[::1], int32, int32, float32[::1])")
    def distanceKernel(d_out, w, h, pos):
        c = nbcuda.blockIdx.x*nbcuda.blockDim.x + nbcuda.threadIdx.x
        r = nbcuda.blockIdx.y*nbcuda.blockDim.y + nbcuda.threadIdx.y
        i = (r*w + c) * 4

        if c >= w or r >= h:
            return

        d = math.sqrt((c - pos[0]) * (c - pos[0]) + (r - pos[1]) * (r - pos[1]))

        intensity = clip(255 - d)

        d_out[i] = intensity
        d_out[i+1] = intensity
        d_out[i+2] = 0
        d_out[i+3] = 255

    create_PBO()

    glutMainLoop()
    atexit(exitfunc)

main()

这是终端输出的 OpenGL 运行s

flashlight instructions
a: toggle mouse tracking mode
arrow keys: move ref location
esc: close graphics window
cuInit
cuDeviceGetCount
cuDeviceGetCount
cuDeviceGet
cuGLCtxCreate
cuCtxGetDevice
cuGLRegisterBufferObject
cuGLUnregisterBufferObject
cuGLRegisterBufferObject
cuGLMapBufferObject
cuCtxSynchronize
cuGLUnmapBufferObject
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 314, in 'calling callback function'
  File "stackcode.py", line 80, in display
    drawTexture()
  File "stackcode.py", line 75, in drawTexture
    glEnd()
  File "latebind.pyx", line 44, in OpenGL_accelerate.latebind.Curry.__call__ (src/latebind.c:1201)
  File "/home/uchytilc/anaconda2/lib/python2.7/site-packages/OpenGL/GL/exceptional.py", line 46, in glEnd
    return baseFunction( )
  File "/home/uchytilc/anaconda2/lib/python2.7/site-packages/OpenGL/platform/baseplatform.py", line 402, in __call__
    return self( *args, **named )
  File "errorchecker.pyx", line 53, in OpenGL_accelerate.errorchecker._ErrorChecker.glCheckError (src/errorchecker.c:1218)
OpenGL.error.GLError: GLError(
    err = 1280,
    description = 'invalid enumerant',
    baseOperation = glEnd,
    cArguments = ()
)
cuCtxPopCurrent
cuCtxPushCurrent
cuGLUnregisterBufferObject
cuGLUnregisterBufferObject failed with code 1
PyCUDA WARNING: a clean-up operation failed (dead context maybe?)
cuGLUnregisterBufferObject failed: invalid argument
cuCtxPopCurrent
cuCtxPushCurrent
cuCtxDetach

问题可能来自这一行:

glBegin(GL_TEXTURE_2D)

glBegin 不允许此参数。它只接受原始类型(TEXTURE_2D 不是)。查看 documentation 关于支持的值。