缓慢的纹理加载

时间:2012-04-29 19:22:02

标签: c++ qt opengl

我有大约六个文件,每个文件250 KB到500 KB。这些文件中的每一个都有多个QImages;每个文件大约有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采用GLformat格式。

2 个答案:

答案 0 :(得分:2)

确保您确定自己的数据:

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

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

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

流水线工作,特别是I / O是加快速度的好方法,通常很简单(生产者 - 消费者并行):

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

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

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

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

  • 通过内存映射文件可以非常有效地完成数据上传(无缓冲,直接从磁盘到GL),只是从映射缓冲区到纹理指针的memcpy。

答案 1 :(得分:1)

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

  • 不要使用GL_COMPRESSED_RGBA,而只需使用GL_RGBA
  • 找到驱动程序的最佳类型,并使用它(您需要配置opengl程序)
  • 在png文件中使用原始数据(避免压缩)
  • 将文件拆分为较小的文件