多次调用cv :: ogl :: Texture2D.copyFrom()会导致cv :: Exception(-219)

时间:2017-03-02 13:08:41

标签: c++ opencv opengl textures

我在HMD上每帧渲染两个视图,现在它很复杂,因为我使用OpenCV加载图像并处理中间结果,其余的是OpenGL,但我仍然希望它能够工作。我正在使用OpenCV 3.1,即使您只有一些建议,也会非常感谢任何帮助。

申请详情

每个视图(左眼和右眼)我将四个图像作为cv :: Mat并将它们复制到四个cv :: ogl :: Texture2D对象中。然后我将这些纹理绑定到活动的OpenGL纹理以配置我的着色器并绘制到帧缓冲区。我再次读取帧缓冲区的像素(glReadPixels())作为cv :: Mat并进行一些后处理。这个cv :: Mat(" synthView")被复制到另一个cv :: ogl :: Texture2D,它在视图的2D屏幕空间四边形上呈现。

这是我为每次调用 cv :: ogl :: Texture2D对象时记录的一些控制台输出。没有实际的代码!

// First iteration for my left eye view
colorImageTexture[LEFT].copyFrom(imageLeft, true); //view1
colorImageTexture[RIGHT].copyFrom(imageRight, true); //view1
depthImageTexture[LEFT].copyFrom(depthLeft, true); //view1
depthImageTexture[RIGHT].copyFrom(depthRight, true); //view1

colorImageTexture[i].bind(); //left
depthImageTexture[i].bind(); //left
colorImageTexture[i].bind(); //right
depthImageTexture[i].bind(); //right

synthesizedImageTexture.copyFrom(synthView, true); //frame0, left_eye done

// Second iteration for my right eye view, reusing colorImageTexture[LEFT] the first time
colorImageTexture[LEFT].copyFrom(imageLeft, true); //view2 // cv::Exception!

当我捕获异常并使用Oculus DK2而不是CV1时,代码工作正常。如您所见,我可以运行一个渲染视图,但尝试渲染第二个视图将在gl :: Buffer :: unbind(ogl :: Buffer :: PIXEL_UNPACK_BUFFER)的copyFrom方法中抛出异常。

在所有ogl :: Texture2D对象被使用一次并且第一个被"重用"之后发生异常,这意味着它不会调用ogl :: Texture2D :: create(。 ..)在copyFrom()函数中!

cv :: Exception的详细信息:

code: -219

err: The specified operation is not allowed in the current state

func: cv::ogl::Buffer::unbind

file: C:\\SDKs\\opencv3.1\\sources\\modules\\core\\src\\opengl.cpp

调用堆栈详细信息:

cv::ogl::Texture2D::copyFrom(const cv::_InputArray &arr, bool autoRelease);

从我的调用中调用,调用

ogl::Buffer::unbind(ogl::Buffer::PIXEL_UNPACK_BUFFER);

在那里,有一个OpenGL调用

gl::BindBuffer(target, 0); // target is "ogl::Buffer::PIXEL_UNPACK_BUFFER"

直接调用CV_CheckGlError();之后,抛出cv :: exception。 HAVE_OPENGL显然没有在我的代码中定义。 GL错误是GL_INVALID_OPERATION。

根据glBindBuffer的specification

void glBindBuffer(GLenum target,
                  GLuint buffer);
  

虽然绑定了非零缓冲区对象名称,但GL上的操作   它所绑定的目标会影响绑定缓冲区对象,以及   绑定到的目标的查询从绑定返回状态   缓冲对象。缓冲区对象名称为零时绑定,如中所示   初始状态,尝试修改或查询目标上的状态   绑定它会生成GL_INVALID_OPERATION错误

如果我理解正确,gl :: BindBuffer(target,0)会导致此错误,因为 buffer 参数为0并且我以某种方式改变了目标。我不确定目标究竟是什么,但也许我的glReadPixels()会干扰它?

有人能指出我正确的方向摆脱这个例外吗?我只是使用示例OpenCV代码来构造我的代码。

更新:我的着色器代码可以触发异常。如果我只输出未投影的坐标或vec4(0,0,0,1.0f),程序会因异常而中断。此外,它继续,但我无法在我的网格上看到我的颜色纹理。

2 个答案:

答案 0 :(得分:1)

鉴于您的问题中的信息,我认为问题在于对像素缓冲区对象(PBO)的异步写入。我相信你的代码试图将缓冲区绑定到0(取消绑定缓冲区),但是该缓冲区仍然被它之前的异步调用写入。

解决此问题的一种方法是使用同步对象。定义同步对象并使用glFenceSync()或glWaitSync()。如果您等待缓冲区完成其操作,则会对性能产生负面影响。以下是有关sync object的一些信息。

请查看此问题,了解有关使用fence sync objects的位置的信息。

另一种方法可能是使用多个缓冲区并在它们之间切换连续帧,这样就可以在解除绑定时使用缓冲区的可能性降低。

答案 1 :(得分:0)

实际答案是OpenCV的代码用glGetError()检查错误。如果你不在你的代码中执行此操作,cv :: ogl :: Texture2D :: copyFrom()代码将捕获错误并抛出异常。