2009-04-30 79 views
7

我创建了一个WPF控件(自FrameworkElement继承),显示一个平铺的图形可以平移。每个瓷砖在24bpp处都是256x256像素。我重写了OnRender。在那里,我加载了任何新的图块(如BitmapFrame),然后使用drawingContext.DrawImage绘制所有可见的图块。WPF渲染性能的BitmapSource

现在,每当有超过每循环渲染了一把新的瓷砖,帧率从60fps到零下降约一秒钟。这不是由加载图像(以毫秒为单位)或DrawImage(根本不需要任何时间,因为它只是填充一些中间渲染数据结构)引起的。

我的猜测是,渲染线程本身扼流圈一旦进入新的BitmapSource实例的大量(约20),(也就是那些它尚未高速缓存)。要么花费很多时间将它们转换为内部DirectX兼容格式,要么它可能是缓存问题。它不能用完视频RAM;穿孔器在60MB以下显示峰值,我有256MB。此外,Perforator说,所有渲染目标都是硬件加速的,所以也不能这样做。

任何见解将不胜感激!

在此先感谢

丹尼尔

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

回答

3

这不只是用大量的图像。只有一张大图像足以容纳渲染,直到它已经被加载,而当图像尺寸开始以数千计起始时,这可能是相当明显的。

我确实同意你可能是渲染线程:我做了一个测试,UI线程仍然很乐意调度消息,而这个渲染延迟发生在试图显示一个完全预缓存的BitmapImage的地方。

它必须在图像上进行某种转换或准备,就像你在猜测一样。我试图通过“渲染”来缓解这种情况,但隐藏了图像,然后在需要展示时显示它。然而,这并不理想,因为无论如何渲染死机都会发生。

(编辑)

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

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

0

也试试这些;

/* 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上的Brush。如果您正在动画或动态添加新动画,则可以生成画笔,然后在手动操作时将它们应用到对象上,如果可以,请务必将它们冻结。此外,VisualBitmapScalingMode是任何Visual的属性。