“阻断疗法” - 拯救 WPF 启动过程中发生设备热插拔导致触摸失效问题

“阻断疗法” - 拯救 WPF 启动过程中发生设备热插拔导致触摸失效问题

如果你在WPF程序启动过程中进行设备热插拔(例如,插入一个U盘,一个USB摄像头),那么你的WPF程序很有可能失去所有触摸消息响应,通过 Tablet.TabletDevices.Count 检查当前程序的挂靠触摸设备,发现为0。有趣的是,如果你将触摸线重新插拔后,程序恢复正常。所以,这是WPF的Bug,微软的锅。那么这个锅的根本原因是啥?有兴趣的可以调试 .net framework 源码,这里没有深究。

阅读更多
WPF 渲染小结

WPF 渲染小结

在上一篇文章D3DImage - 它能做啥、解决了什么问题、有哪些瓶颈、怎么最佳实践最后,提到DropShadowEffect严重影响到D3DImage的渲染性能问题,导致程序在渲染8分屏(8个远端视频)的时候,出现严重的性能下降,渲染卡顿。要知道,在使用原生窗口渲染方案渲染8分屏,CPU占用和内存占用也不过25%和~200Mb,稍差一点,使用D3DImage优化后方案渲染,CPU占用并没有出现多大的跳跃,大约在30%左右。即使是添加了DropShadowEffect的情况下,CPU占用和内存占用好像都没有多大变化;既然在CPU和内存占用都没有多大变化的情况下,WPF渲染卡顿,那肯定(可能吧)是“帧生成”时间过长的锅。

阅读更多
D3DImage - 它能做啥、解决了什么问题、有哪些瓶颈、怎么最佳实践

D3DImage - 它能做啥、解决了什么问题、有哪些瓶颈、怎么最佳实践

D3dImage,.Net Framework 3.5 之后,微软提供的一个全新的ImageSource对象,可以在WPF中很好的呈现DirectX内容;在此之前,你只能将DirectX内容直接渲染在Windows窗口之上,这必然引起令人头疼的AirSpace问题,为了在这些内容上面添加我们习以为常的WPF UI 元素,你只能使用Popup来承载这些内容,完全丧失WPF UI开发的灵活性,且有经验的WPF程序员都知道一个事实:WPF Popup就是一个深坑 - 你需要手动处理各种显示隐藏问题、因为其导致的焦点问题,显示层级问题以及最令人头疼的性能问题,特别是在4K屏幕下,因为我们都知道,Popup就是一个Window,为了解决Airspace问题而使用Popup来承载UI必定需要使其AllowTransparency=True,这就引起了另外一个问题,透明窗口占用内存与其面积成正相关,在4K屏幕下,你可能将整个程序大部分的内存占用贡献给了这些Popup UI。说了这么多,好像在诉控Popup有多么的垃圾(它的确如此,如果在做大量的UI容器时)。

年轻人,如果你觉得Airspace问题真的没有办法解决了,只能用Popup这种技术手段来规避了,那么听老人一句话,不要浪费时间在Popup上了,因为你在前期投入的时间来规避种种Popup UI导致的问题以及各种你意想不到的Bug,到最后总会碰到解决不了,完全不能规避的情况,从而导致整个Popup UI替换方案完全失败的情形。

阅读更多
FFmpeg 入门

FFmpeg 入门

废话少说,要解码一个视频帧,你需要这样做:

获得帧数据后,用SDL还是直接用D3d渲染,那就看你自己了。

D3DImage in WPF

D3DImage in WPF

在.Net Framework 3.5 SP1中,微软在WPF中提供了D3DImage对象,D3DImage是一个ImageSource,这可以让我们在WPF原生的D3D Surface上渲染Direct3D Surface,大大提高了WPF和DirectX内容的交互性。
在此之前,要想在WPF上渲染DirectX的内容,只能让DirectX直接渲染到窗口上,这样会造成不可避免的Airspace问题,因为DirectX内容要时刻刷新重绘,导致WPF窗口上的其他内容被覆盖,表现就是DirectX内容始终在窗口最顶层。
正如前面所说,D3DImage是一个ImageSource,在WPF中,这意味着,我们可以将一个3D场景变成一个Image对象的Source,或者构建一个ImageBrush,这意味这D3D Surface可以渲染到WPF中任意一个以Brush进行渲染的元素上,例如图片,文本前景色,元素背景色等等。
如下,就是一个典型的应用D3DImage的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (d3dimg.IsFrontBufferAvailable)
{
IntPtr pSurface = IntPtr.Zero;
pSurface = _view.GetBackBuffer();

if (pSurface != IntPtr.Zero)
{
d3dimg.Lock();
d3dimg.SetBackBuffer(D3DResourceType.IDirect3DSurface9,pSurface);
_view.Draw();
d3dimg.AddDirtyRect(new Int32Rect(0, 0, d3dimg.PixelWidth, d3dimg.PixelHeight));
d3dimg.Unlock();
}
}

只需要Direct3D内容渲染的Surface接口指针即可,如上面的pSurface。

Mandelbrot Set - 在复平面上绘制曼德博集合

曼德博集合(Mandelbrot set,或译为曼德布洛特复数集合)是一种在复平面上组成分形的点的集合,以数学家本华·曼德博的名字命名。曼德博集合与朱利亚集合有些相似的地方,例如使用相同的复二次多项式来进行迭代。(维基百科)

其中的迭代公式:


其中,c是任意复数。我们知道c可以表示为:c=x+y*i。根据复数的定义,i^2=-1。因此,我们通过将二维平面当作复平面,x是其中复数的实部R,y是复数的虚部Im。根据上面的额迭代公式,使用OpenCL对每个点进行同步的迭代,快速得到曼德博集合。
阅读更多
OpenCL with CLOO

OpenCL with CLOO

CLOO 是一个对 OpenCL 的 .Net 封装,可以让 .Net/Mono 程序充分使用 OpenCL 的优势,易用、开源。

今天用 OpenCL 中的 “Hello World” 程序 - 矩阵乘法,来简单介绍一下 OpenCL。

OpenCL 是一个开放的工业标准,既然是开放的,那么,所有厂商就可以提供自己的实现,例如英特尔,英伟达等等。也正因为如此,也导致在同一台机器上可能存在多个支持不同版本的硬件。例如,英伟达的GPU到现在也才支持 OpenCL 1.2 版本,但是OpenCL都已经出到2.x版本了。

我们可以查看当前设备中,有哪些厂商提供了 OpenCL 的支持,以及运算平台是啥。例如,在 Surface Book (with Nvidia GPU) 上,我们调用以下代码看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//获取所有平台
var platforms = ComputePlatform.Platforms;

foreach(var platform in platforms)
{
Console.WriteLine($"{platform.Name},{platform.Version}");

//获取该平台下的计算设备
var devices = platform.QueryDevices();
foreach(var device in devices)
{
Console.WriteLine($" Device:{device.Name}");
}
}
阅读更多