1

我有大约六个文件,每个文件 250 KB 到 500 KB。这些文件中的每一个都有多个 QImage;每个文件大约 400 张 128x64 的图像。加载到内存的速度约为 60MB/s(因为 OpenGL 需要将 PNG 解压缩为它自己的格式)。

有没有可能加快这个过程?它非常缓慢,因为我有一个演出要填补。

QFile file("file.ucv");

if (file.open(QIODevice::ReadOnly)) {
    qDebug() << "Read from hdd";

    QDataStream r(&file);
    r.setVersion(QDataStream::Qt_4_3);

    QImage t;

    int i = maxPics * place;
    glGenTextures(maxPics, &texture[i]);
    for (int y = 0; y < yNrPics; y++)
        for (int x = 0; x < xNrPics; x++, i++) {

            // Write to precomputed object
            r >> t;

            glBindTexture( GL_TEXTURE_2D, texture[i] );
            glTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
        }

分析器发现这条线是最消耗量的:

            glTexImage2D( GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );

将压缩更改为非压缩可以节省一些时间,但仍然不多。

加载的 QImage 为 GL 格式。

4

2 回答 2

2

确保您确定您的数据:

  • 即确保分析器显示挂钟,而不仅仅是 CPU 消耗(因为磁盘 i/o 不消耗 CPU,但需要时间)。

另外,避免工作是最好的优化:

  • 如果要使用压缩纹理,只需压缩一次(第一次上传),然后下载压缩数据并将其缓存到磁盘。后续上传应将压缩数据直接从磁盘发送到 OpenGL,无需从 png-via-raw-to-gl 重新压缩。

流水线工作,尤其是 I/O 是加快速度的好方法,而且通常很容易(生产者-消费者并行):

  • 通过使用单独的线程来加载图像和创建纹理来管道上传。Qt 通过 QtConcurrent 库在这里提供了很好的支持,这意味着您不必自己处理线程。(不过,您将需要使用 QGLWidget::makeCurrent)

尽可能使用 CPU 上的所有可用内核:

  • 考虑使用多个线程将数据上传到 OpenGL。使用像素缓冲区对象,您可以获得指向纹理数据缓冲区的指针,然后使用 memcpy 将其上传。(memcpy 线程不需要激活上下文。)。
  • 纹理压缩是在 GL 驱动程序中的软件中完成的,因此跨内核并行上传也将有所帮助,但您可能必须创建多个 GL 上下文(共享数据)才能让 GL 驱动程序并行压缩。在你尝试这个之前,看看它是否是平行的应该不会太难。

此外,当您不需要时,请避免通过缓冲 API:s 流式传输数据:

  • 通过内存映射文件,可以非常有效地完成数据上传(无需缓冲,直接从磁盘到 GL),只需从映射缓冲区到纹理指针的 memcpy。
于 2012-04-29T20:10:21.087 回答
1

如果您确定瓶颈在于那段代码,您可能会做几件事:

  • 不要使用GL_COMPRESSED_RGBA,而只是简单地使用GL_RGBA
  • 找到驱动程序的最佳类型,并使用它(您需要分析 opengl 程序)
  • 在 png 文件中使用原始数据(避免压缩)
  • 将文件拆分成更小的文件
于 2012-04-29T19:58:16.050 回答