我有一个控件,它使用D3DImage来托管SharpDX DirectX9表面,并允许用于平移,缩放和与世界对象交互,结果非常棒。当窗口最小化并重新启动或用户锁定然后解锁屏幕时,性能实际上是一个惊人的一致60fps除外。当窗口恢复焦点时,fps下降到大约25-30fps。我可以通过卸载并将控件加载回其容器然后BOOM,60fps来“修复”该问题。
我使用设置为10ms的DispatcherTimer调用主渲染函数。之前,我使用的是CompositionTarget.Rendering事件,但性能不如使用DispatcherTimer。我相当肯定我正确处理丢失的资源。有关每秒丢失帧数的想法吗?
编辑:I am having this same exact problem。不幸的是,进行自动设备重置并不能解决问题,但如果我有一个执行相同重置方法的按钮,那么我的fps会恢复正常。
答案 0 :(得分:2)
锁定/解锁屏幕会导致设备丢失。但你可能知道这一点。
无论如何我也在WPF中使用D3DImage。当我致电
时,我的表现问题就此结束了D3DImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero)
每个设备上的丢失了。我曾经在设备丢失之后遇到响应问题,直到我意识到WPF仍然持有对纹理的引用。当然,当你有更新的纹理时,你应该稍后重新设置后备缓冲。
虽然目前还不清楚幕后到底出了什么问题,但很明显D3DImage会对你的纹理进行引用,这可能会导致设备丢失时成功恢复。就我而言,我们根本没有更新。
对于这个节点的答案很抱歉...但是在真正的D3DImage专家进入房间之前,它总比没有好。
P.S。我正在使用SlimDX,但我认为这并不重要...尽管如此,我知道SharpDX是SlimDX的一个分支。
答案 1 :(得分:0)
SetBackBuffer
有一个过载需要额外的Boolean
标志:
D3DImage.SetBackBuffer(D3DResourceType, IntPtr, Boolean)
当您调用 SetBackBuffer (D3DResourceType,IntPtr)重载或调用SetBackBuffer(D3DResourceType,IntPtr,Boolean)重载并将 enableSoftwareFallback 参数设置为false时,当前缓冲区变得不可用且没有显示任何内容时,[WPF]渲染系统释放对后缓冲区的引用。
我也不是专家,但我猜这就是发生的事情;因为您没有将该标志设置为'true',所以WPF会在退出锁定时立即调用Release()
对D3D表面的最后一次COM引用计数。这似乎要求您保留自己的额外引用计数。
首先,我注意到,即使在从WPF锁定/解锁往返中“返回”你的“使用过的”表面后,你仍然需要不释放,直到你的 next 表面取代它(即成功调用 d3dimg.SetBackBuffer )。否则,当在屏幕上拖动WPF窗口时,您将会闪烁。鉴于这是我发现用于检测WPF何时真正使用你的缓冲区的唯一可靠方法,WPF关注AddRef'或释放它似乎毫无意义。
D3DImage
通常令人困惑的是,运行WPF的IDirect3DDevice9
与生成表面的IDirect3DDevice9
实际上没有关联,而是作为后台缓冲区...对于WPF。整个Lock/Unlock
业务大概是为了WPF的利益,与你自己(可能可以锁定?)IDirect3DSurface9
rendertarget的生存无关。
小心!
如果使用D3DImage.TryLock
,请注意它,嗯...我们应该说,非常规的语义:你必须致电{ {1}}即使在Unlock
返回 false 的情况下也是如此。有关详细信息,请参阅https://stackoverflow.com/a/39581727/147511。