代码之家  ›  专栏  ›  技术社区  ›  Daniel Wolf deepee1

BitmapSource的WPF渲染性能

  •  7
  • Daniel Wolf deepee1  · 技术社区  · 17 年前

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

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

    任何见解将不胜感激!

    提前谢谢

    丹尼尔

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

    2 回复  |  直到 17 年前
        1
  •  3
  •   RandomEngy    17 年前

    不仅仅是大量的图像。只有一个大图像就足以在加载之前保持渲染,当图像尺寸开始增加到数千时,这一点非常明显。

    我确实同意您的说法,这可能是渲染线程:我做了一个测试,UI线程仍然很高兴地发送消息,因为在尝试显示完全预缓存的BitmapImage时出现了渲染延迟。

    它一定是在对图像进行某种转换或准备,就像你推测的那样。我曾试图在我的应用程序中通过“渲染”来缓解这种情况,但隐藏了图像,然后在需要显示时将其显示出来。但是,这并不理想,因为渲染仍然会冻结。

    (编辑)

    后续行动:在讨论MS WPF别名后,我找到了导致延迟的原因。在我的Server2008机器上,它是旧的视频驱动程序(不支持新的WDDM驱动程序型号)和图像大小调整延迟的组合。

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

        2
  •  0
  •   RandomNickName42    16 年前

    也试试这些;

    /* 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