QOpenGLWidget 粉碎显示

Posted

技术标签:

【中文标题】QOpenGLWidget 粉碎显示【英文标题】:QOpenGLWidget crushes on shown 【发布时间】:2019-08-27 09:33:33 【问题描述】:

我在QMainWindow 实例w 中嵌入了QOpenGLWidget。编译没问题。但是在调试时,程序在w.show()处崩溃。

错误对话框显示:

在 0x000007FEE5AF4469 (d3d11sdklayers.dll) 处引发异常 TestQtOpenGL.exe: 0xC0000005: 访问冲突读取位置 0x00000806E5B03A98.

调用栈是:

d3d11sdklayers.dll!000007fee5af4469()   Unknown
d3d11sdklayers.dll!000007fee5ad2971()   Unknown
libGLESv2d.dll!000007fed7d58a8d()   Unknown
libGLESv2d.dll!000007fed7d56313()   Unknown
libGLESv2d.dll!000007fed7d55521()   Unknown
libGLESv2d.dll!000007fed7b2308a()   Unknown
libGLESv2d.dll!000007fed7b24f1b()   Unknown
libGLESv2d.dll!000007fed79dbba8()   Unknown
libGLESv2d.dll!000007fed7bf2678()   Unknown
libEGLd.dll!000007feecd1209d()  Unknown
qwindowsd.dll!000007fed86752ac()    Unknown
qwindowsd.dll!000007fed8674906()    Unknown
qwindowsd.dll!000007fed8602d55()    Unknown
qwindowsd.dll!000007fed8602999()    Unknown
qwindowsd.dll!000007fed860223b()    Unknown
qwindowsd.dll!000007fed86020fe()    Unknown
Qt5Guid.dll!000007fed93a18a0()  Unknown
Qt5Widgetsd.dll!0000000057d55dc2()  Unknown
Qt5Widgetsd.dll!0000000057d97037()  Unknown
Qt5Widgetsd.dll!0000000057d95d45()  Unknown
Qt5Widgetsd.dll!0000000057d439f6()  Unknown
Qt5Widgetsd.dll!0000000057d95fa9()  Unknown
Qt5Widgetsd.dll!0000000057ce700e()  Unknown
Qt5Widgetsd.dll!0000000057ce46c6()  Unknown
Qt5Cored.dll!0000000058c15af6() Unknown
Qt5Cored.dll!0000000058c20c32() Unknown
Qt5Widgetsd.dll!0000000057d520b0()  Unknown
Qt5Widgetsd.dll!0000000057d523f0()  Unknown
Qt5Widgetsd.dll!0000000057d3dd71()  Unknown
Qt5Widgetsd.dll!0000000057d3e0c9()  Unknown
Qt5Widgetsd.dll!0000000057d50b12()  Unknown
Qt5Widgetsd.dll!0000000057d52411()  Unknown
Qt5Widgetsd.dll!0000000057d3dd71()  Unknown
Qt5Widgetsd.dll!0000000057d3e0c9()  Unknown
> TestQtOpenGL.exe!main(int argc, char * * argv) Line 9 C++ TestQtOpenGL.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 104    C++
[External Code]

一个演示:

// main.cpp

#include "TestQtOpenGL.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])


    /*
     * According to some solutions, I have tried the following
     * codes, but no use.
     */
    // QSurfaceFormat format; format.setDepthBufferSize(24);
    // format.setStencilBufferSize(8);
    // format.setVersion(4, 3);
    // format.setProfile(QSurfaceFormat::CoreProfile);
    // QSurfaceFormat::setDefaultFormat(format);

    QApplication a(argc, argv);
    TestQtOpenGL w;
    w.show();
    return a.exec();


// TestQtOpenGL.h
#pragma once
#include <QtWidgets/QMainWindow>
#include <qopenglwidget.h>

class TestQtOpenGL : public QMainWindow

    Q_OBJECT
public:
    TestQtOpenGL(QWidget *parent = Q_NULLPTR);
private:
    QOpenGLWidget *glwidget;
;
// TestQtOpenGL.cpp
#include "TestQtOpenGL.h"

TestQtOpenGL::TestQtOpenGL(QWidget *parent)
    : QMainWindow(parent)

    setFixedSize(800, 600);
    glwidget = new QOpenGLWidget(this);
    setCentralWidget(glwidget);


环境:

Qt 5.9.4 msvc2015 64bit Visual Studio 2015 Windows 7

根据@Aleph0 的建议,我使用 [Visual Studio]->[Debug]->[Windows]->[Modules] 调查了加载的模块。但我没有发现任何可疑的 DLL。模块列表上传here。

