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

标签 c++ opencv opengl textures

我在 HMD 上每帧渲染两个 View ,现在有点复杂,因为我使用 OpenCV 加载图像和处理中间结果,其余的是 OpenGL,但我仍然希望它能工作。我正在使用 OpenCV 3.1,如果您有任何帮助,我们将不胜感激,即使您只是提供一些建议。

申请详情:

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

这是我为每次调用 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 时,代码正在运行。如您所见,我可以运行一个渲染 View ,但尝试渲染第二个 View 将在 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。

根据specification glBindBuffer 的:

void glBindBuffer(GLenum target,
                  GLuint buffer);

While a non-zero buffer object name is bound, GL operations on the target to which it is bound affect the bound buffer object, and queries of the target to which it is bound return state from the bound buffer object. While buffer object name zero is bound, as in the initial state, attempts to modify or query state on the target to which it is bound generates an GL_INVALID_OPERATION error.

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


有人可以指出正确的方向来摆脱这个异常吗?我只是使用示例 OpenCV 代码来构建我的代码。


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

最佳答案

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

克服这个问题的一种方法是使用同步对象。定义一个同步对象并使用 glFenceSync() 或 glWaitSync()。如果您等待缓冲区完成它们的操作,这将对性能产生负面影响。这是关于 sync object 的一些信息.

检查此问题以获取有关在哪里使用 fence sync objects 的信息.

另一种方法是使用多个缓冲区并在它们之间切换连续帧,这将降低在您解除绑定(bind)时缓冲区仍在使用中的可能性。

关于c++ - 多次调用 cv::ogl::Texture2D.copyFrom() 导致 cv::Exception (-219),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42556386/

相关文章:

c++ - 具有任意作业参数的无锁作业队列

python - 如何关闭轮廓而不是边缘 - OpenCV

c# - OpenCV灰度忽略红色

c++ - 如何在 OpenGL 中高效地显示数千个具有动态颜色的相同网格?

c++ - Bullet Physics - 从网格创建 ShapeHull

C++:如何在对象构造期间调用初始化列表之外的成员构造函数?

C++ 替换系统 ("pause") 调用

c++ - 合并两个列表 C++

android - 在 OpenCV Android 或 Java 中设置 SURF 算法参数

c++ - glTexSubImage 会导致黑色纹理,而 glTexImage 效果很好