【问题标题】:WPF render performance with BitmapSourceWPF 使用 BitmapSource 渲染性能
【发布时间】:2010-10-22 19:23:51
【问题描述】:

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

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

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

任何见解都将不胜感激!

提前致谢

丹尼尔

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

【问题讨论】:

    标签: wpf performance bitmap rendering


    【解决方案1】:

    也试试这些;

    /* ivis is declared in XAML <Image x:Name="iVis" UseLayoutRounding="True" SnapsToDevicePixels="True" /> */
    
    iVis.Stretch = Stretch.None;
    RenderOptions.SetBitmapScalingMode(iVis, BitmapScalingMode.NearestNeighbor);
    RenderOptions.SetEdgeMode(iVis, EdgeMode.Aliased);
    VisualBitmapScalingMode = BitmapScalingMode.NearestNeighbor;
    iVis.Source = **** your bitmap source ****
    

    我在使用大量“A”通道颜色时遇到了一些性能问题,等到图像渲染后缩放它对我来说效果更好。

    另外,正如您所说,您使用平铺图形?

    您通常会使用TileBrush 来简单地设置为FrameworkElement 上的画笔。如果您正在为它们设置动画或动态添加新的,您可以生成画笔,然后在手动操作时将它们应用于您的对象,如果可以,请务必冻结它们。此外,VisualBitmapScalingMode 是任何 Visual 的属性。

    【讨论】:

      【解决方案2】:

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

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

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

      (编辑)

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-08
        • 1970-01-01
        相关资源
        最近更新 更多