【问题讨论】:

尝试创建一个继承自 QOpenGLWidget 的类,然后可以在 MainWindow 中使用它。 Qt5 有一个很好的文档如何做到这一点:doc.qt.io/qt-5/qopenglwidget.html#details 我不知道这是否会导致您的问题,但我从未见过像您这样的实现 @RoQuOTriX 谢谢。事实上,我在另一个复杂的项目中发现了这个问题。它在另一台 Windows 10 计算机上成功运行,但在我的计算机上崩溃了。在该项目中,实现了QOpenGLWidget 的子类。但它破坏了程序。所以我创建了这个简单的演示来展示这个问题。我认为在这个演示中继承 QOpenGLWidget 并不能解决问题,但如果有不同,我会尝试报告。 如果它只在特定的电脑上崩溃,你应该检查你的驱动程序和 OpenGL 实现。更新驱动程序通常可以避免此类问题 @RoQuOTriX 没错!更新驱动程序解决了我的问题。奇怪的是我们都没有意识到这是司机的问题。 【参考方案1】:

受@RoQuOTriX 的启发,我用一种非常简单的方式解决了这个问题:

在 Windows 设备管理器中更新图形驱动程序。然后重新启动。重新编译,问题就解决了。

请注意,我的显卡是 Intel HD Graphics。如果您使用独立显卡,则可能需要从设备提供商处获取显卡驱动程序更新。

【讨论】:

【参考方案2】:

阅读QOpenGLWidget 的文档后,我发现了以下段落,这对您可能很重要:

注意:在构造之前调用 QSurfaceFormat::setDefaultFormat() QApplication 实例在某些平台上是必需的(例如, macOS) 请求 OpenGL 核心配置文件上下文时。这是为了 确保上下文之间的资源共享保持正常运行 内部上下文是使用正确的版本和配置文件创建的。

也许您应该重写您的main.cpp 并将setDefaultFormat 放在QApplication 对象的创建之前。

#include "TestQtOpenGL.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])

    // This should be come first on some platforms
    QSurfaceFormat format; format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(4, 3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    QSurfaceFormat::setDefaultFormat(format);

    QApplication a(argc, argv);

    TestQtOpenGL w;
    w.show();
    return a.exec();

在考虑了您的调用堆栈后,我发现有一个libGLESv2d.dll,它没有在我加载的模块中列出。我尝试通过设置切换到OpenGL ES

#include "TestQtOpenGL.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])

    QSurfaceFormat format; format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(4, 3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    format.setRenderableType(QSurfaceFormat::RenderableType::OpenGLES);
    QSurfaceFormat::setDefaultFormat(format);
    // Setting surface format before creation of QApplication

    QApplication a(argc, argv);  

    TestQtOpenGL w;
    w.show();
    return a.exec();

这导致了错误消息:

QOpenGLWidget: Failed to create context
QOpenGLWidget: Failed to create context
qt.qpa.backingstore: composeAndFlush: QOpenGLContext creation failed
qt.qpa.backingstore: composeAndFlush: makeCurrent() failed
qt.qpa.backingstore: composeAndFlush: makeCurrent() failed

我建议您将 RenderableType 更改为绘制 OpenGL 并看看会发生什么。

【讨论】:

感谢您的建议。我已经使用 [Visual Studio]->[Debug]->[Windows]->[Modules] 调查了加载的模块。但我没有发现任何可疑的 DLL。模块列表上传here。 再次感谢。我确实尝试过这种解决方法,但没有用。这些代码在我的main.cpp 中被注释掉了。此外,我的平台是 Windows,而不是 Mac OS 等其他平台。所以我认为那张纸条不适合我的情况。伤心.... @cosmozhang:我刚刚有了另一个想法!我刚刚扩展了我的帖子。也许你可以试试这个,你也可以展示你加载的模块。 这是一个绝妙的发现!但它也失败了。有趣的是,在设备管理器中更新我的图形驱动程序(让 Windows 自动搜索和更新驱动程序)解决了我的问题。

以上是关于QOpenGLWidget 粉碎显示的主要内容,如果未能解决你的问题,请参考以下文章

在qt的QOpenGLWidget开启opengl的抗锯齿

Qt OpenGL (QOpenGLWidget) - 简单三角形

添加到 QGraphicsScene 时如何更新 OpenGL 绘图(QOpenGLWidget)?

Qt 5.5 QOpenGLWidget链接错误未链接任何openGL调用

加不了openglwidget

将OpenGL帧缓冲区对象与Qt(QOpenGLWidget)一起使用,绘制到帧缓冲区时如何禁用多重采样