【问题标题】:how to delete texture object under different thread with share qopenglcontext, on ubuntu20.04 with mesa driver如何使用共享 qopenglcontext 在 ubuntu20.04 上使用 mesa 驱动程序删除不同线程下的纹理对象
【发布时间】:2021-05-31 02:05:52
【问题描述】:

我有一个名为“ShowVideo”的类对象,它继承自 QOpenGLWidget 和 QOpenGLFunctions。 在“initializeGL()”函数中,我创建了一个工作线程和一个子渲染器对象,在子渲染器对象中,我创建了一个 QOpenGLContext 对象,它使用 QOpenGLWidget 上下文调用 setShareContext 进行纹理共享。

在“ShowVideo”类下,有一个名为“onSceneSwitch”的成员函数(需要多次调用),其中我会先释放所有子渲染器的opengl资源(QOpenGLFramebufferObject、纹理等)(通过调用glDeleteTextures),然后重新创建 opengl 资源(例如,使用 glGenTextures)。

在带有nvidia显卡的Windows系统上,它工作正常(opengl资源已成功释放,纹理对象名称在“glDeteleTextures”之后可以重复使用,即使共享opengl上下文没有被破坏)。

但是在 ubuntu20.04 上使用 mesa 显卡驱动,opengl 资源无法释放。 (如果我使用 glGenTextures 来生成纹理对象,每次调用“onSceneSwitch”时都会得到新的纹理对象 ID,从而导致快速超过“GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS”)

代码示例如下:

class ShowVideo : public QOpenGLWidget,protected QOpenGLFunctions
{

protected:
    void initializeGL() 

{
    m_mainRendererContext = new QOpenGLContext();
    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setRedBufferSize(8);
    format.setBlueBufferSize(8);
    format.setGreenBufferSize(8);
    format.setAlphaBufferSize(8);
    format.setVersion(2, 0);
    format.setProfile(QSurfaceFormat::CoreProfile);
    m_mainRendererContext->setFormat(format);
    m_mainRendererContext->setShareContext(this->context());
    m_mainRendererContext->create();

    m_mainRenderThread = new QThread;
    m_mainRenderer = new MainRenderer();
    m_mainRenderer->moveToThread(m_mainRenderThread);

    m_mainRendererContext->moveToThread(m_mainRenderThread);
    m_mainRenderer->setGLContext(m_mainRendererContext);
}

    void onSceneSwitch()
{
    emit m_mainRenderer->releaseGLResourceSignal();

    ...

    emit m_mainRenderer->reCreateGLResourceSignal();
}

};




class MainRenderer : public QObject, protected QOpenGLFunctions
{
private:
    GLuint m_texUnit;
    QOpenGLFramebufferObject *m_Fbo = nullptr;

    QOpenGLContext *mContext;
    QOffscreenSurface *mSurface

public:

void setGLContext(QOpenGLContext *context)
{
    m_Context = context;
}

    void releaseGLResource()
{
    mContext->makeCurrent(mSurface);
    glDeleteTextures(1, &m_texUnit);
    delete m_Fbo;
    m_Fbo = 0;

}


void reCreateGLResource()
{
    mContext->makeCurrent(mSurface);
    glGenTextures(1, &m_texUnit);
    qDebug() << "the m_texUnit is : " << m_texUnit;
    m_Fbo = new QOpenGLFramebufferObject (size, format);
}

}

例如,如果“m_texUnit”在 glGenTextures 之后初始化时为 3,在 Windows 系统上,我每次在“onSceneSwitch”中的 glGenTextures 之后都可以得到 3;但是在ubuntu系统中,因为两个openGLcontext对象是共享的,所以纹理对象名是无法释放的。

顺便说一下,我设置两个openglContext共享的原因是,在类“ShowVideo”的成员函数“paintGL”中,我使用“MainRenderer”中生成的纹理id进行渲染。

【问题讨论】:

    标签: c++ qt opengl


    【解决方案1】:

    “如果我使用 glGenTextures 来生成纹理对象,我每次都会获得新的纹理对象 ID”——据我所知,这是 OpenGL 实现的正确行为。不能保证 glGenTexture 会返回之前删除的 id。正确的方法是重用纹理对象,而不是频繁地创建和销毁它们(注意,纹理等于纹理数据;您可以随时更改纹理包含的内容)。

    顺便说一句,GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 在这里无关紧要 - 它不是您可以创建的纹理数量(这仅受诸如 sizeof(GLuint)、可用内存或特定于实现的限制等技术因素的限制),而是活动的数量 纹理单位(参见 glActiveTexture),即大致可以由着色器程序同时使用的纹理的最大数量。

    【讨论】:

    • 谢谢。在我的应用程序中,有时我需要同时创建许多子渲染器。而在“onSceneSwitch”函数中,我需要删除所有当前的子渲染器,然后创建新的子渲染器,所以在切换过程中会调用glDeleteTextures和glGenTextures(包括一些需要删除和重新创建的QOpenGLFramebufferObject) . .在我的机器中,“GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS”是192。所以切换几次后,glGenTextures的结果会超过192,之后glActiveTexture就不会成功。
    • @marswei 您可能应该重组代码,以便它重用渲染器而不是重新创建它们。如果这不是一个选项,您至少可以创建一些实现纹理重用的纹理管理器,并使用它而不是手动 glGenTextures/glDeleteTextures。至于glActiveTexture函数,它的参数是不是纹理id,而是纹理图像单元,与无关 到 glGenTextures 生成的 id。请阅读khronos.org/opengl/wiki/Texture#Texture_image_units
    • 非常感谢。我现在正在重组我的代码以实现纹理重用。至于我之前的代码在windows上运行正常,在ubuntu上不行,是不是因为windows驱动和mesa驱动的opengl实现不同?
    • @marswei 老实说,考虑到您已经使用纹理 ID 作为 glActiveTexture 的参数(正确的参数是常量 GL_TEXTURE0、GL_TEXYURE1、...),它应该会引发 GL_INVALID_ENUM 错误,并且可能纯粹是巧合和运气(OpenGL中的常见情况)。但是,是的,即使仍然符合 OpenGL 规范,OpenGL 的不同实现也可能具有截然不同的行为(例如,关于错误失败)。
    猜你喜欢
    • 2019-08-03
    • 2014-08-12
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2015-10-01
    • 1970-01-01
    • 2013-06-03
    相关资源
    最近更新 更多