如何提高加载纹理的性能?
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
Asesh 是对的。起初,我持怀疑态度,但我做了一些研究,发现一篇较旧的文章指出,平均 PNG 纹理在硬盘驱动器上占用的内存比可比较的 DDS 纹理少。但是,PNG 纹理需要在 运行 时间进行转换,这比使用 DDS 纹理要慢。
我昨晚一直在寻找合适的转换工具,在测试了一些东西(比如 GIMP 的插件)之后,我使用 AMD 的 Compressonator 将我所有的 PNG 纹理转换为 DDS 纹理。新文件在我的硬盘上占用的内存比 PNG 文件更少(1.7 GB 而不是 2.1 GB)。
我在最初 post 中介绍的纹理加载方法仍然有效,而且速度稍快。但是,我决定根据我在网上找到的几个代码示例编写一个 DDS 导入程序。
结果:导入大型纹理仅需 1 毫秒而不是 103 毫秒。我认为你可以改进。 :-D
非常感谢你,Asesh!
我目前正在为我的游戏项目寻找性能优化。我的初始化过程的瓶颈是加载模型的纹理。加载和分配大纹理最多需要 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
Asesh 是对的。起初,我持怀疑态度,但我做了一些研究,发现一篇较旧的文章指出,平均 PNG 纹理在硬盘驱动器上占用的内存比可比较的 DDS 纹理少。但是,PNG 纹理需要在 运行 时间进行转换,这比使用 DDS 纹理要慢。
我昨晚一直在寻找合适的转换工具,在测试了一些东西(比如 GIMP 的插件)之后,我使用 AMD 的 Compressonator 将我所有的 PNG 纹理转换为 DDS 纹理。新文件在我的硬盘上占用的内存比 PNG 文件更少(1.7 GB 而不是 2.1 GB)。
我在最初 post 中介绍的纹理加载方法仍然有效,而且速度稍快。但是,我决定根据我在网上找到的几个代码示例编写一个 DDS 导入程序。
结果:导入大型纹理仅需 1 毫秒而不是 103 毫秒。我认为你可以改进。 :-D
非常感谢你,Asesh!