使用 BitmapSource 的 WPF 渲染性能

2024-02-12

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

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

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

任何见解将不胜感激!

提前致谢

Daniel

@RandomEngy:
BitmapScalingMode.LowQuality 稍微减少了问题,但并没有消除它。我已经以预期的分辨率加载图块。而且不可能是显卡驱动程序,它是最新的(Nvidia)。
我有点惊讶地发现扩展需要这么多时间。按照我的理解,位图(无论其大小)只是作为 Direct3D 纹理加载,然后进行硬件缩放。事实上,一旦位图首次渲染,我就可以更改其旋转和比例,而不会进一步冻结。


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

我同意你的观点,这可能是渲染线程的问题:我做了一个测试,UI 线程仍然愉快地调度消息,而渲染延迟是由于尝试显示完全预缓存的 BitmapImage 而发生的。

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

(Edit)

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 BitmapSource 的 WPF 渲染性能 的相关文章

随机推荐