【问题标题】:Sharing between QOpenGLContext and QGLWidgetQOpenGLContext 和 QGLWidget 之间的共享
【发布时间】:2013-10-12 02:38:03
【问题描述】:

问题的简短形式:如何使用我的 FBO 作为纹理在 QGLWidget 中绘制,而不只是得到一个空白的白色图像?

还有一些背景和细节……我正在使用 Qt 5.1 开发一个在 GPU 上进行图像处理的应用程序。有一个“合成器”类,它使用一个 QOffscreenSurface、一个 QOpenGLContext 和一个 QOpenGLFramebufferObject。它向 FBO 渲染了一些东西。如果应用程序在仅渲染模式下运行,则结果将写入文件。以交互方式运行,它会显示在我的 QGLWidget 子类中,即“查看器”。

如果我从 FBO 制作 QImage 并将其绘制给查看器,它就可以工作。但是,这需要从 GPU-> QImage-> 作为纹理返回到 GPU 的往返行程。理论上我应该可以直接把FBO当作贴图使用,这正是我想要的。

我试图在我的 QOpenGLContext 和 QGLWidget 的 QGLContext 之间共享,如下所示:

查看器 = 新 tl::ui::glViewer(this); 合成器 = 新 tl::playback::glCompositor(1280, 720, this); 查看器->context()->contextHandle()->setShareContext(compositor->context);

是否可以在两种类型的上下文之间共享?这是这样做的方法吗?我需要做其他事情来使用合成器中的 FBO 在查看器中绘制吗?当我直接绘制 FBO 而不是 QImage 时,我只是变得纯白色,所以我显然做错了什么。


所以我发现了我的问题。我误解了 setShareContext() 的文档,该文档指出它“在调用 create() 之前不会生效”,我错误地认为这意味着您必须在创建上下文后共享上下文。相反,必须在此之前建立共享:

viewer = new tl::ui::glViewer(this);
compositor = new tl::playback::glCompositor(512, 512, viewer->context()->contextHandle(), this);

以及我的 glCompositor 的新构造函数:

offscreenSurface = new QOffscreenSurface();
QSurfaceFormat format;
format.setMajorVersion(4);
format.setMinorVersion(0);

format.setProfile(QSurfaceFormat::CompatibilityProfile);
format.setSamples(0);
offscreenSurface->setFormat(format);
offscreenSurface->create();

context = new QOpenGLContext();
context->setShareContext(srcCtx);
context->setFormat(format);
context->create();
context->makeCurrent(offscreenSurface);

QOpenGLFramebufferObjectFormat f;
f.setSamples(0);
f.setInternalTextureFormat(GL_RGBA32F);
frameBuffer = new QOpenGLFramebufferObject(w, h, f);

将在与查看者的上下文共享的新上下文中创建一个新的 FBO。画的时候,我只是绑定 glBindTexture(GL_TEXTURE_2D, frameBuffer->texture());

我正在标记我得到的答案是正确的,即使它没有直接解决我的问题。内容非常丰富。

【问题讨论】:

    标签: opengl qt5


    【解决方案1】:

    我认为您的问题与 FBO 本身无法跨上下文共享这一事实有关。但是,您可以共享附加的数据存储(渲染缓冲区、纹理等)。

    这真的归结为这样一个事实,即 FBO 只不过是一个漂亮的前端来管理读取/绘制缓冲区的集合,FBO 本身实际上并不是一个可共享的资源。事实上,尽管有这个名字,但就 API 的其余部分而言,它们甚至都不是缓冲区对象。你有没有想过你为什么不在他们身上使用glBufferData (...)等? :)

    至关重要的一点:

    FrameBuffer 对象不是缓冲区对象;它们不包含数据存储;它们只管理连接点的状态,并为验证和绑定语义提供接口。

    这就是它们不能共享的原因,就像 顶点数组对象 不能共享,但它们的组成部分 顶点缓冲区对象 可以。

    这里的要点是:

    • 如果不存储数据,一般不是共享资源。

    您必须寻求的解决方案将涉及使用附加到您的 FBO 的渲染缓冲区和纹理。如果你不做任何疯狂的事情,比如同时在两种上下文中尝试和渲染,共享这些资源应该不会带来太多麻烦。如果你开始尝试从渲染缓冲区或纹理中读取,而其他上下文正在绘制它,它可能会变得非常难看,所以不要这样做:P


    由于 OpenGL 规范中的以下语言,您可能必须先分离纹理,然后才能在其他上下文中使用它:

    OpenGL 3.2 (Core Profile) - 4.4.3 纹理和帧缓冲区之间的反馈循环 - 第 230 页:

    当纹理对象同时用作 GL 操作的源和目标时,可能存在反馈循环。当存在反馈循环时,会产生未定义的行为。本节更详细地描述了渲染反馈循环(参见第 3.8.9 节)和纹理复制反馈循环(参见第 3.8.2 节)。

    坦率地说,您的白色纹理可能是反馈循环的结果(OpenGL 在 3.1 之前的规范版本中没有给这种情况命名,因此在 3.1 中将找到关于“反馈循环”的适当讨论+ 仅限文学作品)。因为这会调用未定义的行为,所以供应商之间的行为会有所不同。分离将消除未定义行为的根源,您应该一切顺利。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 2016-07-17
      相关资源
      最近更新 更多