7

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

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

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

任何见解将不胜感激!

提前致谢

丹尼尔

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

4

2 回答 2

3

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

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

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

(编辑)

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

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

于 2009-04-30T23:23:51.383 回答
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 上的画笔。如果您正在为它们设置动画或动态添加新的,您可以生成画笔,然后在手动操作时将它们应用于您的对象,如果可以,请务必冻结它们。此外,VisualBitmapScalingMode 是任何 Visual 的属性。

于 2010-02-26T14:50:17.450 回答