数周以来,我一直在为 C# 天搜索和测试不同类型的渲染库。到目前为止,我还没有找到一个在多窗口渲染设置上运行良好的库。要求是能够在 12 个以上的显示器设置(财务图表)上运行程序,而不会在快速计算机上出现延迟。每个窗口需要每秒更新多次。虽然这样做 CPU 需要执行大量密集且时间紧迫的任务,因此必须将一些负担转移到 GPU 上。这就是硬件渲染介入的地方,换句话说就是 DirectX 或 OpenGL。
我已经尝试过使用 Windows 窗体的 GDI+,并认为它对于我的需求来说太慢了。我已经通过 OpenTK(在 Windows 窗体控件上)尝试了 OpenGL,这似乎相当快(我仍然要在其上运行一些测试),但很难正常工作(很难找到/编写好的文本渲染库)。最近我通过 SharpDX 在 Windows 窗体上尝试了 DirectX9、DirectX10 和 Direct2D。我为每个窗口尝试了一个单独的设备,并尝试了一个设备/多个交换链方法。所有这些都导致在多个窗口上的性能非常差。例如,如果我将目标 FPS 设置为 20 并在不同的显示器上打开 4 个全屏窗口,整个操作系统就会开始严重滞后。渲染只是将屏幕清除为黑色,不渲染图元。这个测试的 CPU 使用率约为 0%,GPU 使用率约为 10%,我不知道 不明白这里的瓶颈是什么?我的开发计算机非常快,i7 2700k,AMD HD7900,16GB 内存,所以测试肯定应该在这台上运行。
相比之下,我在 C++/Win32 API 一个设备/多个交换链上做了一些 DirectX9 测试,我可以打开遍布 4 显示器工作区的 100 个窗口(3D 茶壶在上面旋转),并且仍然拥有完全负责的操作系统(fps 是当然,渲染窗口非常糟糕地下降到大约 5,这是我期望运行 100 个同时渲染的结果)。
有谁知道在 C# 上进行多窗口渲染的任何好方法,还是我被迫用 C++ 重写我的程序以获得该性能(主要痛苦)?我想在我走 C++ 路线之前,我要再给 OpenGL 一个机会。我会在这里报告任何发现。
测试方法供参考:
对于 C# DirectX 单设备多交换链测试,我使用了这个出色答案中的方法: Display Different images per monitor directX 10
Direct3D10 版本:
我像这样创建了 d3d10device 和 DXGIFactory:
D3DDev = new SharpDX.Direct3D10.Device(SharpDX.Direct3D10.DriverType.Hardware,
SharpDX.Direct3D10.DeviceCreationFlags.None);
DXGIFac = new SharpDX.DXGI.Factory();
然后像这样初始化渲染窗口:
var scd = new SwapChainDescription();
scd.BufferCount = 1;
scd.ModeDescription = new ModeDescription(control.Width, control.Height,
new Rational(60, 1), Format.R8G8B8A8_UNorm);
scd.IsWindowed = true;
scd.OutputHandle = control.Handle;
scd.SampleDescription = new SampleDescription(1, 0);
scd.SwapEffect = SwapEffect.Discard;
scd.Usage = Usage.RenderTargetOutput;
SC = new SwapChain(Parent.DXGIFac, Parent.D3DDev, scd);
var backBuffer = Texture2D.FromSwapChain<Texture2D>(SC, 0);
_rt = new RenderTargetView(Parent.D3DDev, backBuffer);
每次渲染迭代执行的绘图命令很简单:
Parent.D3DDev.ClearRenderTargetView(_rt, new Color4(0, 0, 0, 0));
SC.Present(0, SharpDX.DXGI.PresentFlags.None);
DirectX9 版本非常相似:
设备初始化:
PresentParameters par = new PresentParameters();
par.PresentationInterval = PresentInterval.Immediate;
par.Windowed = true;
par.SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard;
par.PresentationInterval = PresentInterval.Immediate;
par.AutoDepthStencilFormat = SharpDX.Direct3D9.Format.D16;
par.EnableAutoDepthStencil = true;
par.BackBufferFormat = SharpDX.Direct3D9.Format.X8R8G8B8;
// firsthandle is the handle of first rendering window
D3DDev = new SharpDX.Direct3D9.Device(new Direct3D(), 0, DeviceType.Hardware, firsthandle,
CreateFlags.SoftwareVertexProcessing, par);
渲染窗口初始化:
if (parent.D3DDev.SwapChainCount == 0)
{
SC = parent.D3DDev.GetSwapChain(0);
}
else
{
PresentParameters pp = new PresentParameters();
pp.Windowed = true;
pp.SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard;
pp.BackBufferFormat = SharpDX.Direct3D9.Format.X8R8G8B8;
pp.EnableAutoDepthStencil = true;
pp.AutoDepthStencilFormat = SharpDX.Direct3D9.Format.D16;
pp.PresentationInterval = PresentInterval.Immediate;
SC = new SharpDX.Direct3D9.SwapChain(parent.D3DDev, pp);
}
绘制循环代码:
SharpDX.Direct3D9.Surface bb = SC.GetBackBuffer(0);
Parent.D3DDev.SetRenderTarget(0, bb);
Parent.D3DDev.Clear(ClearFlags.Target, Color.Black, 1f, 0);
SC.Present(Present.None, new SharpDX.Rectangle(), new SharpDX.Rectangle(), HWND);
bb.Dispose();
具有多个交换链和一个设备代码的 C++ DirectX9/Win32 API 测试如下:
[C++] DirectX9 多窗口测试 - Pastebin.com
这是 Kevin Harris 的漂亮示例代码的修改版本。
编辑:
为了清楚起见,我的主要问题不是在进行多窗口渲染时这里的 fps 低,而是对所有操作系统功能(窗口动画、拖放滚动等)造成的一般延迟。