使用 BitmapSource 的 WPF 渲染性能

标签 wpf performance bitmap rendering

我创建了一个 WPF 控件(从 FrameworkElement 继承),它显示可以平移的平铺图形。每个图块为 256x256 像素,24bpp。我已经覆盖了 OnRender。在那里,我加载任何新图块(作为 BitmapFrame),然后使用drawingContext.DrawImage 绘制所有可见图块。

现在,只要每个渲染周期有多个新图块,帧速率就会从 60fps 下降到零大约一秒钟。这不是由加载图像(需要几毫秒)引起的,也不是由 DrawImage 引起的(它根本不需要时间,因为它只是填充了一些中间渲染数据结构)。

我的猜测是,渲染线程本身在获得大量(约 20 个)新 BitmapSource 实例(即尚未缓存的实例)时会窒息。要么花费大量时间将它们转换为某种内部 DirectX 兼容格式,要么可能是缓存问题。它不能用完视频 RAM; Perforator 显示峰值低于 60MB,我有 256MB。此外,Perforator 表示所有渲染目标都是硬件加速的,所以也不可能是这样。

任何见解将不胜感激!

提前致谢

丹尼尔

@RandomEngy:
BitmapScalingMode.LowQuality 稍微减少了问题,但并没有摆脱它。我已经以预期的分辨率加载图块。它不能是最新的图形驱动程序(Nvidia)。
得知缩放需要这么多时间,我有点惊讶。按照我的理解,位图(无论其大小)只是作为 Direct3D 纹理加载,然后进行硬件缩放。事实上,一旦位图第一次被渲染,我就可以改变它的旋转和缩放,而无需进一步卡住。

最佳答案

这不仅仅是大量图像。只需一张大图像就足以在加载之前阻止渲染,当您的图像尺寸开始增加数千时,这一点会非常明显。

我同意你的看法,它可能是渲染线程:我做了一个测试,当这个渲染延迟发生时,UI 线程仍然很高兴地调度消息,因为试图显示一个完全预缓存的 BitmapImage。

它必须对图像进行某种转换或准备,就像您推测的那样。我试图通过“渲染”但隐藏图像,然后在我需要显示它时显示它来缓解我的应用程序中的这种情况。然而,这并不理想,因为无论如何都会发生渲染卡住。

(编辑)

一些后续行动:在讨论了 MS WPF 别名之后,我发现了导致延迟的原因。在我的 Server 2008 机器上,它是不支持新 WDDM 驱动程序模型的旧视频驱动程序和调整图像大小的延迟的组合。

如果源图像大小与显示大小不同,则会在图像显示之前延迟渲染线程。默认情况下,图像设置为最高质量,但您可以通过调用 RenderOptions.SetBitmapScalingMode(uiImage, BitmapScalingMode.LowQuality); 更改渲染的缩放选项。 .一旦我这样做了,显示图像之前的神秘卡住就消失了。另一种方法是,如果您不喜欢缩放质量下降,则加载 BitmapImage,其 DecodePixelWidth/Height 等于将显示的大小。然后,如果您在后台线程上加载 BitmapImage,则显示它应该没有延迟。

关于使用 BitmapSource 的 WPF 渲染性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/806083/

相关文章:

WPF ListView 设置 SelectedItem

Java:将 N 个二维数组附加到单个二维数组中的有效方法

java - javac 是否根据底层操作系统执行任何字节码级别的优化?

java - 当显示 AlertDialog 时,自定义 View onMeasure(...) 宽度和高度为 0

c# - WPF UserControl - Usercontrol DataGrid 的 SelectedItem 绑定(bind)到 UserControl 外的 DataGrid 的 ItemSource

wpf - 动画网格背景颜色

java - 任何与时间戳一起使用的高性能 Java 库?

c++ - OpenGL 渲染与原始图像颜色不同的纹理?

android - 位图压缩 PNG -> JPEG,在 Android 中反之亦然

c# - WPF框架在后台线程中使用Dispatcher.CurrentDispatcher,导致内存泄漏