工具/软件:
您好、
我使用 Linux 6.1.33 和 QT 版本 QT5.15.7 通过 QML 接口进行 Qt 应用开发。 当前的主要现象是、运行 QML 应用一段时间后、使用 ToolButton 和 Canvas 等画布区域会出现问题、从而导致图像显示异常。 接口的情况是,程序运行后,整个接口的输出通道会发生变化,输出通道 (Canvs canvas) 会实时更新和刷新,并且制冷温度和 UV (ToolButton) 透明度会定期变化。 其他位置保持不变。 下图展示了该现象
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:
您好、
我使用 Linux 6.1.33 和 QT 版本 QT5.15.7 通过 QML 接口进行 Qt 应用开发。 当前的主要现象是、运行 QML 应用一段时间后、使用 ToolButton 和 Canvas 等画布区域会出现问题、从而导致图像显示异常。 接口的情况是,程序运行后,整个接口的输出通道会发生变化,输出通道 (Canvs canvas) 会实时更新和刷新,并且制冷温度和 UV (ToolButton) 透明度会定期变化。 其他位置保持不变。 下图展示了该现象
您好、
以下是分析过程、源代码跟踪过程和数据
使用屏幕 1280x800 (LVDS)
修改 Qt 源代码、并在绑定后读取纹理数据。
QT Opengles 纹理相册管理负责创建和分配纹理、创建一个大的纹理块 (2048x1024) 作为一个整体、然后使用子纹理进行图像数据存储和分配。
qtdeclative/quick/scenegraph/util/qsgopenglatlasteture.cpp src
目前,在纹理绑定后,从 GPU 读取纹理缓冲区的操作被添加。 出现问题时、单击“应用“将读取创建子纹理以保存图像的所有图像数据。 正常运行时、图像读取是正常的、但出现异常时、GPU 缓冲区也会出现问题。
将纹理保存到图像代码、如下所示
if(qApp->property("save_image") =="1"){ GLuint fbo; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0); int count =g_textures.size(); qDebug()<<"save texture image ++++++++++++++++++++++++++++++++++++++++++++++++++"<<count; for(int i=0; i<count; i++){ QRect r= g_textures[i]->atlasSubRect(); int x = r.x(); int y = r.y(); int w = r.width(); int h = r.height(); GLubyte* pixels = (GLubyte*)malloc(w * h * 4); glReadPixels(x, y, w, h, GL_BGRA, GL_UNSIGNED_BYTE, pixels); QImage img(pixels, w, h, QImage::Format_ARGB32_Premultiplied); qDebug() <<"text_save ="<<i<< img.save(QString("/home/root/image/%1.png").arg(i)); free(pixels); } glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbo); qApp->setProperty("save_image", "0"); }
在纹理管理中、您可以在每次更新或创建纹理时查看纹理更新日志。
QML:符合家庭条件
qt.scenegraphy.time.texture: atlastexture 上传时间: 1ms (100x80)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (48x48)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (60x60)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (60x60)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (60x60)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (23x23)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (114x114)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (91x91)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (91x91)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture:atlastexture 上传时间:0ms (40x40)
Qt.scenegraphy.time.texture: atlasTexture 上传时间: 0ms (40x40)/*应用程序顶部有四个按钮,左侧有三个按钮(65x65 是纹理的大小)*/
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (65x65)/*关于 ToolButton 图标的大小*/
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (65x65)/*设置 ToolButton 图标*/
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (65x65)/*维护 ToolButton 图标*/
Qt.scenegraphy.time.texture: atlastexture 上传时间: 0ms (60x60)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 5 毫秒 (227x168 )/*进入走廊*/
Qt.scenegraphy.time.texture: atlastexture 上传时间: 2 毫秒 (227x168 )/*输出走廊*/
从日志中可以看出,当纹理更新时,该纹理缓冲区将被释放并重新分配,即使纹理中新分配的子纹理的位置偏移和大小从未改变,且没有 65x65 的修改日志信息)纹理大小已在未来收到。 因此、改变 ToolButton 图标大小是很奇怪的。
更新画布(走廊)绘图一次的过程。
tlasBase:删除删除纹理 RECT= QRect (218,0229x170)
AtlasBase:删除纹理 RECT= QRect (218,170229x170)
Qt.scenegrap.time.texture: atlastexture 上传时间: 3mS (227x168)
Qt.scenegraphy.time.texture: atlastexture 上传时间: 2 毫秒 (227x168)
在 QT 事件阶段从 QT 源代码创建 2048 * 1024 纹理缓冲区。 有纹理分配时、指定位置和大小、然后将数据复制到此区域。
在 QT 中处理纹理数据上传功能。
void Atlas::uploadBgra(Texture *texture) { QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); const QRect &r = texture->atlasSubRect(); QImage image = texture->image(); if (image.isNull()) return; if (image.format() != QImage::Format_ARGB32_Premultiplied && image.format() != QImage::Format_RGB32) { image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); } if (m_debug_overlay) { QPainter p(&image); p.setCompositionMode(QPainter::CompositionMode_SourceAtop); p.fillRect(0, 0, image.width(), image.height(), QBrush(QColor::fromRgbF(0, 1, 1, 0.5))); } QVarLengthArray<quint32, 512> tmpBits(qMax(image.width() + 2, image.height() + 2)); int iw = image.width(); int ih = image.height(); int bpl = image.bytesPerLine() / 4; const quint32 *src = (const quint32 *) image.constBits(); quint32 *dst = tmpBits.data(); // top row, padding corners dst[0] = src[0]; memcpy(dst + 1, src, iw * sizeof(quint32)); dst[1 + iw] = src[iw-1]; funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst); // bottom row, padded corners const quint32 *lastRow = src + bpl * (ih - 1); dst[0] = lastRow[0]; memcpy(dst + 1, lastRow, iw * sizeof(quint32)); dst[1 + iw] = lastRow[iw-1]; funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + ih + 1, iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst); // left column for (int i=0; i<ih; ++i) dst[i] = src[i * bpl]; funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst); // right column for (int i=0; i<ih; ++i) dst[i] = src[i * bpl + iw - 1]; funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + iw + 1, r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst); // Inner part of the image.... if (bpl != iw) { int sy = r.y() + 1; int ey = sy + r.height() - 2; for (int y = sy; y < ey; ++y) { funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, y, r.width() - 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, src); src += bpl; } } else { funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src); } }
日志中的一触式数据
轻触一次可打印当前上传的数据信息。
Krunal、
我不确定 AM62X 是否具有 与 TDA4X 相同的 GPU 驱动程序错误?
您好、
我认为 GPU 问题的原因如下:
1.使用 Alta 纹理图册进行处理时,将创建一个空纹理(即共享纹理 ID 的大缓冲区),用于管理和存储整个显示的图像。 每个图像用作区域(即子纹理)的缓冲区、当修改某个图像时、相应的区域(即子纹理)将会更新。 当 GPU 负载较高时、修改某个子纹理区域会导致缓冲区中的其他未修改纹理区域数据被修改。
2.使用多个图像创建纹理时(为每个图像指定纹理 ID)、以这种方式绘制的数据是正常的。
基于现象 1 和 2、我认为当 GPU 压力高时、驱动程序处理子纹理更新时未修改子纹理区域的纹理数据将被清除或修改。
3.我目前保持原始测试环境不变、将 GPU 相关的驱动程序和固件更新为 SDK 9.2、此问题将不再重现。
QT5.15.7 没有 QT-DISABLE_SHADLER-DISKACHE=1 环境变量。 我们尝试修改环境变量以导出 QML-DISABLE-DISKACHE=1 以进行测试。