如何提高加载纹理的性能?

How to improve the performance of loading textures?

我目前正在为我的游戏项目寻找性​​能优化。我的初始化过程的瓶颈是加载模型的纹理。加载和分配大纹理最多需要 100 毫秒。这是一个问题,因为我有很多。我分析了我的代码,发现大部分时间(大约 96%)都花在 CopyPixels 的调用上(见下文)。

我在下面附加了用于导入所有纹理的函数。此功能非常有用,它基于官方 SharpDX-samples-master 示例代码。首先,我从我的自定义文件格式加载图像字节(对于大纹理大约需要 2 毫秒)。然后,我创建格式转换器并使用它将像素复制到数据流。但是,复制像素非常慢。

有没有更快的方法来达到同样的效果?

public static Resources.Texture ImportTexture(Resources.AResourceManager resourceManager, string resourcePackFileName, int bytePosition, out string resourceItemName)
{
    // Load image bytes from file.
    FileReader fileReader = new FileReader();
    DataTypes.Content.ResourceItem resourceItem = fileReader.ImportTextureFromCollection(resourcePackFileName, bytePosition);
    resourceItemName = resourceItem.Name;

    // Create texture.
    Resources.Texture tex = null;
    using (SharpDX.WIC.BitmapDecoder bitmapDecoder = new SharpDX.WIC.BitmapDecoder(resourceManager.ImagingFactory, new MemoryStream(resourceItem.Data, false), SharpDX.WIC.DecodeOptions.CacheOnDemand))
    {
        using (SharpDX.WIC.FormatConverter formatConverter = new SharpDX.WIC.FormatConverter(resourceManager.ImagingFactory))
        {
            formatConverter.Initialize(bitmapDecoder.GetFrame(0), SharpDX.WIC.PixelFormat.Format32bppPRGBA, SharpDX.WIC.BitmapDitherType.None, null, 0.0, SharpDX.WIC.BitmapPaletteType.Custom);

            SharpDX.DataStream dataStream = new SharpDX.DataStream(formatConverter.Size.Height * formatConverter.Size.Width * 4, true, true);

            // This takes most of the time!
            formatConverter.CopyPixels(formatConverter.Size.Width * 4, dataStream);

            // Creating texture data structure.
            tex = new Resources.Texture(formatConverter.Size.Width, formatConverter.Size.Height, formatConverter.Size.Width * 4)
            {
                DataStream = dataStream
            };
        }
    }

    return tex;
}

Looks like you are using bitmaps. Have you considered using DDS files instead? It supports both compressed and uncompressed formats – Asesh

A​​sesh 是对的。起初,我持怀疑态度,但我做了一些研究,发现一篇较旧的文章指出,平均 PNG 纹理在硬盘驱动器上占用的内存比可比较的 DDS 纹理少。但是,PNG 纹理需要在 运行 时间进行转换,这比使用 DDS 纹理要慢。

我昨晚一直在寻找合适的转换工具,在测试了一些东西(比如 GIMP 的插件)之后,我使用 AMD 的 Compressonator 将我所有的 PNG 纹理转换为 DDS 纹理。新文件在我的硬盘上占用的内存比 PNG 文件更少(1.7 GB 而不是 2.1 GB)。

我在最初 post 中介绍的纹理加载方法仍然有效,而且速度稍快。但是,我决定根据我在网上找到的几个代码示例编写一个 DDS 导入程序。

结果:导入大型纹理仅需 1 毫秒而不是 103 毫秒。我认为你可以改进。 :-D

非常感谢你,Asesh!